mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-15 03:32:21 +03:00
Compare commits
38 Commits
dependabot
...
fix/radar-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2d2598a0d | ||
|
|
e05ac345da | ||
|
|
dfcf6086a2 | ||
|
|
6233ca6642 | ||
|
|
45a4358b61 | ||
|
|
6cad6314b5 | ||
|
|
7bb3bc7e32 | ||
|
|
8d1a59771a | ||
|
|
bac3b4eb37 | ||
|
|
abd4df63dc | ||
|
|
7580feb1bf | ||
|
|
be04c7aecb | ||
|
|
834e53b95b | ||
|
|
da148eddb7 | ||
|
|
3784c35b29 | ||
|
|
74f146a7d4 | ||
|
|
2256057f4a | ||
|
|
b314b1b112 | ||
|
|
b334d2d05a | ||
|
|
baa68bfc06 | ||
|
|
d0aff219f5 | ||
|
|
6f48ac4bfe | ||
|
|
e80ac605bc | ||
|
|
1a55b20963 | ||
|
|
a45076fa2a | ||
|
|
7859c843de | ||
|
|
b8a6557449 | ||
|
|
fa7bf4df7b | ||
|
|
f806740a2f | ||
|
|
e2e589c79c | ||
|
|
b11d55332b | ||
|
|
ee6695acad | ||
|
|
b6bba896b3 | ||
|
|
ea95cc2937 | ||
|
|
a801abc8e9 | ||
|
|
86caa94baa | ||
|
|
2ebab9c686 | ||
|
|
340edbc997 |
27
.env.example
27
.env.example
@@ -2040,6 +2040,22 @@ APP_LOG_TO_FILE=true
|
|||||||
# ALIBABA_CODING_PLAN_HOST=
|
# ALIBABA_CODING_PLAN_HOST=
|
||||||
# ALIBABA_CODING_PLAN_QUOTA_URL=
|
# ALIBABA_CODING_PLAN_QUOTA_URL=
|
||||||
|
|
||||||
|
# ── Qwen Cloud / Model Studio personal Token Plan quota ──
|
||||||
|
# Cookie-authenticated console-gateway fetcher (issue #9603). Used by:
|
||||||
|
# open-sse/services/qwenTokenPlanQuotaFetcher.ts. Prefer the per-connection
|
||||||
|
# Dashboard fields (qwenCloudCookie / qwenCloudSecToken) — these env vars are
|
||||||
|
# global fallbacks. Cookie/sec_token are SENSITIVE session credentials.
|
||||||
|
# Getting the cookie: log in to home.qwencloud.com > Billing > Subscription,
|
||||||
|
# press F12 > Network, reload, filter by api.json, click any request to
|
||||||
|
# cs-data.qwencloud.com and copy the WHOLE Cookie value from Request Headers
|
||||||
|
# (it contains login_qwencloud_ticket). Paste it on ONE line — the value may
|
||||||
|
# contain '=' and ';'. It expires with the browser session; re-paste it when
|
||||||
|
# the dashboard reports an expired session.
|
||||||
|
# QWEN_CLOUD_COOKIE=
|
||||||
|
# QWEN_CLOUD_SEC_TOKEN=
|
||||||
|
# QWEN_TOKEN_PLAN_HOST=
|
||||||
|
# QWEN_TOKEN_PLAN_DASHBOARD_URL=
|
||||||
|
|
||||||
# ── Alibaba Model Studio free-tier quota sync ──
|
# ── Alibaba Model Studio free-tier quota sync ──
|
||||||
# Console front-end path overrides for the free-tier quota fetcher. Used by:
|
# Console front-end path overrides for the free-tier quota fetcher. Used by:
|
||||||
# open-sse/services/alibabaFreeTierQuotaFetcher.ts. When unset, the fetcher
|
# open-sse/services/alibabaFreeTierQuotaFetcher.ts. When unset, the fetcher
|
||||||
@@ -2636,9 +2652,9 @@ QUOTA_STORE_DRIVER=sqlite
|
|||||||
# ═══════════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
# Optional add-on (feature flag RADAR_ENABLED, default off — see feature flag
|
# 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
|
# settings, not an env var) that overlays a signed, freshly-curated free-model
|
||||||
# catalog on top of the release baseline. All four variables below are optional
|
# catalog on top of the release baseline. The first four variables below are
|
||||||
# and only needed to point the client at a self-hosted/forked feed or
|
# optional overrides for a self-hosted/forked feed or supporter-key flow. The
|
||||||
# supporter-key flow instead of the default OmniRoute Radar service. Used by:
|
# fifth is an optional, default-free link to the owner's private operations panel. Used by:
|
||||||
# src/lib/radar/sync.ts, src/lib/radar/pinnedKeys.ts, src/lib/radar/links.ts.
|
# 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
|
# Base URL of the Radar feed service. Overrides the built-in default so forks
|
||||||
@@ -2659,6 +2675,11 @@ QUOTA_STORE_DRIVER=sqlite
|
|||||||
# page). No pricing/value lives in this repo — only the link.
|
# page). No pricing/value lives in this repo — only the link.
|
||||||
# RADAR_SUPPORTER_PLANS_URL=https://radar.omniroute.online/planos
|
# 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
|
# 27. RELEASE v3.8.50 ADDITIONS
|
||||||
# ═══════════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|||||||
2
.github/pull_request_template.md
vendored
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`
|
- [ ] `npm run lint`
|
||||||
- [ ] Reconciled with the current active release base; focused checks rerun afterward
|
- [ ] Reconciled with the current active release base; focused checks rerun afterward
|
||||||
- [ ] Production-code changes include a new or updated automated test in this PR
|
- [ ] Production-code changes include a new or updated automated test in this PR
|
||||||
- [ ] SonarQube PR analysis is green or any remaining issues are explicitly documented below
|
- SonarQube is temporarily opt-in while the private project has no quota; it is not a PR gate.
|
||||||
|
|
||||||
## Tests Added Or Updated
|
## Tests Added Or Updated
|
||||||
|
|
||||||
|
|||||||
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@@ -998,7 +998,10 @@ jobs:
|
|||||||
name: SonarQube
|
name: SonarQube
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: test-coverage
|
needs: test-coverage
|
||||||
if: ${{ !cancelled() && needs.test-coverage.result == 'success' }}
|
# 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' }}
|
||||||
env:
|
env:
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
|
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
|
||||||
@@ -1397,7 +1400,7 @@ jobs:
|
|||||||
echo "| i18n UI Coverage | $(status '${{ needs.i18n-ui-coverage.result }}') |" >> "$GITHUB_STEP_SUMMARY"
|
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 "| 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 "| PR Test Policy | $(status '${{ needs.pr-test-policy.result }}') |" >> "$GITHUB_STEP_SUMMARY"
|
||||||
echo "| SonarQube | $(status '${{ needs.sonarqube.result }}') |" >> "$GITHUB_STEP_SUMMARY"
|
echo "| SonarQube (opt-in; disabled without SONARQUBE_ENABLED=true) | $(status '${{ needs.sonarqube.result }}') |" >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
|
||||||
echo "" >> "$GITHUB_STEP_SUMMARY"
|
echo "" >> "$GITHUB_STEP_SUMMARY"
|
||||||
echo "## 🏗️ Build" >> "$GITHUB_STEP_SUMMARY"
|
echo "## 🏗️ Build" >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
|||||||
2
.github/workflows/docker-publish.yml
vendored
2
.github/workflows/docker-publish.yml
vendored
@@ -372,7 +372,7 @@ jobs:
|
|||||||
- name: Upload Trivy SARIF to Security tab
|
- name: Upload Trivy SARIF to Security tab
|
||||||
if: needs.prepare.outputs.version != 'main'
|
if: needs.prepare.outputs.version != 'main'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
uses: github/codeql-action/upload-sarif@v4.37.6
|
uses: github/codeql-action/upload-sarif@v4.37.4
|
||||||
with:
|
with:
|
||||||
sarif_file: trivy-results.sarif
|
sarif_file: trivy-results.sarif
|
||||||
category: trivy-image
|
category: trivy-image
|
||||||
|
|||||||
46
.github/workflows/quality.yml
vendored
46
.github/workflows/quality.yml
vendored
@@ -60,13 +60,49 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
name: Build (advisory)
|
name: Build (advisory)
|
||||||
needs: changes
|
needs: changes
|
||||||
if: ${{ github.event_name != 'pull_request' || ((github.event.pull_request.draft == false || startsWith(github.head_ref, 'mergify/merge-queue/')) && needs.changes.outputs.code == 'true') }}
|
# FORK PRs ONLY. build.yml's `Fast Production Build` triggers on `push: branches: ["**"]`
|
||||||
# Dynamic runner — same fork-safe rule as ci.yml / fast-gates.
|
# and runs `build:release` — a superset of this job — so for an own-origin branch this job
|
||||||
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' }}
|
# 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
|
||||||
# #7307: advisory for the first week of release-PR runs; remove
|
# #7307: advisory for the first week of release-PR runs; remove
|
||||||
# continue-on-error after the production-build signal is stable.
|
# continue-on-error after the production-build signal is stable.
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
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
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
@@ -79,6 +115,10 @@ jobs:
|
|||||||
- run: npm run build
|
- run: npm run build
|
||||||
env:
|
env:
|
||||||
OMNIROUTE_USE_TURBOPACK: "1"
|
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
|
# No artifact upload here: the PR-to-release quality workflow has no
|
||||||
# downstream package/e2e jobs that consume the Next.js build output.
|
# downstream package/e2e jobs that consume the Next.js build output.
|
||||||
|
|
||||||
|
|||||||
30
AGENTS.md
30
AGENTS.md
@@ -48,20 +48,20 @@ Repository map and Reference Documentation sections below.
|
|||||||
|
|
||||||
**OmniRoute** — unified AI proxy/router. One endpoint, 339 LLM providers, auto-fallback.
|
**OmniRoute** — unified AI proxy/router. One endpoint, 339 LLM providers, auto-fallback.
|
||||||
|
|
||||||
| Layer | Location | Purpose |
|
| Layer | Location | Purpose |
|
||||||
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| API Routes | `src/app/api/v1/` | Next.js App Router — entry points |
|
| API Routes | `src/app/api/v1/` | Next.js App Router — entry points |
|
||||||
| Handlers | `open-sse/handlers/` | Request processing (chat, embeddings, etc) |
|
| Handlers | `open-sse/handlers/` | Request processing (chat, embeddings, etc) |
|
||||||
| Executors | `open-sse/executors/` | Provider-specific HTTP dispatch |
|
| Executors | `open-sse/executors/` | Provider-specific HTTP dispatch |
|
||||||
| Translators | `open-sse/translator/` | Format conversion (OpenAI↔Claude↔Gemini) |
|
| Translators | `open-sse/translator/` | Format conversion (OpenAI↔Claude↔Gemini) |
|
||||||
| Transformer | `open-sse/transformer/` | Responses API ↔ Chat Completions |
|
| Transformer | `open-sse/transformer/` | Responses API ↔ Chat Completions |
|
||||||
| Services | `open-sse/services/` | Combo routing, rate limits, caching, etc |
|
| Services | `open-sse/services/` | Combo routing, rate limits, caching, etc |
|
||||||
| Database | `src/lib/db/` | SQLite domain modules (145 migrations) |
|
| Database | `src/lib/db/` | SQLite domain modules (148 migrations) |
|
||||||
| Domain/Policy | `src/domain/` | Policy engine, cost rules, fallback logic |
|
| 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 |
|
| 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 |
|
| A2A Server | `src/lib/a2a/` | JSON-RPC 2.0 agent protocol |
|
||||||
| Skills | `src/lib/skills/` | Extensible skill framework |
|
| Skills | `src/lib/skills/` | Extensible skill framework |
|
||||||
| Memory | `src/lib/memory/` | Persistent conversational memory |
|
| 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).
|
Monorepo: `src/` (Next.js 16 app), `open-sse/` (streaming engine workspace), `electron/` (desktop app), `tests/`, `bin/` (CLI entry point).
|
||||||
|
|
||||||
@@ -679,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
|
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
|
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
|
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
|
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
|
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.
|
`check:tracked-artifacts` (pre-commit + CI) bloqueia `_tasks` rastreado em qualquer forma.
|
||||||
|
|||||||
29
README.md
29
README.md
@@ -210,7 +210,7 @@ curl http://localhost:20128/v1/chat/completions \
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<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)."/>
|
<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 109 tools, A2A, memory, guardrails, evals — 25,000+ tests)."/>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
@@ -461,7 +461,7 @@ All **19** strategies — mix & match per combo step:
|
|||||||
|
|
||||||
</div>
|
</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: 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."/>
|
<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 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."/>
|
||||||
|
|
||||||
<sub>📊 Full methodology & per-feature detail vs 9router, OpenRouter, CLIProxyAPI & LiteLLM → [`docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md`](docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md)</sub>
|
<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,6 +513,25 @@ Pix copia-e-cola:
|
|||||||
|
|
||||||
<br/>
|
<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">
|
<div align="center">
|
||||||
|
|
||||||
## ✨ What's New
|
## ✨ What's New
|
||||||
@@ -748,7 +767,7 @@ Expose OmniRoute over **MCP**, **A2A**, a **REST API**, **webhooks** or a **remo
|
|||||||
<table>
|
<table>
|
||||||
<tr><th align="left">Interface</th><th align="left">Endpoint / command</th><th align="left">Use it for</th></tr>
|
<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 (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>105 tools</b>, 31 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>109 tools</b>, 33 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>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>A2A</b></td><td align="left" nowrap><code>/.well-known/agent.json</code></td><td align="left">Agent-to-agent, <b>JSON-RPC 2.0</b> + SSE, 6 skills</td></tr>
|
||||||
<tr><td align="left" nowrap>🌐 <b>REST API</b></td><td align="left" nowrap><code>/v1/*</code></td><td align="left">OpenAI-compatible — chat, embeddings, images, audio, OCR</td></tr>
|
<tr><td align="left" nowrap>🌐 <b>REST API</b></td><td align="left" nowrap><code>/v1/*</code></td><td align="left">OpenAI-compatible — chat, embeddings, images, audio, OCR</td></tr>
|
||||||
@@ -1061,7 +1080,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>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>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>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) — 95 domain modules, 145 migrations</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>Memory</b></td><td>SQLite FTS5 full-text + int8-quantized vector embeddings, typed decay</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>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>
|
<tr><td nowrap><b>Protocols</b></td><td>MCP (stdio / HTTP / SSE) + A2A v0.3 (JSON-RPC 2.0 + SSE)</td></tr>
|
||||||
@@ -1135,7 +1154,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><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/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="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>105 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>109 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="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="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>
|
<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>
|
||||||
|
|||||||
76
bin/cli/commands/radar.mjs
Normal file
76
bin/cli/commands/radar.mjs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
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,6 +78,7 @@ import { registerTokens } from "./tokens.mjs";
|
|||||||
import { registerConfigure } from "./configure.mjs";
|
import { registerConfigure } from "./configure.mjs";
|
||||||
import { registerApiCommands } from "../api-commands/registry.mjs";
|
import { registerApiCommands } from "../api-commands/registry.mjs";
|
||||||
import { registerPlugin } from "./plugin.mjs";
|
import { registerPlugin } from "./plugin.mjs";
|
||||||
|
import { registerRadar } from "./radar.mjs";
|
||||||
|
|
||||||
export function registerCommands(program) {
|
export function registerCommands(program) {
|
||||||
registerMemory(program);
|
registerMemory(program);
|
||||||
@@ -161,4 +162,5 @@ export function registerCommands(program) {
|
|||||||
registerConfigure(program);
|
registerConfigure(program);
|
||||||
registerApiCommands(program);
|
registerApiCommands(program);
|
||||||
registerPlugin(program);
|
registerPlugin(program);
|
||||||
|
registerRadar(program);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -921,6 +921,11 @@
|
|||||||
"model": "Filter by model"
|
"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": {
|
"resilience": {
|
||||||
"description": "Inspect and manage resilience mechanisms",
|
"description": "Inspect and manage resilience mechanisms",
|
||||||
"status": {
|
"status": {
|
||||||
|
|||||||
@@ -918,6 +918,11 @@
|
|||||||
"model": "Filtrar por model"
|
"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": {
|
"resilience": {
|
||||||
"description": "Inspecionar e gerenciar mecanismos de resiliência",
|
"description": "Inspecionar e gerenciar mecanismos de resiliência",
|
||||||
"status": {
|
"status": {
|
||||||
|
|||||||
1
changelog.d/features/9830-radar-local-model-state.md
Normal file
1
changelog.d/features/9830-radar-local-model-state.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- **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
changelog.d/features/9836-radar-guided-combos.md
Normal file
1
changelog.d/features/9836-radar-guided-combos.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- **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
changelog.d/features/9912-radar-supporter-offers.md
Normal file
1
changelog.d/features/9912-radar-supporter-offers.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- **feat(radar):** add a signed live offers feed and supporter offers dashboard ([#9912](https://github.com/diegosouzapw/OmniRoute/pull/9912))
|
||||||
1
changelog.d/features/9923-radar-intel.md
Normal file
1
changelog.d/features/9923-radar-intel.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- **feat(radar):** add signed Intel insights, supporter recognition, and local Radar CLI commands ([#9923](https://github.com/diegosouzapw/OmniRoute/pull/9923))
|
||||||
1
changelog.d/features/9926-radar-launch-news.md
Normal file
1
changelog.d/features/9926-radar-launch-news.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- **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/build-advisory-hosted-runner.md
Normal file
1
changelog.d/fixes/build-advisory-hosted-runner.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- 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/**`)
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
"providers-bailian-coding-plan.spec.ts": 240,
|
"providers-bailian-coding-plan.spec.ts": 240,
|
||||||
"providers-management.spec.ts": 324,
|
"providers-management.spec.ts": 324,
|
||||||
"proxy-registry.smoke.spec.ts": 218,
|
"proxy-registry.smoke.spec.ts": 218,
|
||||||
|
"radar-guided-setup.spec.ts": 177,
|
||||||
"resilience-plan-alignment.spec.ts": 382,
|
"resilience-plan-alignment.spec.ts": 382,
|
||||||
"responsive.spec.ts": 21,
|
"responsive.spec.ts": 21,
|
||||||
"search-tools-studio.spec.ts": 133,
|
"search-tools-studio.spec.ts": 133,
|
||||||
@@ -36,4 +37,4 @@
|
|||||||
"traffic-inspector.spec.ts": 212,
|
"traffic-inspector.spec.ts": 212,
|
||||||
"translator-friendly.spec.ts": 115,
|
"translator-friendly.spec.ts": 115,
|
||||||
"visual-resilience-smoke.spec.ts": 20
|
"visual-resilience-smoke.spec.ts": 20
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,10 +205,10 @@ Runs on pull requests only.
|
|||||||
|
|
||||||
Runs after `build`. Blocks merge on failure.
|
Runs after `build`. Blocks merge on failure.
|
||||||
|
|
||||||
| Suite | Validates | Blocking |
|
| Suite | Validates | Blocking |
|
||||||
| ---------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||||
| `test:vitest` | MCP server (105 tools), autoCombo, cache — vitest runner | Yes |
|
| `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 |
|
| `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)
|
### Nightly workflows (scheduled, advisory)
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ OmniRoute/
|
|||||||
| **.gitleaks.toml** | gitleaks secret-scan ruleset |
|
| **.gitleaks.toml** | gitleaks secret-scan ruleset |
|
||||||
| **.zizmor.yml** | zizmor GitHub-Actions security-lint config |
|
| **.zizmor.yml** | zizmor GitHub-Actions security-lint config |
|
||||||
| **socket.yml** | Socket.dev supply-chain config |
|
| **socket.yml** | Socket.dev supply-chain config |
|
||||||
| **news.json** | In-app release-notes feed (read by `src/shared/utils/releaseNotes.ts`) |
|
| **news.json** | Localized v2 announcement feed; Radar launch item ships inactive |
|
||||||
| **flake.nix** / **flake.lock** | Nix dev-shell definition + lock |
|
| **flake.nix** / **flake.lock** | Nix dev-shell definition + lock |
|
||||||
| **.env** | Local secrets (gitignored — generated from `.env.example`) |
|
| **.env** | Local secrets (gitignored — generated from `.env.example`) |
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@ src/
|
|||||||
| `compliance/` | Audit log + provider audit — see `docs/security/COMPLIANCE.md` |
|
| `compliance/` | Audit log + provider audit — see `docs/security/COMPLIANCE.md` |
|
||||||
| `compression/` | Compression engine glue (engines live in `open-sse/services/compression/`) |
|
| `compression/` | Compression engine glue (engines live in `open-sse/services/compression/`) |
|
||||||
| `config/` | Runtime config helpers |
|
| `config/` | Runtime config helpers |
|
||||||
| `db/` | 95+ domain DB modules + 144 migrations (always go through here for SQLite) |
|
| `db/` | 95+ domain DB modules + 148 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` |
|
| `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` |
|
| `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.) |
|
| `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/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) |
|
| `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 |
|
| `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 |
|
| `plugins/` | Plugin registry |
|
||||||
| `promptCache/` | Anthropic-style prompt cache breakpoints |
|
| `promptCache/` | Anthropic-style prompt cache breakpoints |
|
||||||
| `skills/` | Skills framework (built-in + marketplace + SkillsSH) — see `docs/frameworks/SKILLS.md` |
|
| `skills/` | Skills framework (built-in + marketplace + SkillsSH) — see `docs/frameworks/SKILLS.md` |
|
||||||
@@ -209,7 +209,7 @@ src/
|
|||||||
| `cacheLayer.ts`, `idempotencyLayer.ts` | Request caching + idempotency |
|
| `cacheLayer.ts`, `idempotencyLayer.ts` | Request caching + idempotency |
|
||||||
| (~30 more top-level files) | Specialized helpers (logEnv, modelsDevSync, piiSanitizer, etc.) |
|
| (~30 more top-level files) | Specialized helpers (logEnv, modelsDevSync, piiSanitizer, etc.) |
|
||||||
|
|
||||||
### `src/db/` — Database (117 modules + 144 migrations)
|
### `src/db/` — Database (117 modules + 148 migrations)
|
||||||
|
|
||||||
| Subdir | Purpose |
|
| Subdir | Purpose |
|
||||||
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
@@ -256,6 +256,7 @@ src/
|
|||||||
| `utils/circuitBreaker.ts` | Provider circuit breaker (see `docs/architecture/RESILIENCE_GUIDE.md`) |
|
| `utils/circuitBreaker.ts` | Provider circuit breaker (see `docs/architecture/RESILIENCE_GUIDE.md`) |
|
||||||
| `utils/apiAuth.ts` | API key validation, scope checking |
|
| `utils/apiAuth.ts` | API key validation, scope checking |
|
||||||
| `utils/fetchTimeout.ts` | Timeout/abort wrappers for upstream fetch |
|
| `utils/fetchTimeout.ts` | Timeout/abort wrappers for upstream fetch |
|
||||||
|
| `utils/releaseNotes.ts` | Closed v2/legacy announcement parser, localization and ID dismissal |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -270,7 +271,7 @@ open-sse/
|
|||||||
├── translator/ # Format converters (9 request, 9 response, 9 helpers)
|
├── translator/ # Format converters (9 request, 9 response, 9 helpers)
|
||||||
├── transformer/ # Responses API ↔ Chat Completions (TransformStream)
|
├── transformer/ # Responses API ↔ Chat Completions (TransformStream)
|
||||||
├── services/ # ~80+ service modules (combo, accountFallback, autoCombo, reasoningCache, claude code/chatgpt stealth, modelDeprecation, taskAwareRouter, workflowFSM, etc.)
|
├── services/ # ~80+ service modules (combo, accountFallback, autoCombo, reasoningCache, claude code/chatgpt stealth, modelDeprecation, taskAwareRouter, workflowFSM, etc.)
|
||||||
├── mcp-server/ # MCP server (105 tools, 3 transports, 31 scopes)
|
├── mcp-server/ # MCP server (109 tools, 3 transports, 33 scopes)
|
||||||
├── config/ # Provider/model registries, header config, model aliases
|
├── config/ # Provider/model registries, header config, model aliases
|
||||||
├── utils/ # TLS client, proxy fetch/dispatcher, network helpers
|
├── utils/ # TLS client, proxy fetch/dispatcher, network helpers
|
||||||
├── index.ts # Workspace entry
|
├── index.ts # Workspace entry
|
||||||
@@ -406,7 +407,7 @@ open-sse/
|
|||||||
|
|
||||||
| Doc | Purpose |
|
| Doc | Purpose |
|
||||||
| -------------------------- | ------------------------------------------------------------------- |
|
| -------------------------- | ------------------------------------------------------------------- |
|
||||||
| `MCP-SERVER.md` | MCP server: 105 tools, 3 transports, 31 scopes, REST endpoints |
|
| `MCP-SERVER.md` | MCP server: 109 tools, 3 transports, 33 scopes, REST endpoints |
|
||||||
| `A2A-SERVER.md` | A2A v0.3: JSON-RPC, 6 skills, REST helpers, agent card |
|
| `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 |
|
| `AGENT_PROTOCOLS_GUIDE.md` | Unified guide: A2A vs ACP vs Cloud Agents |
|
||||||
| `CLOUD_AGENT.md` | Codex Cloud / Devin / Jules orchestration |
|
| `CLOUD_AGENT.md` | Codex Cloud / Devin / Jules orchestration |
|
||||||
|
|||||||
@@ -330,32 +330,75 @@ excludeMarkers, defaultRetryAfterMs}`), matched via `applyStatusRestatement()`.
|
|||||||
|
|
||||||
Permanent errors (agentrouter's `无权访问模型` — no access to this model) are
|
Permanent errors (agentrouter's `无权访问模型` — no access to this model) are
|
||||||
NEVER restated: `excludeMarkers` vetoes the rule even when `textMarkers` hit,
|
NEVER restated: `excludeMarkers` vetoes the rule even when `textMarkers` hit,
|
||||||
so the error keeps its original status and nothing retries it forever. A
|
so the error keeps its original status and nothing retries it forever. The
|
||||||
separate provider classification rule
|
matching provider classification rule
|
||||||
(`agentrouter-model-access-denied` in `open-sse/config/providerErrorRules.ts`)
|
(`agentrouter-model-access-denied` in `open-sse/config/providerErrorRules.ts`:
|
||||||
declares an `auth_error`/scope-`model` match for this text, but it does not
|
`reason: "auth_error"`, `scope: "model"`, a `6h` declared base cooldown) is
|
||||||
fire on the live production path today: the rule only matches `status ===
|
consulted by `checkFallbackError` (`open-sse/services/accountFallback.ts`)
|
||||||
403`, and `checkFallbackError`'s apikey-category `FORBIDDEN` branch
|
*before* the generic apikey-category `FORBIDDEN` early-return, gated on
|
||||||
(`open-sse/services/accountFallback.ts`) returns early for a plain 403
|
`honorsRuleLockScope(provider)` (#10334 — currently agentrouter-exclusive via
|
||||||
*before* the provider-rule lookup ever runs. In practice a `无权访问模型` 403
|
the `HONORS_RULE_LOCK_SCOPE_PROVIDERS` allowlist in
|
||||||
is handled the same way as the base apikey-provider 403 path (see Connection
|
`providerErrorRules.ts`). The rule's declared 6h cooldown flows through as
|
||||||
Cooldown, §2), not as a 6h model lockout. The rule still exists as a
|
`fallbackResult.baseCooldownMs`, but it still feeds the pre-existing
|
||||||
declarative classification consumable by future callers of `classifyError`
|
per-model-quota lockout path (`lockModelIfPerModelQuota()` /
|
||||||
with context — wiring it into the production `checkFallbackError` path is
|
`recordModelLockoutFailure()`, unchanged by #10334 except for the cooldown
|
||||||
tracked as a follow-up, not yet done.
|
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.
|
||||||
|
|
||||||
Restated quota errors (`额度不足`) do reach a provider rule in production
|
Restated quota errors (`额度不足`) reach a provider rule in production
|
||||||
(`agentrouter-user-quota-exhausted`, scope `"connection"`), but `scope` on
|
(`agentrouter-user-quota-exhausted`: `reason: "quota_exhausted"`, `scope:
|
||||||
`ProviderErrorRuleMatch` is currently informational — the persistence path
|
"connection"`, no declared cooldown of its own — the persistence layer's
|
||||||
(`checkFallbackError` → `combo.ts`) only consumes `reason` and `cooldownMs`,
|
scaled backoff default applies). Since #10334, `scope` on
|
||||||
never `scope`. What actually happens for agentrouter (`passthroughModels:
|
`ProviderErrorRuleMatch` IS consumed end-to-end, but **only** for providers in
|
||||||
true` → `hasPerModelQuota()` returns `true`) is a **per-model** lockout via
|
the `HONORS_RULE_LOCK_SCOPE_PROVIDERS` allowlist (`providerErrorRules.ts` —
|
||||||
`recordModelLockoutFailure()`: the connection itself is never cooled down for
|
today only `"agentrouter"`, gated via `honorsRuleLockScope()`). For every
|
||||||
this error (`combo.ts` skips `recordProviderCooldown` for 429 when
|
other provider `scope` remains informational, exactly as before #10334.
|
||||||
`hasPerModelQuota` is true), so other models on the same account keep being
|
`checkFallbackError` surfaces the matched rule's scope as
|
||||||
tried — each one burns one call and its own lockout before combo routing
|
`fallbackResult.ruleScope`; `isAgentrouterConnectionQuotaScope()`
|
||||||
moves on. Honoring `scope` end-to-end (so a `"connection"` match actually
|
(`src/sse/services/auth.ts`) is the shared guard that confirms a
|
||||||
locks the connection) is tracked as a follow-up.
|
`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.
|
||||||
|
|
||||||
### Two-stage design: status restatement, then classification
|
### Two-stage design: status restatement, then classification
|
||||||
|
|
||||||
@@ -380,6 +423,15 @@ allowlisted providers, the structured error otherwise. Adding a provider to
|
|||||||
that the default path for every provider not on the list stays
|
that the default path for every provider not on the list stays
|
||||||
byte-for-byte unchanged.
|
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
|
### Adding a new quota-misstating gateway
|
||||||
|
|
||||||
1. Register one rule array in `statusRestatementRegistry`
|
1. Register one rule array in `statusRestatementRegistry`
|
||||||
@@ -395,7 +447,15 @@ byte-for-byte unchanged.
|
|||||||
`checkFallbackError` only ever hands the rule the structured
|
`checkFallbackError` only ever hands the rule the structured
|
||||||
`{code, type}` error and a body-text rule will never match live traffic.
|
`{code, type}` error and a body-text rule will never match live traffic.
|
||||||
Rules that match purely on `status`/`headers` (like Opencode's or
|
Rules that match purely on `status`/`headers` (like Opencode's or
|
||||||
Minimax's) do not need this opt-in.
|
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.
|
||||||
3. Add unit tests mirroring `tests/unit/upstream-status-restatement.test.ts`
|
3. Add unit tests mirroring `tests/unit/upstream-status-restatement.test.ts`
|
||||||
and `tests/unit/agentrouter-error-rules.test.ts` (including the
|
and `tests/unit/agentrouter-error-rules.test.ts` (including the
|
||||||
not-permanent / not-creditsExhausted guards, and — if the provider needs
|
not-permanent / not-creditsExhausted guards, and — if the provider needs
|
||||||
|
|||||||
@@ -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: 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.">
|
<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 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.">
|
||||||
<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>
|
<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>
|
<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>
|
<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>
|
||||||
<g opacity="0"><animate attributeName="opacity" values="0;1" dur="0.4s" begin="0.51s" fill="freeze"/>
|
<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="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">105</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>
|
||||||
<use href="#no" x="604" y="359"/>
|
<use href="#no" x="604" y="359"/>
|
||||||
<use href="#mid" x="760" y="359"/>
|
<use href="#mid" x="760" y="359"/>
|
||||||
<use href="#no" x="916" 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, 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.">
|
<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 109 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>
|
<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>
|
<defs>
|
||||||
<pattern id="gridPaperP" width="32" height="32" patternUnits="userSpaceOnUse">
|
<pattern id="gridPaperP" width="32" height="32" patternUnits="userSpaceOnUse">
|
||||||
@@ -125,7 +125,7 @@
|
|||||||
<path d="M 7,11 L 10,14 L 15.4,8.2"/>
|
<path d="M 7,11 L 10,14 L 15.4,8.2"/>
|
||||||
</g>
|
</g>
|
||||||
<text x="862" y="354" font-size="18" font-weight="800" fill="#7ee787">Production-grade</text>
|
<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 (105</text>
|
<text x="826" y="388" font-size="13.5" fill="#a1a1aa">Circuit breakers, TLS stealth, MCP (109</text>
|
||||||
<text x="826" y="410" font-size="13.5" fill="#a1a1aa">tools), A2A, memory, guardrails, evals —</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>
|
<text x="826" y="432" font-size="13.5" fill="#a1a1aa">25,000+ tests.</text>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -1,14 +1,14 @@
|
|||||||
---
|
---
|
||||||
title: "OmniRoute MCP Server Documentation"
|
title: "OmniRoute MCP Server Documentation"
|
||||||
version: 3.8.40
|
version: 3.8.50
|
||||||
lastUpdated: 2026-06-28
|
lastUpdated: 2026-08-08
|
||||||
---
|
---
|
||||||
|
|
||||||
# OmniRoute MCP Server Documentation
|
# OmniRoute MCP Server Documentation
|
||||||
|
|
||||||
> Model Context Protocol server with 105 tools across routing, cache, compression, memory, skills, proxy, pool, and context source operations.
|
> Model Context Protocol server with 109 tools across routing, cache, compression, memory, skills, proxy, pool, Radar, and context source operations.
|
||||||
>
|
>
|
||||||
> 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.
|
> 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.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ Cursor, Cline, and compatible MCP client setup.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Essential Tools (8) — Phase 1
|
## Essential Tools (13) — Phase 1
|
||||||
|
|
||||||
| Tool | Scopes | Description |
|
| Tool | Scopes | Description |
|
||||||
| :------------------------------ | :-------------------- | :------------------------------------------------------------ |
|
| :------------------------------ | :-------------------- | :------------------------------------------------------------ |
|
||||||
@@ -72,16 +72,15 @@ Cursor, Cline, and compatible MCP client setup.
|
|||||||
| `omniroute_list_combos` | `read:combos` | All configured combos with strategies (optional metrics) |
|
| `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_get_combo_metrics` | `read:combos` | Performance metrics for a specific combo |
|
||||||
| `omniroute_switch_combo` | `write:combos` | Activate or deactivate a 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_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_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_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_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 |
|
||||||
## Phase 1 — Search
|
| `omniroute_tool_search` | `read:tools` | Discover tools from the registered MCP catalog |
|
||||||
|
| `omniroute_web_search` | `execute:search` | Web search through the configured search providers |
|
||||||
| Tool | Scopes | Description |
|
| `omniroute_web_fetch` | `execute:search` | Fetch web content through the configured fetch providers |
|
||||||
| :--------------------- | :--------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| `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
|
## Advanced Tools (11) — Phase 2
|
||||||
|
|
||||||
@@ -227,7 +226,7 @@ See [AGENT-SKILLS.md](./AGENT-SKILLS.md) for the full catalog and how external a
|
|||||||
|
|
||||||
## Related Frameworks (v3.8.0)
|
## Related Frameworks (v3.8.0)
|
||||||
|
|
||||||
computed = 105, computed by `countUniqueMcpTools()`) is intentionally
|
The MCP tool inventory above (109 unique tools, computed by `countUniqueMcpTools()`) is intentionally
|
||||||
scoped to runtime routing/cache/compression/memory/skills/proxy/context-source operations. Two adjacent
|
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:
|
frameworks ship alongside the MCP server in v3.8.0 and are documented separately:
|
||||||
|
|
||||||
@@ -369,7 +368,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`).
|
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 105 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 109 tools are announced unchanged.
|
||||||
|
|
||||||
| Variable | Mode |
|
| Variable | Mode |
|
||||||
| :--------------- | :-------------------------------------------------------------------------------------- |
|
| :--------------- | :-------------------------------------------------------------------------------------- |
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
---
|
---
|
||||||
title: "Radar Free-Model Catalog"
|
title: "Radar Free-Model Catalog"
|
||||||
version: 3.8.50
|
version: 3.8.50
|
||||||
lastUpdated: 2026-08-08
|
lastUpdated: 2026-08-13
|
||||||
---
|
---
|
||||||
|
|
||||||
# Radar Free-Model Catalog
|
# Radar Free-Model Catalog
|
||||||
|
|
||||||
> **Source of truth:** `src/lib/radar/`, `src/lib/db/radar.ts`, `src/app/api/radar/`
|
> **Source of truth:** `src/lib/radar/`, `src/lib/db/radar.ts`, `src/app/api/radar/`
|
||||||
> **Last updated:** 2026-08-08 — v3.8.50
|
> **Last updated:** 2026-08-13 — v3.8.50
|
||||||
|
|
||||||
Radar is an **optional add-on** that overlays a signed, freshly-curated free-model
|
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
|
catalog on top of the release baseline (`FREE_MODEL_BUDGETS` in
|
||||||
@@ -15,11 +15,12 @@ catalog on top of the release baseline (`FREE_MODEL_BUDGETS` in
|
|||||||
faster than release cadence — providers add, shrink, or discontinue free quotas between
|
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.
|
releases, and the baseline catalog can only be refreshed when a new version ships.
|
||||||
|
|
||||||
**Nothing that is free today stops being free.** Radar never removes or paywalls a
|
**Nothing that is free today stops being free because of the remote feed.** Radar never
|
||||||
baseline entry; it only refreshes limits/status fields at read time and can layer in
|
paywalls a baseline entry; it only refreshes limits/status fields at read time and can
|
||||||
newly-discovered free models between releases. The baseline catalog itself is never
|
layer in newly-discovered free models between releases. An operator can still hide a
|
||||||
mutated on disk — see [Read-time overlay merge rules](#read-time-overlay-merge-rules)
|
model locally, and can restore it from the same dashboard. The baseline catalog itself
|
||||||
below.
|
is never mutated on disk — see
|
||||||
|
[Read-time overlay merge rules](#read-time-overlay-merge-rules) below.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -29,14 +30,39 @@ 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
|
workstreams. It is a code-level status, not a promise that a particular hosted deployment
|
||||||
or external integration is currently available.
|
or external integration is currently available.
|
||||||
|
|
||||||
| Area | Status in this release |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
||||||
| 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. |
|
| 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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -48,15 +74,16 @@ Radar is gated end-to-end by the `RADAR_ENABLED` feature flag
|
|||||||
|
|
||||||
**When the flag is off, the surface does not exist:**
|
**When the flag is off, the surface does not exist:**
|
||||||
|
|
||||||
- `GET /api/radar/catalog`, `POST /api/radar/sync`, `POST /api/radar/settings` all
|
- All `/api/radar/*` endpoints, including local model-state reads and writes,
|
||||||
return `404` before touching any Radar module.
|
return `404` before touching any Radar module.
|
||||||
- The dashboard screens (`/dashboard/radar`, `/dashboard/radar/setup`) render
|
- The dashboard screens (`/dashboard/radar`, `/dashboard/radar/setup`,
|
||||||
|
`/dashboard/radar/combos`, `/dashboard/radar/offers`, `/dashboard/radar/intel`) render
|
||||||
`notFound()`.
|
`notFound()`.
|
||||||
- `getRadarCatalog()` (`src/lib/radar/index.ts`) returns the untouched baseline —
|
- `getRadarCatalog()` (`src/lib/radar/index.ts`) returns the untouched baseline —
|
||||||
same entry count, same values, every entry tagged `origin: "baseline"` — and never
|
same entry count, same values, every entry tagged `origin: "baseline"` — and never
|
||||||
reads the feed cache.
|
reads the feed cache.
|
||||||
- No network call is ever made; `syncRadar()` (`src/lib/radar/sync.ts`) returns
|
- No Radar network call is ever made; each sync module returns `{ status: "disabled" }`
|
||||||
`{ status: "disabled" }` at step 1 without touching `fetch`.
|
before touching `fetch`.
|
||||||
|
|
||||||
This is a strict superset gate: flipping the flag on unlocks the _screens_, nothing
|
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
|
more. It does not upload data, does not start a background sync, and does not change
|
||||||
@@ -78,14 +105,17 @@ Opt-in false → { status: "opt_out" } — no network call
|
|||||||
|
|
||||||
When both are on, the sync path is:
|
When both are on, the sync path is:
|
||||||
|
|
||||||
1. `GET <feed base URL>/v1/catalog/latest` with an optional `Authorization: Bearer
|
1. `GET <feed base URL>/v1/catalog/latest` with `x-omniroute-radar-schema: 2` and an optional
|
||||||
<supporter key>` header (see below).
|
`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.
|
||||||
2. Nothing about the request, the operator, or their traffic is uploaded — it is a
|
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
|
plain, unauthenticated-by-default GET. OmniRoute never posts usage data, provider
|
||||||
configuration, or model traffic to the feed service.
|
configuration, or model traffic to the feed service.
|
||||||
3. The response is verified, validated, and cached locally (see
|
3. The response is verified, validated, and cached locally (see
|
||||||
[Security model](#security-model)). Radar has exactly two server-side network paths:
|
[Security model](#security-model)). Radar has exactly four server-side network paths:
|
||||||
`syncRadar()` for the catalog and `syncRadarReferrals()` for the standalone referrals feed.
|
`syncRadar()` for the catalog, `syncRadarReferrals()` for referrals, and
|
||||||
|
`syncRadarOffers()` / `syncRadarIntel()` for supporter-only offers and Intel.
|
||||||
|
|
||||||
The **supporter key** is an optional Bearer token (`radar_settings.supporter_key`)
|
The **supporter key** is an optional Bearer token (`radar_settings.supporter_key`)
|
||||||
that lets the feed service decide which tier to serve (see
|
that lets the feed service decide which tier to serve (see
|
||||||
@@ -95,7 +125,7 @@ that lets the feed service decide which tier to serve (see
|
|||||||
helpers (`src/lib/db/encryption.ts`) used for provider credentials.
|
helpers (`src/lib/db/encryption.ts`) used for provider credentials.
|
||||||
- Set via `POST /api/radar/settings` (`{ supporterKey: "omr_" + 40 hex chars }`) and
|
- Set via `POST /api/radar/settings` (`{ supporterKey: "omr_" + 40 hex chars }`) and
|
||||||
**never echoed back** — the response returns a masked form (`omr_****abcd`).
|
**never echoed back** — the response returns a masked form (`omr_****abcd`).
|
||||||
- Changing or clearing it atomically invalidates both the catalog and referrals caches. The
|
- Changing or clearing it atomically invalidates the catalog, referrals, offers, and Intel caches. The
|
||||||
next sync/read resolves the new entitlement server-side; saving a key does not itself make
|
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.
|
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
|
- Sent to the feed service as a Bearer token on the sync GET — nothing else about the
|
||||||
@@ -128,6 +158,29 @@ client component never reads `process.env` itself.
|
|||||||
| `RADAR_CONTRIBUTOR_CLAIM_URL` | Overrides the contributor-claim URL (default `https://radar.omniroute.online/auth/github`). |
|
| `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`). |
|
| `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
|
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
|
(`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`
|
path: pasting a key and submitting sends `POST /api/radar/settings`
|
||||||
@@ -141,6 +194,57 @@ 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
|
remain the way to _obtain_ a key in the first place; this input is where an operator
|
||||||
who already has one activates it.
|
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
|
## Security model
|
||||||
@@ -271,6 +375,54 @@ Four rules, in order of precedence:
|
|||||||
entry (`tombstones` set), the feed re-adding that `provider:modelId` in a later
|
entry (`tombstones` set), the feed re-adding that `provider:modelId` in a later
|
||||||
version does not bring it back.
|
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
|
### Provenance markers
|
||||||
|
|
||||||
Every merged entry carries an `origin` field the UI renders as a badge:
|
Every merged entry carries an `origin` field the UI renders as a badge:
|
||||||
@@ -284,30 +436,41 @@ Every merged entry carries an `origin` field the UI renders as a badge:
|
|||||||
|
|
||||||
## Local surfaces — never a feed proxy
|
## Local surfaces — never a feed proxy
|
||||||
|
|
||||||
Five local routes back the UI, all under `src/app/api/radar/`:
|
The local Radar route families below back the UI under `src/app/api/radar/`:
|
||||||
|
|
||||||
| Route | Method | Purpose |
|
| Route | Method | Purpose |
|
||||||
| ---------------------- | ------ | --------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------------ | ------ | --------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `/api/radar/catalog` | GET | Returns the merged catalog (`getRadarCatalog()`) from the local cache. |
|
| `/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/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` | GET | Returns `{ optIn, hasSupporterKey, supporterKeyMasked }` — never the raw key. |
|
||||||
| `/api/radar/settings` | POST | Sets opt-in and/or the (encrypted) supporter 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/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. |
|
||||||
|
|
||||||
**Hard rule: these routes never proxy the feed service.** The browser only ever talks
|
**Hard rule: these routes never proxy the feed service.** The browser only ever talks
|
||||||
to the local OmniRoute server. The two modules that touch the Radar service are
|
to the local OmniRoute server. The four modules that touch the Radar service are
|
||||||
`src/lib/radar/sync.ts` (catalog) and `src/lib/radar/referralsSync.ts` (referrals); both
|
`src/lib/radar/sync.ts` (catalog), `src/lib/radar/referralsSync.ts` (referrals), and
|
||||||
always run server-side, never client-side. This keeps the feed URL and any supporter key
|
`src/lib/radar/offersSync.ts` (offers) plus `src/lib/radar/intelSync.ts` (Intel); all run
|
||||||
out of client-facing network traffic entirely.
|
server-side, never client-side. This keeps
|
||||||
|
the feed URL and any supporter key out of client-facing network traffic entirely.
|
||||||
|
|
||||||
All five routes return `404` when `RADAR_ENABLED` is off (see
|
All Radar endpoints return `404` when `RADAR_ENABLED` is off (see
|
||||||
[Flag](#flag-radar_enabled-default-off) above), and route error responses through
|
[Flag](#flag-radar_enabled-default-off) above), and route error responses through
|
||||||
`buildErrorBody()`/`sanitizeErrorMessage()` per the repo-wide error-sanitization rule
|
`buildErrorBody()`/`sanitizeErrorMessage()` per the repo-wide error-sanitization rule
|
||||||
(`docs/security/ERROR_SANITIZATION.md`).
|
(`docs/security/ERROR_SANITIZATION.md`).
|
||||||
|
|
||||||
### Authentication
|
### Authentication
|
||||||
|
|
||||||
All five routes require authentication via `isAuthenticated()`
|
All Radar endpoints require authentication via `isAuthenticated()`
|
||||||
(`src/shared/utils/apiAuth.ts`) — a dashboard session cookie or a management-scoped
|
(`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
|
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`
|
`404` check always runs **before** the auth check, so an install with `RADAR_ENABLED`
|
||||||
@@ -318,6 +481,58 @@ 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 (free credits)
|
||||||
|
|
||||||
Referral links are served from a **standalone, always-current** feed —
|
Referral links are served from a **standalone, always-current** feed —
|
||||||
@@ -473,8 +688,9 @@ service without touching client code:
|
|||||||
|
|
||||||
1. Serve a `GET /v1/catalog/latest` endpoint returning a JSON body that satisfies
|
1. Serve a `GET /v1/catalog/latest` endpoint returning a JSON body that satisfies
|
||||||
`RadarFeedSchema` (`src/lib/radar/feedSchema.ts`) — top-level `feed:
|
`RadarFeedSchema` (`src/lib/radar/feedSchema.ts`) — top-level `feed:
|
||||||
"omniroute-radar"`, `schemaVersion: 1`, `version`, `tier`, `providers`, `models`,
|
"omniroute-radar"`, `schemaVersion: 2`, `version`, `tier`, `providers`, `models`,
|
||||||
`quirks`, and `totals`.
|
`quirks`, and `totals`. Honor `x-omniroute-radar-schema: 2`; a transition-compatible server
|
||||||
|
should default requests without it to a separately signed v1 artifact.
|
||||||
2. Sign the exact response bytes with an Ed25519 key pair and return the base64
|
2. Sign the exact response bytes with an Ed25519 key pair and return the base64
|
||||||
signature in the `x-omniroute-feed-signature` response header.
|
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
|
3. Set `RADAR_FEED_URL` to the new base URL and `RADAR_FEED_PUBKEY` to the matching
|
||||||
@@ -498,11 +714,24 @@ 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
|
(`src/lib/radar/referralsFeedSchema.ts`) and sign it with the same Ed25519 key pair as
|
||||||
the catalog feed.
|
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
|
## Related docs
|
||||||
|
|
||||||
- [`docs/security/ERROR_SANITIZATION.md`](../security/ERROR_SANITIZATION.md) — the
|
- [`docs/security/ERROR_SANITIZATION.md`](../security/ERROR_SANITIZATION.md) — the
|
||||||
error-response pattern the five `/api/radar/*` routes follow.
|
error-response pattern the `/api/radar/*` routes follow.
|
||||||
- [`docs/reference/ENVIRONMENT.md`](../reference/ENVIRONMENT.md#27-radar-feed-self-hosting)
|
- [`docs/reference/ENVIRONMENT.md`](../reference/ENVIRONMENT.md#27-radar-feed-self-hosting)
|
||||||
— `RADAR_FEED_URL` / `RADAR_FEED_PUBKEY` reference.
|
— `RADAR_FEED_URL` / `RADAR_FEED_PUBKEY` reference.
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 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
|
## Overview
|
||||||
|
|
||||||
@@ -21,7 +18,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -109,7 +106,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -131,7 +128,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -214,11 +211,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -269,7 +266,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -352,9 +349,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -397,7 +394,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -441,7 +438,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -485,7 +482,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ directly from anywhere — CI can only stage; only the owner's 2FA releases.
|
|||||||
as the default reflex (minutes, reversible); `npm unpublish` only inside the 72h/no-dependents
|
as the default reflex (minutes, reversible); `npm unpublish` only inside the 72h/no-dependents
|
||||||
window and never as the first move. Docker: never rewrite a version tag — rollback is
|
window and never as the first move. Docker: never rewrite a version tag — rollback is
|
||||||
repointing `latest` to the last good digest.
|
repointing `latest` to the last good digest.
|
||||||
|
|
||||||
## Hotfix Fast-Lane (label `hotfix`)
|
## Hotfix Fast-Lane (label `hotfix`)
|
||||||
|
|
||||||
A PR labeled `hotfix` skips the heavy CI matrix (9-shard E2E, coverage ratchet,
|
A PR labeled `hotfix` skips the heavy CI matrix (9-shard E2E, coverage ratchet,
|
||||||
@@ -276,6 +277,22 @@ Deploy skills use the light rsync flow — no `npm pack`, no `npm i -g`:
|
|||||||
- [ ] Open milestone for next version
|
- [ ] Open milestone for next version
|
||||||
- [ ] If critical: pin discussion or post in `news.json` for in-app banner
|
- [ ] If critical: pin discussion or post in `news.json` for in-app banner
|
||||||
|
|
||||||
|
### Radar public-launch gate
|
||||||
|
|
||||||
|
The Radar announcement is intentionally committed with `active: false`. Activation is a separate
|
||||||
|
change after every item below is evidenced:
|
||||||
|
|
||||||
|
- [ ] All stacked Radar PRs are merged and the release-tip CI is green
|
||||||
|
- [ ] Deploy and smoke the OSS Radar routes with `RADAR_ENABLED` still off by default
|
||||||
|
- [ ] Smoke `GET /planos`, `/termos`, `/privacidade`, and `/reembolso` on the named Radar host
|
||||||
|
- [ ] Record operator identity/contact/address and owner-approved legal review in the private service
|
||||||
|
- [ ] Exercise Stripe Checkout and the signed webhook in test mode only
|
||||||
|
- [ ] Exercise one encrypted transactional-email delivery with the approved sender/domain
|
||||||
|
- [ ] Prove backup restore and one supervised, budget-capped research run
|
||||||
|
- [ ] Approve the BRL/PIX review policy before accepting donation evidence
|
||||||
|
- [ ] Enable public Checkout only after the preceding gates, then activate the new `news.json` ID
|
||||||
|
- [ ] Verify the Home banner uses localized copy and a new ID reappears after an older ID is dismissed
|
||||||
|
|
||||||
## Embedded Services smoke (v3.8.4+)
|
## Embedded Services smoke (v3.8.4+)
|
||||||
|
|
||||||
Before shipping any release that includes embedded services changes, verify:
|
Before shipping any release that includes embedded services changes, verify:
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ different endpoint families, so all four products remain separate provider IDs.
|
|||||||
| Provider family | `global-sg` | `china-beijing` | Wire format |
|
| Provider family | `global-sg` | `china-beijing` | Wire format |
|
||||||
| ----------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------- | ----------- |
|
| ----------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------- | ----------- |
|
||||||
| `alibaba` | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | OpenAI |
|
| `alibaba` | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | OpenAI |
|
||||||
| `bailian-coding-plan` | `https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1` | `https://coding.dashscope.aliyuncs.com/apps/anthropic/v1` | Anthropic |
|
| `bailian-coding-plan` | `https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1` | `https://token-plan.cn-beijing.maas.aliyuncs.com/apps/anthropic/v1` | Anthropic |
|
||||||
| `qwen-cloud` | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | OpenAI |
|
| `qwen-cloud` | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | OpenAI |
|
||||||
| `qwen-cloud-token-plan` | `https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1` | `https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1` | OpenAI |
|
| `qwen-cloud-token-plan` | `https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1` | `https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1` | OpenAI |
|
||||||
|
|
||||||
|
|||||||
@@ -1142,6 +1142,10 @@ Provider quota endpoints, network tunnels (Tailscale, Ngrok, MITM debug proxy),
|
|||||||
| `REDIS_URL` | `redis://localhost:6379` | `src/shared/utils/rateLimiter.ts` | Redis connection string for the rate limiter backend. |
|
| `REDIS_URL` | `redis://localhost:6379` | `src/shared/utils/rateLimiter.ts` | Redis connection string for the rate limiter backend. |
|
||||||
| `ALIBABA_CODING_PLAN_HOST` | _(production host)_ | `open-sse/services/bailianQuotaFetcher.ts` | Override the host used to fetch Alibaba Bailian coding-plan quotas. |
|
| `ALIBABA_CODING_PLAN_HOST` | _(production host)_ | `open-sse/services/bailianQuotaFetcher.ts` | Override the host used to fetch Alibaba Bailian coding-plan quotas. |
|
||||||
| `ALIBABA_CODING_PLAN_QUOTA_URL` | derived from host | `open-sse/services/bailianQuotaFetcher.ts` | Full quota URL override for Alibaba Bailian. |
|
| `ALIBABA_CODING_PLAN_QUOTA_URL` | derived from host | `open-sse/services/bailianQuotaFetcher.ts` | Full quota URL override for Alibaba Bailian. |
|
||||||
|
| `QWEN_CLOUD_COOKIE` | _(unset)_ | `open-sse/services/qwenTokenPlanQuotaFetcher.ts` | Console session cookie for the Qwen Cloud / Model Studio personal Token Plan quota gateway (the inference API key cannot read it). Copy the whole `Cookie` request header — it contains `login_qwencloud_ticket` — from any `api.json` call to `cs-data.qwencloud.com` on home.qwencloud.com › Billing › Subscription (F12 › Network). Sensitive and session-scoped; prefer the per-connection `qwenCloudCookie` Dashboard field. |
|
||||||
|
| `QWEN_CLOUD_SEC_TOKEN` | _(unset)_ | `open-sse/services/qwenTokenPlanQuotaFetcher.ts` | Manual `sec_token` override for the Token Plan console gateway. Sensitive; when unset the fetcher resolves it from the dashboard HTML using the cookie. |
|
||||||
|
| `QWEN_TOKEN_PLAN_HOST` | `https://cs-data.qwencloud.com` | `open-sse/services/qwenTokenPlanQuotaFetcher.ts` | Gateway host override for the personal Token Plan quota fetcher (e.g. `bailian-singapore-cs.alibabacloud.com` for the Model Studio console). |
|
||||||
|
| `QWEN_TOKEN_PLAN_DASHBOARD_URL` | `https://home.qwencloud.com/` | `open-sse/services/qwenTokenPlanQuotaFetcher.ts` | Dashboard URL used to resolve `sec_token` from the logged-in HTML. |
|
||||||
| `ALIBABA_FREE_TIER_VISION_FE_PATH` | `/costing-balance/free-quota-image-video` | `open-sse/services/alibabaFreeTierQuotaFetcher.ts` | Console front-end path override for fetching Alibaba Model Studio free-tier vision/media quota. |
|
| `ALIBABA_FREE_TIER_VISION_FE_PATH` | `/costing-balance/free-quota-image-video` | `open-sse/services/alibabaFreeTierQuotaFetcher.ts` | Console front-end path override for fetching Alibaba Model Studio free-tier vision/media quota. |
|
||||||
| `ALIBABA_FREE_TIER_MULTIMODAL_FE_PATH` | `/costing-balance/free-quota-multimodal` | `open-sse/services/alibabaFreeTierQuotaFetcher.ts` | Console front-end path override for fetching Alibaba Model Studio free-tier multimodal quota. |
|
| `ALIBABA_FREE_TIER_MULTIMODAL_FE_PATH` | `/costing-balance/free-quota-multimodal` | `open-sse/services/alibabaFreeTierQuotaFetcher.ts` | Console front-end path override for fetching Alibaba Model Studio free-tier multimodal quota. |
|
||||||
| `ALIBABA_FREE_TIER_AUDIO_FE_PATH` | `/costing-balance/free-quota-audio` | `open-sse/services/alibabaFreeTierQuotaFetcher.ts` | Console front-end path override for fetching Alibaba Model Studio free-tier audio quota. |
|
| `ALIBABA_FREE_TIER_AUDIO_FE_PATH` | `/costing-balance/free-quota-audio` | `open-sse/services/alibabaFreeTierQuotaFetcher.ts` | Console front-end path override for fetching Alibaba Model Studio free-tier audio quota. |
|
||||||
@@ -1348,17 +1352,24 @@ that should be able to run the docs translator.
|
|||||||
Optional add-on gated by the RADAR_ENABLED feature flag (default off — a feature
|
Optional add-on gated by the RADAR_ENABLED feature flag (default off — a feature
|
||||||
flag toggled via Settings/DB, not an env var; see
|
flag toggled via Settings/DB, not an env var; see
|
||||||
[docs/frameworks/RADAR.md](../frameworks/RADAR.md#flag-radar_enabled-default-off)).
|
[docs/frameworks/RADAR.md](../frameworks/RADAR.md#flag-radar_enabled-default-off)).
|
||||||
The four variables below are optional overrides used only to point the client at a
|
The first four variables below are optional overrides for a self-hosted or forked feed and
|
||||||
self-hosted or forked feed / supporter-key flow instead of the default OmniRoute
|
supporter-key flows. The fifth, `RADAR_ADMIN_URL`, is a separate default-free link to the owner's
|
||||||
Radar service. See [docs/frameworks/RADAR.md](../frameworks/RADAR.md) for the full
|
private operations panel. See [docs/frameworks/RADAR.md](../frameworks/RADAR.md) for the full
|
||||||
module doc.
|
module doc and its
|
||||||
|
[end-to-end activation and guided-setup sequence](../frameworks/RADAR.md#end-to-end-activation-and-guided-setup).
|
||||||
|
|
||||||
|
The generic Home/Changelog announcement reader is not configured by an environment
|
||||||
|
variable and does not depend on the RADAR_ENABLED feature flag. It reads the public repository
|
||||||
|
`news.json` URL declared in `src/shared/utils/releaseNotes.ts` by
|
||||||
|
GET only; dismissal IDs remain in browser local storage.
|
||||||
|
|
||||||
| Variable | Default | Source File | Description |
|
| Variable | Default | Source File | Description |
|
||||||
| -------------------------------- | --------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------ |
|
| -------------------------------- | --------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------ |
|
||||||
| `RADAR_FEED_URL` | `https://radar.omniroute.online` | `src/lib/radar/sync.ts` | Base URL of the Radar feed service. Override to point at a self-hosted or forked feed. |
|
| `RADAR_FEED_URL` | `https://radar.omniroute.online` | `src/lib/radar/{sync,referralsSync,offersSync,intelSync}.ts` | Base URL shared by the separately signed catalog, referrals, supporter-offers, and Intel feeds. Override to point at a self-hosted or forked service. |
|
||||||
| `RADAR_FEED_PUBKEY` | _(pinned default key)_ | `src/lib/radar/pinnedKeys.ts` | Ed25519 public key (base64-DER SPKI or PEM) used to verify feed signatures from a custom feed. |
|
| `RADAR_FEED_PUBKEY` | _(pinned default key)_ | `src/lib/radar/pinnedKeys.ts` | Ed25519 public key (base64-DER SPKI or PEM) used to verify feed signatures from a custom feed. |
|
||||||
| `RADAR_CONTRIBUTOR_CLAIM_URL` | `https://radar.omniroute.online/auth/github` | `src/lib/radar/links.ts` | URL the "I'm a contributor" dashboard button opens (GitHub OAuth supporter-key claim flow). |
|
| `RADAR_CONTRIBUTOR_CLAIM_URL` | `https://radar.omniroute.online/auth/github` | `src/lib/radar/links.ts` | URL the "I'm a contributor" dashboard button opens (GitHub OAuth supporter-key claim flow). |
|
||||||
| `RADAR_SUPPORTER_PLANS_URL` | `https://radar.omniroute.online/planos` | `src/lib/radar/links.ts` | URL the "Support the project" dashboard button opens (payment/plans page). |
|
| `RADAR_SUPPORTER_PLANS_URL` | `https://radar.omniroute.online/planos` | `src/lib/radar/links.ts` | URL the "Support the project" dashboard button opens (payment/plans page). |
|
||||||
|
| `RADAR_ADMIN_URL` | _(unset)_ | `src/lib/radar/links.ts` | Owner-only private operations-panel link. HTTPS is required except for an HTTP loopback SSH forward; unset or invalid values create no navigation item. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
24
llm.txt
24
llm.txt
@@ -1,6 +1,6 @@
|
|||||||
# OmniRoute
|
# OmniRoute
|
||||||
|
|
||||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 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.
|
> 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 (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@@ -14,7 +14,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"`)
|
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||||
- **State management:** Zustand (client), SQLite (server persistence)
|
- **State management:** Zustand (client), SQLite (server persistence)
|
||||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
- **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
|
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||||
@@ -102,7 +102,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||||
│ │ ├── compliance/ # Compliance policy engine
|
│ │ ├── compliance/ # Compliance policy engine
|
||||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||||
│ │ │ ├── models.ts # Model catalog management
|
│ │ │ ├── models.ts # Model catalog management
|
||||||
@@ -124,7 +124,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ │ ├── secrets.ts # Secrets management
|
│ │ │ ├── secrets.ts # Secrets management
|
||||||
│ │ │ ├── stateReset.ts # State reset utilities
|
│ │ │ ├── stateReset.ts # State reset utilities
|
||||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||||
│ │ ├── evals/ # Eval runner and scheduler
|
│ │ ├── evals/ # Eval runner and scheduler
|
||||||
│ │ ├── memory/ # Persistent conversational memory
|
│ │ ├── memory/ # Persistent conversational memory
|
||||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||||
@@ -207,11 +207,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ │ ├── moderations.ts # Content moderation
|
│ │ ├── moderations.ts # Content moderation
|
||||||
│ │ ├── rerank.ts # Reranking API
|
│ │ ├── rerank.ts # Reranking API
|
||||||
│ │ └── search.ts # Web search API
|
│ │ └── search.ts # Web search API
|
||||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||||
│ │ ├── audit.ts # Tool call audit logging
|
│ │ ├── audit.ts # Tool call audit logging
|
||||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||||
│ │ └── httpTransport.ts # HTTP transport handler
|
│ │ └── httpTransport.ts # HTTP transport handler
|
||||||
@@ -262,7 +262,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
|||||||
│ ├── i18n/ # 43-language translated docs
|
│ ├── i18n/ # 43-language translated docs
|
||||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
│ ├── 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
|
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
│ ├── frameworks/ # MCP-SERVER.md (109 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
|
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.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
|
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||||
@@ -345,9 +345,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)
|
- **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
|
- **ACP** — Agent Communication Protocol registry and manager
|
||||||
|
|
||||||
### MCP Server (105 Tools)
|
### MCP Server (109 Tools)
|
||||||
|
|
||||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||||
`docs/frameworks/MCP-SERVER.md`.
|
`docs/frameworks/MCP-SERVER.md`.
|
||||||
@@ -390,7 +390,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.
|
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 99 `src/lib/db/` modules with 117 SQL migrations.
|
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 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`.
|
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`.
|
||||||
|
|
||||||
@@ -434,7 +434,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`.
|
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, 145 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, 148 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.
|
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.
|
||||||
|
|
||||||
@@ -478,7 +478,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
|||||||
- **339-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`
|
- **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
|
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||||
|
|||||||
47
news.json
47
news.json
@@ -1,8 +1,43 @@
|
|||||||
{
|
{
|
||||||
"active": false,
|
"schemaVersion": 2,
|
||||||
"title": "Novidade no Omniverse",
|
"items": [
|
||||||
"message": "Está lançado hoje o tOmni, o terminal interativo múltiplo para Agentes de AI! Experimente a nova interface focada em produtividade para desenvolvedores.",
|
{
|
||||||
"link": "https://github.com/diegosouzapw/tOmni",
|
"id": "radar-launch-2026-08",
|
||||||
"linkLabel": "Conhecer o tOmni",
|
"active": false,
|
||||||
"icon": "campaign"
|
"publishedAt": "2026-08-09T00:00:00.000Z",
|
||||||
|
"text": {
|
||||||
|
"en": {
|
||||||
|
"title": "OmniRoute Radar",
|
||||||
|
"message": "An opt-in, GET-only free-model catalog overlay with no telemetry from the OmniRoute client.",
|
||||||
|
"linkLabel": "Learn about Radar"
|
||||||
|
},
|
||||||
|
"pt-BR": {
|
||||||
|
"title": "OmniRoute Radar",
|
||||||
|
"message": "Um catálogo opcional de modelos gratuitos, somente GET e sem telemetria enviada pelo cliente OmniRoute.",
|
||||||
|
"linkLabel": "Conheça o Radar"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"link": "https://radar.omniroute.online/planos",
|
||||||
|
"icon": "radar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tomni-launch-2026-07",
|
||||||
|
"active": false,
|
||||||
|
"publishedAt": "2026-07-01T00:00:00.000Z",
|
||||||
|
"text": {
|
||||||
|
"en": {
|
||||||
|
"title": "New in the Omniverse",
|
||||||
|
"message": "tOmni is an interactive multi-agent terminal focused on developer productivity.",
|
||||||
|
"linkLabel": "Meet tOmni"
|
||||||
|
},
|
||||||
|
"pt-BR": {
|
||||||
|
"title": "Novidade no Omniverse",
|
||||||
|
"message": "O tOmni é um terminal interativo para múltiplos agentes, focado na produtividade de desenvolvedores.",
|
||||||
|
"linkLabel": "Conhecer o tOmni"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"link": "https://github.com/diegosouzapw/tOmni",
|
||||||
|
"icon": "campaign"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,13 +30,15 @@ export type ProviderErrorRule = {
|
|||||||
export type ProviderErrorRuleMatch = {
|
export type ProviderErrorRuleMatch = {
|
||||||
reason: ConfiguredErrorReason;
|
reason: ConfiguredErrorReason;
|
||||||
/**
|
/**
|
||||||
* Intended lock scope. NOTE: this field is currently INFORMATIONAL — no
|
* Intended lock scope. #10334: this field is CONSUMED end-to-end only for
|
||||||
* consumer of `getProviderErrorRuleMatch` (checkFallbackError, combo.ts)
|
* providers in `HONORS_RULE_LOCK_SCOPE_PROVIDERS` (agentrouter-exclusive
|
||||||
* reads `scope` today; only `reason` and `cooldownMs` are consulted. The
|
* today, gated by `honorsRuleLockScope()`) — for those, `checkFallbackError`
|
||||||
* actual lock scope applied at runtime is decided independently by each
|
* surfaces it as `ruleScope` on its return value for the persistence layer
|
||||||
* call site (e.g. `hasPerModelQuota()` deciding model- vs connection-level
|
* to honor instead of re-deriving scope from `hasPerModelQuota()`. For
|
||||||
* lockout). Honoring this field end-to-end is tracked as a follow-up —
|
* every other provider it remains INFORMATIONAL: `getProviderErrorRuleMatch`
|
||||||
* see `docs/architecture/RESILIENCE_GUIDE.md` §7.
|
* callers still read only `reason`/`cooldownMs`, and the actual lock scope
|
||||||
|
* is decided independently by each call site. Widening the allowlist is
|
||||||
|
* tracked as a follow-up — see `docs/architecture/RESILIENCE_GUIDE.md` §7.
|
||||||
*/
|
*/
|
||||||
scope: "model" | "provider" | "connection";
|
scope: "model" | "provider" | "connection";
|
||||||
/** Optional explicit cooldown; falls back to the existing per-reason defaults. */
|
/** Optional explicit cooldown; falls back to the existing per-reason defaults. */
|
||||||
@@ -188,31 +190,29 @@ function buildOpenrouterRules(): ProviderErrorRule[] {
|
|||||||
// agentrouter.org misstates temporary quota exhaustion as 403/400 with a
|
// agentrouter.org misstates temporary quota exhaustion as 403/400 with a
|
||||||
// Chinese body. upstreamStatusRestatement.ts rewrites the status to 429
|
// Chinese body. upstreamStatusRestatement.ts rewrites the status to 429
|
||||||
// BEFORE classification, so rules here accept both the raw 403/400 and the
|
// BEFORE classification, so rules here accept both the raw 403/400 and the
|
||||||
// restated 429 (text is the real discriminator either way). In production,
|
// restated 429 (text is the real discriminator either way). Both the raw 403
|
||||||
// the raw 403 path is what actually matters here: checkFallbackError's
|
// path AND the restated 429 path reach these rules in production:
|
||||||
// apikey-category FORBIDDEN branch (~line 1699) returns EARLY for a plain
|
// checkFallbackError's `honorsRuleLockScope("agentrouter")` pre-check
|
||||||
// 403, before these rules are ever consulted — these rules fire on the
|
// (#10334) consults these rules BEFORE the generic apikey-category FORBIDDEN
|
||||||
// RESTATED 429 (chatCore's upstreamStatusRestatement hook runs first) via
|
// branch, and the restated 429 reaches them via the existing provider-rule
|
||||||
// resolveRuleMatchBody, which is the only path in checkFallbackError that
|
// lookup in the configured-rule branch. Both paths use resolveRuleMatchBody,
|
||||||
// hands these rules the full error text instead of just {code, type}.
|
// the only mechanism in checkFallbackError that hands agentrouter's rules the
|
||||||
|
// full error text instead of just {code, type}.
|
||||||
// - "额度不足": account-wide temporary quota → quota_exhausted, scope
|
// - "额度不足": account-wide temporary quota → quota_exhausted, scope
|
||||||
// "connection" (mirror of the Opencode account-wide rationale above).
|
// "connection" (mirror of the Opencode account-wide rationale above).
|
||||||
// NOTE: `scope` on ProviderErrorRuleMatch is currently informational —
|
// `scope` on ProviderErrorRuleMatch is CONSUMED for agentrouter (#10334,
|
||||||
// checkFallbackError/combo.ts only consume `reason` and `cooldownMs`, not
|
// exclusive allowlist via `honorsRuleLockScope`): checkFallbackError
|
||||||
// `scope`. For agentrouter specifically (passthroughModels: true →
|
// surfaces it as `ruleScope` on its return value. Whether the persistence
|
||||||
// hasPerModelQuota() is true), this quota_exhausted match actually
|
// layer (markAccountUnavailable / combo target exhaustion) actually
|
||||||
// resolves to a PER-MODEL lockout (recordModelLockoutFailure), not a
|
// switches from `hasPerModelQuota()`-derived scope to honoring `ruleScope`
|
||||||
// connection-wide lock — other models on the same account keep being
|
// is Tasks 2/3 of #10334 — this task only surfaces the field.
|
||||||
// tried by combo routing (each burning one call) until they lock out
|
|
||||||
// individually. Honoring `scope` end-to-end is tracked as a follow-up.
|
|
||||||
// - "无权访问模型": declares auth_error/scope "model" (intent: lock only the
|
// - "无权访问模型": declares auth_error/scope "model" (intent: lock only the
|
||||||
// model so the connection keeps serving the rest — Model Lockout tier).
|
// model so the connection keeps serving the rest — Model Lockout tier).
|
||||||
// This rule does NOT fire on the production path today: it only matches
|
// This rule now fires on the production 403 path (#10334): the
|
||||||
// `status === 403`, but checkFallbackError's apikey FORBIDDEN branch
|
// `honorsRuleLockScope` pre-check matches it and returns its declared
|
||||||
// returns early for a plain 403 before this rule is ever consulted (see
|
// reason/cooldown/scope before the generic apikey-FORBIDDEN early-return
|
||||||
// the note above). A live `无权访问模型` 403 is handled like the base
|
// ever runs. A live `无权访问模型` 403 therefore no longer falls through to
|
||||||
// apikey-provider 403 today. Wiring this rule into that path is tracked
|
// the base apikey-provider 403 handling.
|
||||||
// as a follow-up.
|
|
||||||
function buildAgentrouterRules(): ProviderErrorRule[] {
|
function buildAgentrouterRules(): ProviderErrorRule[] {
|
||||||
const AGENTROUTER_ERROR_STATUSES = new Set([400, 403, 429]);
|
const AGENTROUTER_ERROR_STATUSES = new Set([400, 403, 429]);
|
||||||
return [
|
return [
|
||||||
@@ -231,8 +231,15 @@ function buildAgentrouterRules(): ProviderErrorRule[] {
|
|||||||
if (status !== 403) return null;
|
if (status !== 403) return null;
|
||||||
const text = JSON.stringify(body ?? "").toLowerCase();
|
const text = JSON.stringify(body ?? "").toLowerCase();
|
||||||
if (!text.includes("无权访问模型")) return null;
|
if (!text.includes("无权访问模型")) return null;
|
||||||
// 6h: effectively "until the operator fixes the key's model grants",
|
// Declares a 6h cooldown, but the effective cooldown is NOT 6h: the
|
||||||
// without being an unrecoverable terminal state.
|
// model-lockout persistence layer (recordModelLockoutFailure, called from
|
||||||
|
// markAccountUnavailable) clamps every base cooldown — this one included —
|
||||||
|
// to the configured model-lockout maxCooldownMs, which defaults to
|
||||||
|
// 1_800_000ms / 30min (src/lib/resilience/modelLockoutSettings.ts,
|
||||||
|
// DEFAULT_MODEL_LOCKOUT_SETTINGS.maxCooldownMs). So in practice this is
|
||||||
|
// "locked for ~30min by default (up to 6h if an operator raises the model-
|
||||||
|
// lockout cap in settings)", not "until the operator fixes the key's model
|
||||||
|
// grants" — it is a recoverable window, not a real fix-driven unlock.
|
||||||
return { reason: "auth_error", scope: "model", cooldownMs: 6 * 60 * 60 * 1000 };
|
return { reason: "auth_error", scope: "model", cooldownMs: 6 * 60 * 60 * 1000 };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -255,6 +262,21 @@ export const providerRuleRegistry = new Map<string, ProviderErrorRule[]>([
|
|||||||
["agentrouter", buildAgentrouterRules()],
|
["agentrouter", buildAgentrouterRules()],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Providers whose ProviderErrorRuleMatch.scope is actually CONSUMED at the
|
||||||
|
* persistence layer (markAccountUnavailable / combo target exhaustion) to pick
|
||||||
|
* connection-vs-model lock scope. EXCLUSIVE allowlist by owner decision
|
||||||
|
* (2026-08-14, issue #10334) — deliberately SEPARATE from
|
||||||
|
* FULL_TEXT_RULE_PROVIDERS: that set controls what body a rule matches against
|
||||||
|
* (input), this one controls whether the matched scope changes caller behavior
|
||||||
|
* (output). A provider could need one without the other.
|
||||||
|
*/
|
||||||
|
const HONORS_RULE_LOCK_SCOPE_PROVIDERS = new Set(["agentrouter"]);
|
||||||
|
|
||||||
|
export function honorsRuleLockScope(provider: string | null | undefined): boolean {
|
||||||
|
return !!provider && HONORS_RULE_LOCK_SCOPE_PROVIDERS.has(provider.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Providers whose rules match on the FULL upstream error text.
|
* Providers whose rules match on the FULL upstream error text.
|
||||||
* checkFallbackError's rule lookup normally passes only the structured
|
* checkFallbackError's rule lookup normally passes only the structured
|
||||||
|
|||||||
@@ -60,7 +60,12 @@ export const bailian_coding_planProvider: RegistryEntry = {
|
|||||||
alias: "bcp",
|
alias: "bcp",
|
||||||
format: "claude",
|
format: "claude",
|
||||||
executor: "default",
|
executor: "default",
|
||||||
baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1",
|
// Token Plan endpoint (the catalog entry is "Alibaba Token Plan"). The former
|
||||||
|
// coding-intl.dashscope.aliyuncs.com host only accepts Coding Plan keys and rejects
|
||||||
|
// Token Plan keys with 401 invalid_api_key. Verified live 2026-08-14: this host
|
||||||
|
// returns 200 for every model below with the same key.
|
||||||
|
// Docs: https://www.alibabacloud.com/help/en/model-studio/more-tools
|
||||||
|
baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic/v1",
|
||||||
chatPath: "/messages",
|
chatPath: "/messages",
|
||||||
authType: "apikey",
|
authType: "apikey",
|
||||||
authHeader: "x-api-key",
|
authHeader: "x-api-key",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# OmniRoute MCP Server
|
# OmniRoute MCP Server
|
||||||
|
|
||||||
> **Model Context Protocol server** that exposes OmniRoute's gateway intelligence as **107 tools** for AI agents.
|
> **Model Context Protocol server** that exposes OmniRoute's gateway intelligence as **109 tools** for AI agents.
|
||||||
>
|
>
|
||||||
> **Source of truth for the full tool catalog and REST surface:** [`docs/frameworks/MCP-SERVER.md`](../../docs/frameworks/MCP-SERVER.md). This README focuses on architecture, configuration, and integration examples; the catalog below is a summary subset.
|
> **Source of truth for the full tool catalog and REST surface:** [`docs/frameworks/MCP-SERVER.md`](../../docs/frameworks/MCP-SERVER.md). This README focuses on architecture, configuration, and integration examples; the catalog below is a summary subset.
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ The MCP Server allows any AI agent (Claude Desktop, Cursor, VS Code Copilot, cus
|
|||||||
┌──────────────────────────────────────────────────────────────────┐
|
┌──────────────────────────────────────────────────────────────────┐
|
||||||
│ OmniRoute MCP Server │
|
│ OmniRoute MCP Server │
|
||||||
│ ┌──────────────┐ ┌─────────────────┐ ┌────────────────────┐ │
|
│ ┌──────────────┐ ┌─────────────────┐ ┌────────────────────┐ │
|
||||||
│ │ Scope │ │ 107 MCP Tools │ │ Audit Logger │ │
|
│ │ Scope │ │ 109 MCP Tools │ │ Audit Logger │ │
|
||||||
│ │ Enforcement │──│ (core + memory │──│ (SHA-256/SQLite) │ │
|
│ │ Enforcement │──│ (core + memory │──│ (SHA-256/SQLite) │ │
|
||||||
│ │ │ │ + skills + …) │ │ │ │
|
│ │ │ │ + skills + …) │ │ │ │
|
||||||
│ └──────────────┘ └────────┬────────┘ └────────────────────┘ │
|
│ └──────────────┘ └────────┬────────┘ └────────────────────┘ │
|
||||||
@@ -120,18 +120,23 @@ omniroute --mcp
|
|||||||
|
|
||||||
## Tool Reference
|
## Tool Reference
|
||||||
|
|
||||||
### Phase 1: Essential Tools (8)
|
### Phase 1: Essential Tools (13)
|
||||||
|
|
||||||
| # | Tool | Scopes | Description |
|
| # | Tool | Scopes | Description |
|
||||||
| --- | ------------------------------- | --------------------- | -------------------------------------------------------------------------- |
|
| --- | ------------------------------- | --------------------- | -------------------------------------------------------------------------- |
|
||||||
| 1 | `omniroute_get_health` | `read:health` | Gateway health, uptime, memory, circuit breakers, rate limits, cache stats |
|
| 1 | `omniroute_tool_search` | `read:tools` | Discover tools from the registered MCP catalog |
|
||||||
| 2 | `omniroute_list_combos` | `read:combos` | List all combos (model chains) with strategies and optional metrics |
|
| 2 | `omniroute_get_health` | `read:health` | Gateway health, uptime, memory, circuit breakers, rate limits, cache stats |
|
||||||
| 3 | `omniroute_get_combo_metrics` | `read:combos` | Performance metrics for a specific combo |
|
| 3 | `omniroute_list_combos` | `read:combos` | List all combos (model chains) with strategies and optional metrics |
|
||||||
| 4 | `omniroute_switch_combo` | `write:combos` | Activate or deactivate a combo for routing |
|
| 4 | `omniroute_get_combo_metrics` | `read:combos` | Performance metrics for a specific combo |
|
||||||
| 5 | `omniroute_check_quota` | `read:quota` | Remaining API quota per provider with token health status |
|
| 5 | `omniroute_switch_combo` | `write:combos` | Activate or deactivate a combo for routing |
|
||||||
| 6 | `omniroute_route_request` | `execute:completions` | Send a chat completion through intelligent routing |
|
| 6 | `omniroute_create_combo` | `write:combos` | Create a validated combo through the existing combo API |
|
||||||
| 7 | `omniroute_cost_report` | `read:usage` | Cost report by period (session/day/week/month) with per-provider breakdown |
|
| 7 | `omniroute_check_quota` | `read:quota` | Remaining API quota per provider with token health status |
|
||||||
| 8 | `omniroute_list_models_catalog` | `read:models` | List all available models across providers with capabilities and pricing |
|
| 8 | `omniroute_route_request` | `execute:completions` | Send a chat completion through intelligent routing |
|
||||||
|
| 9 | `omniroute_cost_report` | `read:usage` | Cost report by period (session/day/week/month) with per-provider breakdown |
|
||||||
|
| 10 | `omniroute_list_models_catalog` | `read:models` | List all available models across providers with capabilities and pricing |
|
||||||
|
| 11 | `omniroute_radar_catalog` | `read:radar` | Read the local signed Radar catalog with provider/family filters |
|
||||||
|
| 12 | `omniroute_web_search` | `execute:search` | Search the web through configured search providers |
|
||||||
|
| 13 | `omniroute_web_fetch` | `execute:search` | Fetch web content through configured fetch providers |
|
||||||
|
|
||||||
### Phase 2: Advanced Tools (8)
|
### Phase 2: Advanced Tools (8)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Unit tests for MCP Essential Tools (Phase 1)
|
* Unit tests for MCP Essential Tools (Phase 1)
|
||||||
*
|
*
|
||||||
* Tests all 10 essential tool handlers via the tool handler functions.
|
* Tests the essential tool handlers via the tool handler functions.
|
||||||
* The omniroute_web_search tests use InMemoryTransport + Client to exercise
|
* The omniroute_web_search tests use InMemoryTransport + Client to exercise
|
||||||
* the actual registered handler (not mockFetch directly).
|
* the actual registered handler (not mockFetch directly).
|
||||||
*/
|
*/
|
||||||
@@ -22,10 +22,10 @@ describe("MCP Essential Tools", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("Tool schema validation", () => {
|
describe("Tool schema validation", () => {
|
||||||
it("should have exactly 12 essential tools (includes web_search + web_fetch + tool_search)", () => {
|
it("should have exactly 13 essential tools (including Radar catalog)", () => {
|
||||||
// 11 -> 12: #8925 shipped omniroute_create_combo as a phase-1 tool.
|
// 12 -> 13: F3 shipped omniroute_radar_catalog as a phase-1 read-only tool.
|
||||||
const schemas = MCP_ESSENTIAL_TOOLS;
|
const schemas = MCP_ESSENTIAL_TOOLS;
|
||||||
expect(schemas).toHaveLength(12);
|
expect(schemas).toHaveLength(13);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("all tools should have omniroute_ prefix", () => {
|
it("all tools should have omniroute_ prefix", () => {
|
||||||
|
|||||||
151
open-sse/mcp-server/__tests__/radarCatalogTool.test.ts
Normal file
151
open-sse/mcp-server/__tests__/radarCatalogTool.test.ts
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
||||||
|
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
||||||
|
|
||||||
|
import { MCP_SCOPE_LIST, MCP_TOOL_SCOPES } from "../../../src/shared/constants/mcpScopes.ts";
|
||||||
|
import { evaluateToolScopes } from "../scopeEnforcement.ts";
|
||||||
|
import { getMcpRadarCatalog } from "../radarCatalog.ts";
|
||||||
|
import { MCP_ESSENTIAL_TOOLS, MCP_TOOL_MAP } from "../schemas/tools.ts";
|
||||||
|
import { createMcpServer } from "../server.ts";
|
||||||
|
|
||||||
|
vi.mock("../audit.ts", () => ({
|
||||||
|
logToolCall: vi.fn().mockResolvedValue(undefined),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const catalog = {
|
||||||
|
entries: [
|
||||||
|
{
|
||||||
|
provider: "groq",
|
||||||
|
modelId: "llama",
|
||||||
|
displayName: "Llama on Groq",
|
||||||
|
familyId: "llama-family",
|
||||||
|
monthlyTokens: 200,
|
||||||
|
creditTokens: 0,
|
||||||
|
freeType: "recurring-daily",
|
||||||
|
poolKey: null,
|
||||||
|
tos: "ok",
|
||||||
|
enabled: true,
|
||||||
|
origin: "radar",
|
||||||
|
capabilities: { tools: true, vision: false, thinking: false },
|
||||||
|
limits: { rpm: 30, rpd: null, tpm: null, tpd: null },
|
||||||
|
setup: { keyUrl: "https://secret.example/key", steps: ["do not expose"] },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provider: "cerebras",
|
||||||
|
modelId: "llama",
|
||||||
|
displayName: "Llama on Cerebras",
|
||||||
|
familyId: "llama-family",
|
||||||
|
monthlyTokens: 300,
|
||||||
|
creditTokens: 0,
|
||||||
|
freeType: "recurring-daily",
|
||||||
|
poolKey: null,
|
||||||
|
tos: "ok",
|
||||||
|
enabled: false,
|
||||||
|
disabledBy: "radar",
|
||||||
|
origin: "radar",
|
||||||
|
capabilities: { tools: true, vision: false, thinking: true },
|
||||||
|
limits: { rpm: null, rpd: 100, tpm: null, tpd: null },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
meta: { version: "2026.08.08.1", tier: "community", fetchedAt: "2026-08-08T20:00:00Z" },
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("omniroute_radar_catalog", () => {
|
||||||
|
it("is a phase-1 read-only registry tool with the dedicated Radar scope", () => {
|
||||||
|
const definition = MCP_TOOL_MAP.omniroute_radar_catalog;
|
||||||
|
expect(definition).toBeDefined();
|
||||||
|
expect(definition.phase).toBe(1);
|
||||||
|
expect(definition.scopes).toEqual(["read:radar"]);
|
||||||
|
expect(definition.auditLevel).toBe("none");
|
||||||
|
expect(definition.sourceEndpoints).toEqual(["/api/radar/catalog"]);
|
||||||
|
expect(MCP_ESSENTIAL_TOOLS).toContain(definition);
|
||||||
|
expect(MCP_SCOPE_LIST).toContain("read:radar");
|
||||||
|
expect(MCP_TOOL_SCOPES.omniroute_radar_catalog).toEqual(["read:radar"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reads only the local catalog and returns a closed filtered projection", async () => {
|
||||||
|
const fetchJson = vi.fn().mockResolvedValue(catalog);
|
||||||
|
const result = await getMcpRadarCatalog(
|
||||||
|
{ provider: "groq", familyId: "llama-family", enabledOnly: true },
|
||||||
|
{ fetchJson }
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(fetchJson).toHaveBeenCalledOnce();
|
||||||
|
expect(fetchJson).toHaveBeenCalledWith("/api/radar/catalog");
|
||||||
|
expect(result.models).toHaveLength(1);
|
||||||
|
expect(result.models[0]).toEqual({
|
||||||
|
provider: "groq",
|
||||||
|
modelId: "llama",
|
||||||
|
displayName: "Llama on Groq",
|
||||||
|
familyId: "llama-family",
|
||||||
|
quota: {
|
||||||
|
monthlyTokens: 200,
|
||||||
|
creditTokens: 0,
|
||||||
|
freeType: "recurring-daily",
|
||||||
|
limits: { rpm: 30, rpd: null, tpm: null, tpd: null },
|
||||||
|
},
|
||||||
|
capabilities: { tools: true, vision: false, thinking: false },
|
||||||
|
enabled: true,
|
||||||
|
origin: "radar",
|
||||||
|
disabledBy: null,
|
||||||
|
});
|
||||||
|
expect(JSON.stringify(result)).not.toContain("secret.example");
|
||||||
|
expect(JSON.stringify(result)).not.toContain("setup");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("defaults enabledOnly to true and includes disabled models only when explicitly requested", async () => {
|
||||||
|
const fetchJson = vi.fn().mockResolvedValue(catalog);
|
||||||
|
expect((await getMcpRadarCatalog({}, { fetchJson })).models).toHaveLength(1);
|
||||||
|
expect((await getMcpRadarCatalog({ enabledOnly: false }, { fetchJson })).models).toHaveLength(
|
||||||
|
2
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows read:radar and read:* but denies a missing scope when enforcement is active", () => {
|
||||||
|
expect(evaluateToolScopes("omniroute_radar_catalog", ["read:radar"], true).allowed).toBe(true);
|
||||||
|
expect(evaluateToolScopes("omniroute_radar_catalog", ["read:*"], true).allowed).toBe(true);
|
||||||
|
expect(evaluateToolScopes("omniroute_radar_catalog", [], true)).toMatchObject({
|
||||||
|
allowed: false,
|
||||||
|
reason: "missing_scopes",
|
||||||
|
missing: ["read:radar"],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("omniroute_radar_catalog MCP dispatch", () => {
|
||||||
|
const mockFetch = vi.fn();
|
||||||
|
let client: Client;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
mockFetch.mockReset();
|
||||||
|
vi.stubGlobal("fetch", mockFetch);
|
||||||
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
||||||
|
const server = createMcpServer();
|
||||||
|
await server.connect(serverTransport);
|
||||||
|
client = new Client({ name: "radar-catalog-test", version: "1.0.0" });
|
||||||
|
await client.connect(clientTransport);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await client.close();
|
||||||
|
vi.unstubAllGlobals();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("registers and dispatches a real read without sync or write", async () => {
|
||||||
|
mockFetch.mockResolvedValueOnce({ ok: true, json: async () => catalog });
|
||||||
|
|
||||||
|
const listed = await client.listTools();
|
||||||
|
expect(listed.tools.some((tool) => tool.name === "omniroute_radar_catalog")).toBe(true);
|
||||||
|
|
||||||
|
const result = await client.callTool({
|
||||||
|
name: "omniroute_radar_catalog",
|
||||||
|
arguments: { enabledOnly: false },
|
||||||
|
});
|
||||||
|
expect(result.isError).toBeFalsy();
|
||||||
|
expect(mockFetch).toHaveBeenCalledOnce();
|
||||||
|
expect(mockFetch.mock.calls[0][0]).toContain("/api/radar/catalog");
|
||||||
|
expect(mockFetch.mock.calls[0][1]).not.toMatchObject({ method: "POST" });
|
||||||
|
const body = JSON.parse((result.content[0] as { text: string }).text);
|
||||||
|
expect(body.models).toHaveLength(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
170
open-sse/mcp-server/radarCatalog.ts
Normal file
170
open-sse/mcp-server/radarCatalog.ts
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||||
|
|
||||||
|
import { logToolCall } from "./audit.ts";
|
||||||
|
import { radarCatalogInput, radarCatalogOutput } from "./schemas/radarCatalog.ts";
|
||||||
|
import type { McpToolExtraLike } from "./scopeEnforcement.ts";
|
||||||
|
import type { TextToolResult } from "./toolResult.ts";
|
||||||
|
import { sanitizeErrorMessage } from "../utils/error.ts";
|
||||||
|
|
||||||
|
type JsonRecord = Record<string, unknown>;
|
||||||
|
|
||||||
|
type ScopeEnforcer = (
|
||||||
|
toolName: string,
|
||||||
|
handler: (args: unknown, extra?: McpToolExtraLike) => Promise<TextToolResult>,
|
||||||
|
toolScopes?: readonly string[]
|
||||||
|
) => (args: unknown, extra?: McpToolExtraLike) => Promise<TextToolResult>;
|
||||||
|
|
||||||
|
export interface McpRadarCatalogArgs {
|
||||||
|
provider?: string;
|
||||||
|
familyId?: string;
|
||||||
|
enabledOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface McpRadarCatalogDeps {
|
||||||
|
fetchJson?: (path: string) => Promise<unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function record(value: unknown): JsonRecord {
|
||||||
|
return value !== null && typeof value === "object" && !Array.isArray(value)
|
||||||
|
? (value as JsonRecord)
|
||||||
|
: {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function text(value: unknown, fallback = ""): string {
|
||||||
|
return typeof value === "string" ? value : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
function number(value: unknown): number {
|
||||||
|
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nullableNumber(value: unknown): number | null {
|
||||||
|
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeMeta(
|
||||||
|
value: unknown
|
||||||
|
): { version: string; tier: string; fetchedAt: string } | null {
|
||||||
|
const meta = record(value);
|
||||||
|
if (
|
||||||
|
typeof meta.version !== "string" ||
|
||||||
|
typeof meta.tier !== "string" ||
|
||||||
|
typeof meta.fetchedAt !== "string"
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return { version: meta.version, tier: meta.tier, fetchedAt: meta.fetchedAt };
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeEntry(value: unknown) {
|
||||||
|
const entry = record(value);
|
||||||
|
const provider = text(entry.provider).trim();
|
||||||
|
const modelId = text(entry.modelId).trim();
|
||||||
|
if (!provider || !modelId) return null;
|
||||||
|
|
||||||
|
const capabilities = record(entry.capabilities);
|
||||||
|
const limits = record(entry.limits);
|
||||||
|
const origin =
|
||||||
|
entry.origin === "radar" || entry.origin === "local" ? entry.origin : ("baseline" as const);
|
||||||
|
return {
|
||||||
|
provider,
|
||||||
|
modelId,
|
||||||
|
displayName: text(entry.displayName, modelId),
|
||||||
|
familyId: typeof entry.familyId === "string" ? entry.familyId : null,
|
||||||
|
quota: {
|
||||||
|
monthlyTokens: number(entry.monthlyTokens),
|
||||||
|
creditTokens: number(entry.creditTokens),
|
||||||
|
freeType: text(entry.freeType, "unknown"),
|
||||||
|
limits:
|
||||||
|
Object.keys(limits).length > 0
|
||||||
|
? {
|
||||||
|
rpm: nullableNumber(limits.rpm),
|
||||||
|
rpd: nullableNumber(limits.rpd),
|
||||||
|
tpm: nullableNumber(limits.tpm),
|
||||||
|
tpd: nullableNumber(limits.tpd),
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
},
|
||||||
|
capabilities:
|
||||||
|
Object.keys(capabilities).length > 0
|
||||||
|
? {
|
||||||
|
tools: capabilities.tools === true,
|
||||||
|
vision: capabilities.vision === true,
|
||||||
|
thinking: capabilities.thinking === true,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
enabled: entry.enabled !== false,
|
||||||
|
origin,
|
||||||
|
disabledBy: entry.disabledBy === "radar" ? ("radar" as const) : null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function compareEntries(
|
||||||
|
left: NonNullable<ReturnType<typeof normalizeEntry>>,
|
||||||
|
right: NonNullable<ReturnType<typeof normalizeEntry>>
|
||||||
|
): number {
|
||||||
|
return left.provider.localeCompare(right.provider) || left.modelId.localeCompare(right.modelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Read and project the local Radar catalog without exposing setup or secret-bearing state. */
|
||||||
|
export async function getMcpRadarCatalog(
|
||||||
|
args: McpRadarCatalogArgs,
|
||||||
|
deps: McpRadarCatalogDeps = {}
|
||||||
|
) {
|
||||||
|
const fetchJson =
|
||||||
|
deps.fetchJson ??
|
||||||
|
((path: string) => import("./server.ts").then((module) => module.omniRouteFetch(path)));
|
||||||
|
const raw = record(await fetchJson("/api/radar/catalog"));
|
||||||
|
const providerFilter = args.provider?.trim().toLowerCase();
|
||||||
|
const familyFilter = args.familyId?.trim().toLowerCase();
|
||||||
|
const enabledOnly = args.enabledOnly !== false;
|
||||||
|
const entries = Array.isArray(raw.entries) ? raw.entries : [];
|
||||||
|
const models = entries
|
||||||
|
.map(normalizeEntry)
|
||||||
|
.filter((entry): entry is NonNullable<typeof entry> => entry !== null)
|
||||||
|
.filter((entry) => !enabledOnly || entry.enabled)
|
||||||
|
.filter((entry) => !providerFilter || entry.provider.toLowerCase() === providerFilter)
|
||||||
|
.filter((entry) => !familyFilter || entry.familyId?.toLowerCase() === familyFilter)
|
||||||
|
.sort(compareEntries);
|
||||||
|
|
||||||
|
return { meta: normalizeMeta(raw.meta), models };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleRadarCatalog(args: {
|
||||||
|
provider?: string;
|
||||||
|
familyId?: string;
|
||||||
|
enabledOnly: boolean;
|
||||||
|
}): Promise<TextToolResult> {
|
||||||
|
const start = Date.now();
|
||||||
|
try {
|
||||||
|
const result = radarCatalogOutput.parse(await getMcpRadarCatalog(args));
|
||||||
|
await logToolCall(
|
||||||
|
"omniroute_radar_catalog",
|
||||||
|
args,
|
||||||
|
{ modelCount: result.models.length },
|
||||||
|
Date.now() - start,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
||||||
|
} catch (error) {
|
||||||
|
const message = sanitizeErrorMessage(error) || "Failed to read Radar catalog";
|
||||||
|
await logToolCall("omniroute_radar_catalog", args, null, Date.now() - start, false, message);
|
||||||
|
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerRadarCatalogTool(
|
||||||
|
server: McpServer,
|
||||||
|
withScopeEnforcement: ScopeEnforcer
|
||||||
|
): void {
|
||||||
|
server.registerTool(
|
||||||
|
"omniroute_radar_catalog",
|
||||||
|
{
|
||||||
|
description: "Reads the local signed Radar catalog with optional provider and family filters",
|
||||||
|
inputSchema: radarCatalogInput,
|
||||||
|
},
|
||||||
|
withScopeEnforcement("omniroute_radar_catalog", (args) =>
|
||||||
|
handleRadarCatalog(radarCatalogInput.parse(args))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -91,6 +91,8 @@ export {
|
|||||||
ccrStatsTool,
|
ccrStatsTool,
|
||||||
} from "./tools.ts";
|
} from "./tools.ts";
|
||||||
|
|
||||||
|
export { radarCatalogInput, radarCatalogOutput, radarCatalogTool } from "./radarCatalog.ts";
|
||||||
|
|
||||||
// A2A schemas
|
// A2A schemas
|
||||||
export {
|
export {
|
||||||
AgentCardSchema,
|
AgentCardSchema,
|
||||||
|
|||||||
65
open-sse/mcp-server/schemas/radarCatalog.ts
Normal file
65
open-sse/mcp-server/schemas/radarCatalog.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import type { McpToolDefinition } from "./toolDefinition.ts";
|
||||||
|
|
||||||
|
export const radarCatalogInput = z.object({
|
||||||
|
provider: z.string().trim().min(1).max(100).optional().describe("Filter by provider id"),
|
||||||
|
familyId: z.string().trim().min(1).max(120).optional().describe("Filter by curated family id"),
|
||||||
|
enabledOnly: z.boolean().default(true).describe("Exclude models disabled by the Radar feed"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const radarLimitOutput = z.object({
|
||||||
|
rpm: z.number().nullable(),
|
||||||
|
rpd: z.number().nullable(),
|
||||||
|
tpm: z.number().nullable(),
|
||||||
|
tpd: z.number().nullable(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const radarCatalogOutput = z.object({
|
||||||
|
meta: z
|
||||||
|
.object({
|
||||||
|
version: z.string(),
|
||||||
|
tier: z.string(),
|
||||||
|
fetchedAt: z.string(),
|
||||||
|
})
|
||||||
|
.nullable(),
|
||||||
|
models: z.array(
|
||||||
|
z.object({
|
||||||
|
provider: z.string(),
|
||||||
|
modelId: z.string(),
|
||||||
|
displayName: z.string(),
|
||||||
|
familyId: z.string().nullable(),
|
||||||
|
quota: z.object({
|
||||||
|
monthlyTokens: z.number(),
|
||||||
|
creditTokens: z.number(),
|
||||||
|
freeType: z.string(),
|
||||||
|
limits: radarLimitOutput.nullable(),
|
||||||
|
}),
|
||||||
|
capabilities: z
|
||||||
|
.object({
|
||||||
|
tools: z.boolean(),
|
||||||
|
vision: z.boolean(),
|
||||||
|
thinking: z.boolean(),
|
||||||
|
})
|
||||||
|
.nullable(),
|
||||||
|
enabled: z.boolean(),
|
||||||
|
origin: z.enum(["baseline", "radar", "local"]),
|
||||||
|
disabledBy: z.literal("radar").nullable(),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const radarCatalogTool: McpToolDefinition<
|
||||||
|
typeof radarCatalogInput,
|
||||||
|
typeof radarCatalogOutput
|
||||||
|
> = {
|
||||||
|
name: "omniroute_radar_catalog",
|
||||||
|
description:
|
||||||
|
"Reads the local signed Radar catalog with optional provider and curated-family filters. Never syncs or writes data.",
|
||||||
|
inputSchema: radarCatalogInput,
|
||||||
|
outputSchema: radarCatalogOutput,
|
||||||
|
scopes: ["read:radar"],
|
||||||
|
auditLevel: "none",
|
||||||
|
phase: 1,
|
||||||
|
sourceEndpoints: ["/api/radar/catalog"],
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* MCP Tool Schemas — Contracts for all 23 core and advanced OmniRoute MCP tools.
|
* MCP Tool Schemas — Contracts for the canonical OmniRoute MCP tools.
|
||||||
*
|
*
|
||||||
* Defines input/output Zod schemas, descriptions, scopes, and audit levels
|
* Defines input/output Zod schemas, descriptions, scopes, and audit levels
|
||||||
* for both essential (Phase 1) and advanced (Phase 2) MCP tools.
|
* for both essential (Phase 1) and advanced (Phase 2) MCP tools.
|
||||||
@@ -13,11 +13,11 @@ import { z } from "zod";
|
|||||||
import { toolSearchTool } from "./toolSearch.ts";
|
import { toolSearchTool } from "./toolSearch.ts";
|
||||||
import { pickFastestModelTool } from "./pickFastestModel.ts";
|
import { pickFastestModelTool } from "./pickFastestModel.ts";
|
||||||
import { CCR_MCP_TOOLS } from "./ccrTools.ts";
|
import { CCR_MCP_TOOLS } from "./ccrTools.ts";
|
||||||
|
import { radarCatalogTool } from "./radarCatalog.ts";
|
||||||
import {
|
import {
|
||||||
AUTO_ROUTING_STRATEGY_VALUES,
|
AUTO_ROUTING_STRATEGY_VALUES,
|
||||||
ROUTING_STRATEGY_VALUES,
|
ROUTING_STRATEGY_VALUES,
|
||||||
} from "../../../src/shared/constants/routingStrategies.ts";
|
} from "../../../src/shared/constants/routingStrategies.ts";
|
||||||
|
|
||||||
// ============ Shared Types ============
|
// ============ Shared Types ============
|
||||||
// AuditLevel + McpToolDefinition live in the leaf ./toolDefinition.ts so that
|
// AuditLevel + McpToolDefinition live in the leaf ./toolDefinition.ts so that
|
||||||
// toolSearch.ts can import the type without forming a tools.ts ↔ toolSearch.ts cycle.
|
// toolSearch.ts can import the type without forming a tools.ts ↔ toolSearch.ts cycle.
|
||||||
@@ -26,8 +26,7 @@ export type { AuditLevel, McpToolDefinition } from "./toolDefinition.ts";
|
|||||||
import type { McpToolDefinition } from "./toolDefinition.ts";
|
import type { McpToolDefinition } from "./toolDefinition.ts";
|
||||||
export { pickFastestModelInput, pickFastestModelOutput } from "./pickFastestModel.ts";
|
export { pickFastestModelInput, pickFastestModelOutput } from "./pickFastestModel.ts";
|
||||||
export * from "./ccrTools.ts";
|
export * from "./ccrTools.ts";
|
||||||
|
// ============ Phase 1: Essential Tools ============
|
||||||
// ============ Phase 1: Essential Tools (8) ============
|
|
||||||
|
|
||||||
// --- Tool 1: omniroute_get_health ---
|
// --- Tool 1: omniroute_get_health ---
|
||||||
export const getHealthInput = z.object({}).describe("No parameters required");
|
export const getHealthInput = z.object({}).describe("No parameters required");
|
||||||
@@ -440,7 +439,7 @@ export const listModelsCatalogTool: McpToolDefinition<
|
|||||||
sourceEndpoints: ["/api/models/catalog", "/v1/models"],
|
sourceEndpoints: ["/api/models/catalog", "/v1/models"],
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Tool 9: omniroute_web_search ---
|
// --- Tool 10: omniroute_web_search ---
|
||||||
export const webSearchInput = z.object({
|
export const webSearchInput = z.object({
|
||||||
query: z
|
query: z
|
||||||
.string()
|
.string()
|
||||||
@@ -1519,6 +1518,7 @@ export const MCP_TOOLS = [
|
|||||||
routeRequestTool,
|
routeRequestTool,
|
||||||
costReportTool,
|
costReportTool,
|
||||||
listModelsCatalogTool,
|
listModelsCatalogTool,
|
||||||
|
radarCatalogTool,
|
||||||
webSearchTool,
|
webSearchTool,
|
||||||
webFetchTool,
|
webFetchTool,
|
||||||
simulateRouteTool,
|
simulateRouteTool,
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ import { normalizeQuotaResponse } from "../../src/shared/contracts/quota.ts";
|
|||||||
import { resolveOmniRouteBaseUrl } from "../../src/shared/utils/resolveOmniRouteBaseUrl.ts";
|
import { resolveOmniRouteBaseUrl } from "../../src/shared/utils/resolveOmniRouteBaseUrl.ts";
|
||||||
import { sanitizeErrorMessage } from "../utils/error.ts";
|
import { sanitizeErrorMessage } from "../utils/error.ts";
|
||||||
import { getMcpModelsCatalog } from "./catalog.ts";
|
import { getMcpModelsCatalog } from "./catalog.ts";
|
||||||
|
import { registerRadarCatalogTool } from "./radarCatalog.ts";
|
||||||
|
import type { TextToolResult } from "./toolResult.ts";
|
||||||
export { getMcpModelsCatalog } from "./catalog.ts";
|
export { getMcpModelsCatalog } from "./catalog.ts";
|
||||||
|
|
||||||
const OMNIROUTE_BASE_URL = resolveOmniRouteBaseUrl();
|
const OMNIROUTE_BASE_URL = resolveOmniRouteBaseUrl();
|
||||||
@@ -146,11 +148,6 @@ function readMcpAccessibilityConfig(): McpAccessibilityConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type TextToolResult = {
|
|
||||||
content: Array<{ type: "text"; text: string }>;
|
|
||||||
isError?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
function toRecord(value: unknown): JsonRecord {
|
function toRecord(value: unknown): JsonRecord {
|
||||||
return value && typeof value === "object" && !Array.isArray(value) ? (value as JsonRecord) : {};
|
return value && typeof value === "object" && !Array.isArray(value) ? (value as JsonRecord) : {};
|
||||||
}
|
}
|
||||||
@@ -842,6 +839,8 @@ export function createMcpServer(): McpServer {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
registerRadarCatalogTool(server, withScopeEnforcement);
|
||||||
|
|
||||||
server.registerTool(
|
server.registerTool(
|
||||||
"omniroute_simulate_route",
|
"omniroute_simulate_route",
|
||||||
{
|
{
|
||||||
|
|||||||
4
open-sse/mcp-server/toolResult.ts
Normal file
4
open-sse/mcp-server/toolResult.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export type TextToolResult = {
|
||||||
|
content: Array<{ type: "text"; text: string }>;
|
||||||
|
isError?: boolean;
|
||||||
|
};
|
||||||
@@ -15,7 +15,11 @@ import {
|
|||||||
serviceSupervisorCooldown,
|
serviceSupervisorCooldown,
|
||||||
isNimFunctionDegraded,
|
isNimFunctionDegraded,
|
||||||
} from "../config/errorConfig.ts";
|
} from "../config/errorConfig.ts";
|
||||||
import { getProviderErrorRuleMatch, resolveRuleMatchBody } from "../config/providerErrorRules.ts";
|
import {
|
||||||
|
getProviderErrorRuleMatch,
|
||||||
|
resolveRuleMatchBody,
|
||||||
|
honorsRuleLockScope,
|
||||||
|
} from "../config/providerErrorRules.ts";
|
||||||
import * as rot from "./rotationConfig.ts";
|
import * as rot from "./rotationConfig.ts";
|
||||||
import { getPassthroughProviders, getProviderCategory } from "../config/providerRegistry.ts";
|
import { getPassthroughProviders, getProviderCategory } from "../config/providerRegistry.ts";
|
||||||
import {
|
import {
|
||||||
@@ -1458,6 +1462,11 @@ export function checkFallbackError(
|
|||||||
/** #6061: the provider-configured cooldown (ms) before backoff scaling, surfaced so the
|
/** #6061: the provider-configured cooldown (ms) before backoff scaling, surfaced so the
|
||||||
* caller can persist an explicit reset window instead of the engine's scaled cooldown. */
|
* caller can persist an explicit reset window instead of the engine's scaled cooldown. */
|
||||||
configuredCooldownMs?: number;
|
configuredCooldownMs?: number;
|
||||||
|
/** #10334 — the matched ProviderErrorRule's declared lock scope, surfaced so the
|
||||||
|
* persistence layer can honor it instead of re-deriving scope from
|
||||||
|
* hasPerModelQuota(). Populated ONLY when honorsRuleLockScope(provider) is true;
|
||||||
|
* always undefined for every other provider, so existing consumers are unaffected. */
|
||||||
|
ruleScope?: "model" | "provider" | "connection";
|
||||||
} {
|
} {
|
||||||
// #10360: an executor-result contract violation is OUR bug, not the provider's.
|
// #10360: an executor-result contract violation is OUR bug, not the provider's.
|
||||||
// Retrying reproduces it verbatim, and cooling the connection down (or tripping
|
// Retrying reproduces it verbatim, and cooling the connection down (or tripping
|
||||||
@@ -1712,6 +1721,36 @@ export function checkFallbackError(
|
|||||||
return { shouldFallback: false, cooldownMs: 0, reason: RateLimitReason.UNKNOWN };
|
return { shouldFallback: false, cooldownMs: 0, reason: RateLimitReason.UNKNOWN };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #10334 — agentrouter EXCLUSIVE: consult the provider rules BEFORE the
|
||||||
|
// apikey-FORBIDDEN early-return below, so a recognized 403 body (e.g.
|
||||||
|
// "无权访问模型") carries the rule's declared reason/cooldown/scope instead of
|
||||||
|
// the generic short auth cooldown. Gated on honorsRuleLockScope — for any
|
||||||
|
// other provider this block is a no-op and the early-return stays identical.
|
||||||
|
if (status === HTTP_STATUS.FORBIDDEN && provider && honorsRuleLockScope(provider)) {
|
||||||
|
const forbiddenMatch = getProviderErrorRuleMatch(
|
||||||
|
provider,
|
||||||
|
status,
|
||||||
|
headers,
|
||||||
|
resolveRuleMatchBody(provider, structuredError ?? null, errorStr)
|
||||||
|
);
|
||||||
|
if (forbiddenMatch) {
|
||||||
|
const scaled = getScaledBaseCooldown(
|
||||||
|
forbiddenMatch.reason as RateLimitReasonValue,
|
||||||
|
backoffLevel
|
||||||
|
);
|
||||||
|
const ruleCooldownMs = forbiddenMatch.cooldownMs;
|
||||||
|
return {
|
||||||
|
shouldFallback: true,
|
||||||
|
cooldownMs: ruleCooldownMs ?? scaled.cooldownMs,
|
||||||
|
baseCooldownMs: ruleCooldownMs ?? scaled.baseCooldownMs,
|
||||||
|
configuredCooldownMs: ruleCooldownMs,
|
||||||
|
newBackoffLevel: ruleCooldownMs !== undefined ? 0 : scaled.newBackoffLevel,
|
||||||
|
reason: forbiddenMatch.reason,
|
||||||
|
ruleScope: forbiddenMatch.scope,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
status === HTTP_STATUS.FORBIDDEN &&
|
status === HTTP_STATUS.FORBIDDEN &&
|
||||||
provider &&
|
provider &&
|
||||||
@@ -1764,6 +1803,8 @@ export function checkFallbackError(
|
|||||||
providerMatch?.cooldownMs !== undefined && providerMatch.cooldownMs > 0
|
providerMatch?.cooldownMs !== undefined && providerMatch.cooldownMs > 0
|
||||||
? providerMatch.cooldownMs
|
? providerMatch.cooldownMs
|
||||||
: undefined;
|
: undefined;
|
||||||
|
const ruleScope =
|
||||||
|
providerMatch && honorsRuleLockScope(provider) ? providerMatch.scope : undefined;
|
||||||
const fallback = buildRetryableFallback(reason);
|
const fallback = buildRetryableFallback(reason);
|
||||||
if (providerCooldownMs !== undefined) {
|
if (providerCooldownMs !== undefined) {
|
||||||
return {
|
return {
|
||||||
@@ -1771,9 +1812,10 @@ export function checkFallbackError(
|
|||||||
cooldownMs: providerCooldownMs,
|
cooldownMs: providerCooldownMs,
|
||||||
baseCooldownMs: providerCooldownMs,
|
baseCooldownMs: providerCooldownMs,
|
||||||
configuredCooldownMs: providerCooldownMs,
|
configuredCooldownMs: providerCooldownMs,
|
||||||
|
ruleScope,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return fallback;
|
return { ...fallback, ruleScope };
|
||||||
}
|
}
|
||||||
// #6842: non-backoff configured rules (e.g. status_402) previously never
|
// #6842: non-backoff configured rules (e.g. status_402) previously never
|
||||||
// consulted providerRuleRegistry, so a provider-specific rule (like
|
// consulted providerRuleRegistry, so a provider-specific rule (like
|
||||||
@@ -1789,12 +1831,15 @@ export function checkFallbackError(
|
|||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
const cooldownMs = providerMatch?.cooldownMs ?? configuredRule.cooldownMs ?? 0;
|
const cooldownMs = providerMatch?.cooldownMs ?? configuredRule.cooldownMs ?? 0;
|
||||||
|
const ruleScope =
|
||||||
|
providerMatch && honorsRuleLockScope(provider) ? providerMatch.scope : undefined;
|
||||||
return {
|
return {
|
||||||
shouldFallback: true,
|
shouldFallback: true,
|
||||||
cooldownMs,
|
cooldownMs,
|
||||||
baseCooldownMs: cooldownMs,
|
baseCooldownMs: cooldownMs,
|
||||||
configuredCooldownMs: cooldownMs,
|
configuredCooldownMs: cooldownMs,
|
||||||
reason: providerMatch?.reason ?? configuredRule.reason ?? RateLimitReason.UNKNOWN,
|
reason: providerMatch?.reason ?? configuredRule.reason ?? RateLimitReason.UNKNOWN,
|
||||||
|
ruleScope,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ import {
|
|||||||
import { RateLimitReason } from "../../config/constants.ts";
|
import { RateLimitReason } from "../../config/constants.ts";
|
||||||
import { isProviderCircuitOpenResult, isRequestScopedUpstreamFailure } from "./comboPredicates.ts";
|
import { isProviderCircuitOpenResult, isRequestScopedUpstreamFailure } from "./comboPredicates.ts";
|
||||||
import { isCloudflareFingerprintRejection } from "../errorClassifier.ts";
|
import { isCloudflareFingerprintRejection } from "../errorClassifier.ts";
|
||||||
|
// #10334 — agentrouter-exclusive predicate shared with the persistence layer
|
||||||
|
// (markAccountUnavailable) so the same-request combo skip and the persisted
|
||||||
|
// connection cooldown agree on exactly which fallbackResult shapes qualify.
|
||||||
|
import { isAgentrouterConnectionQuotaScope } from "@/sse/services/auth";
|
||||||
import type { ComboLogger, ResolvedComboTarget } from "./types.ts";
|
import type { ComboLogger, ResolvedComboTarget } from "./types.ts";
|
||||||
|
|
||||||
// Connection-level failure statuses: the provider connection itself is likely bad (upstream
|
// Connection-level failure statuses: the provider connection itself is likely bad (upstream
|
||||||
@@ -60,7 +64,13 @@ export type ComboExhaustionSets = {
|
|||||||
|
|
||||||
export type ApplyComboTargetExhaustionOptions = {
|
export type ApplyComboTargetExhaustionOptions = {
|
||||||
result: { status: number; headers?: Headers | null };
|
result: { status: number; headers?: Headers | null };
|
||||||
fallbackResult: Parameters<typeof isProviderExhaustedReason>[0];
|
fallbackResult: Parameters<typeof isProviderExhaustedReason>[0] & {
|
||||||
|
/** #10334 — agentrouter-exclusive; see isAgentrouterConnectionQuotaScope
|
||||||
|
* (src/sse/services/auth.ts). Populated only for providers in
|
||||||
|
* HONORS_RULE_LOCK_SCOPE_PROVIDERS (today: agentrouter only). */
|
||||||
|
ruleScope?: "model" | "provider" | "connection";
|
||||||
|
permanent?: boolean;
|
||||||
|
};
|
||||||
errorText: string;
|
errorText: string;
|
||||||
rawModel: string;
|
rawModel: string;
|
||||||
isTokenLimitBreach: boolean;
|
isTokenLimitBreach: boolean;
|
||||||
@@ -86,6 +96,56 @@ export function applyComboTargetExhaustion(
|
|||||||
const { result, sets, log, tag, errorText, structuredError } = opts;
|
const { result, sets, log, tag, errorText, structuredError } = opts;
|
||||||
const provider = target.provider;
|
const provider = target.provider;
|
||||||
|
|
||||||
|
// #10334: agentrouter-exclusive account-wide quota exhaustion ("额度不足")
|
||||||
|
// must skip remaining SAME-CONNECTION targets within THIS request too, not
|
||||||
|
// just via the persisted cooldown markAccountUnavailable applies for
|
||||||
|
// whichever leg runs next. agentrouter is a passthroughModels provider
|
||||||
|
// (hasPerModelQuota() === true), so without this branch the classification
|
||||||
|
// below would fall straight through isProviderQuotaExhausted's
|
||||||
|
// !hasPerModelQuota() guard, and — for the restated-429 case —
|
||||||
|
// markConnectionLevelExhaustion's connection-level guard (429 is not in
|
||||||
|
// CONNECTION_LEVEL_ERROR_STATUSES), marking nothing: combo would keep
|
||||||
|
// burning one upstream call per remaining model of the same exhausted
|
||||||
|
// account. isAgentrouterConnectionQuotaScope is the same guard
|
||||||
|
// markAccountUnavailable uses, so both consumers agree on exactly which
|
||||||
|
// fallbackResult shapes qualify (never a permanent/credits-exhausted
|
||||||
|
// result, even one carrying ruleScope "connection").
|
||||||
|
//
|
||||||
|
// Runs BEFORE the auth-level (401/403) branch below. This is deliberate,
|
||||||
|
// not incidental: the "额度不足" rule matches statuses {400, 403, 429}
|
||||||
|
// (buildAgentrouterRules, providerErrorRules.ts), and Task 1's FORBIDDEN
|
||||||
|
// pre-check (accountFallback.ts ~1729-1751) surfaces `ruleScope:
|
||||||
|
// "connection"` for a RAW 403 carrying that body too — so this branch can
|
||||||
|
// also fire on a 403, not just the restated 429. That is safe: for a 403
|
||||||
|
// this branch and markAuthLevelExhaustion below write the SAME set with
|
||||||
|
// the SAME `${provider}:${connId}` key and both return `true` — they are
|
||||||
|
// set-equivalent for agentrouter on that status. The Cloudflare-1010 and
|
||||||
|
// Alibaba free-tier EXEMPTIONS further down in the 401/403 branch cannot
|
||||||
|
// apply here regardless of ordering: 1010 is a CDN fingerprint rejection
|
||||||
|
// agentrouter's own text never carries, and the Alibaba exemption is
|
||||||
|
// gated on isAlibabaModelStudioProvider(provider), which agentrouter is
|
||||||
|
// not.
|
||||||
|
//
|
||||||
|
// Unlike the connection-level/auth-level branches, this path deliberately
|
||||||
|
// does NOT fall through to markTransientOrConnectionLevel, so
|
||||||
|
// sets.transientRateLimitedProviders is NEVER populated for this failure.
|
||||||
|
// That is required, not just incidental: combo.ts (both dispatchers, see
|
||||||
|
// the `allowRateLimitedConnection` reads keyed off
|
||||||
|
// transientRateLimitedProviders) uses that set to force-allow reusing a
|
||||||
|
// rate-limited CONNECTION for the provider's remaining legs — i.e. it
|
||||||
|
// bypasses the very `rateLimitedUntil` filter this branch (and Task 2's
|
||||||
|
// markAccountUnavailable) just set. Marking it here would silently
|
||||||
|
// re-open the account this branch just cooled down. One secondary
|
||||||
|
// consequence: a SIBLING agentrouter connection that is merely
|
||||||
|
// rate-limited (not the one this branch exhausted) will also no longer be
|
||||||
|
// force-allowed for a later leg on the same provider — a remaining leg
|
||||||
|
// can now resolve to "no credentials available" instead of retrying a
|
||||||
|
// rate-limited sibling account, which is the intended, safer outcome.
|
||||||
|
if (isAgentrouterConnectionQuotaScope(provider, opts.fallbackResult)) {
|
||||||
|
markAgentrouterConnectionQuotaExhaustion(target, { sets, log, tag });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// #8133/#8137: auth-level failures (401/403) mean that connection's credentials are bad.
|
// #8133/#8137: auth-level failures (401/403) mean that connection's credentials are bad.
|
||||||
// Split out to keep applyComboTargetExhaustion under the complexity ceiling.
|
// Split out to keep applyComboTargetExhaustion under the complexity ceiling.
|
||||||
// Cloudflare 1010 (a 403 carrying error_code 1010 / browser_signature_banned) is NOT an
|
// Cloudflare 1010 (a 403 carrying error_code 1010 / browser_signature_banned) is NOT an
|
||||||
@@ -259,6 +319,35 @@ function markAuthLevelExhaustion(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* #10334: agentrouter-exclusive connection-scope account quota exhaustion. Mirrors
|
||||||
|
* markAuthLevelExhaustion's connectionId-present/absent split — when the target carries a
|
||||||
|
* connectionId, only that connection's account is exhausted (sibling agentrouter connections
|
||||||
|
* for the same user may still have quota); fall back to whole-provider exhaustion only when no
|
||||||
|
* connectionId is available.
|
||||||
|
*/
|
||||||
|
function markAgentrouterConnectionQuotaExhaustion(
|
||||||
|
target: ResolvedComboTarget,
|
||||||
|
opts: Pick<ApplyComboTargetExhaustionOptions, "sets" | "log" | "tag">
|
||||||
|
): void {
|
||||||
|
const { sets, log, tag } = opts;
|
||||||
|
const provider = target.provider;
|
||||||
|
const connId = target.connectionId ?? undefined;
|
||||||
|
if (connId) {
|
||||||
|
sets.exhaustedConnections.add(`${provider}:${connId}`);
|
||||||
|
log.info(
|
||||||
|
tag,
|
||||||
|
`Provider ${provider} connection ${connId} account quota exhausted (rule scope=connection) — marking for skip on remaining targets (#10334)`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
sets.exhaustedProviders.add(provider as string);
|
||||||
|
log.info(
|
||||||
|
tag,
|
||||||
|
`Provider ${provider} account quota exhausted (rule scope=connection, no connectionId) — marking for skip on remaining targets (#10334)`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* #1731v2: connection-level errors (408/5xx, excluding the OmniRoute circuit-open signal) suggest
|
* #1731v2: connection-level errors (408/5xx, excluding the OmniRoute circuit-open signal) suggest
|
||||||
* the provider connection itself is bad → skip remaining same-connection (or same-provider, when
|
* the provider connection itself is bad → skip remaining same-connection (or same-provider, when
|
||||||
|
|||||||
437
open-sse/services/qwenTokenPlanQuotaFetcher.ts
Normal file
437
open-sse/services/qwenTokenPlanQuotaFetcher.ts
Normal file
@@ -0,0 +1,437 @@
|
|||||||
|
/**
|
||||||
|
* qwenTokenPlanQuotaFetcher.ts — Qwen Cloud / Alibaba Model Studio PERSONAL Token Plan
|
||||||
|
* quota fetcher (issue #9603, "quota is missing").
|
||||||
|
*
|
||||||
|
* The personal Token Plan (5-hour / 7-day sliding windows) has NO official OpenAPI —
|
||||||
|
* the console gateway is the only quota surface, and the inference API key does NOT
|
||||||
|
* authenticate it. Both portals read the same backend:
|
||||||
|
* - home.qwencloud.com portal → https://cs-data.qwencloud.com (default)
|
||||||
|
* - Model Studio console (intl) → https://bailian-singapore-cs.alibabacloud.com
|
||||||
|
*
|
||||||
|
* Transport (captured live 2026-08-13 from a logged-in session):
|
||||||
|
* POST {host}/data/api.json?product=sfm_bailian&action=IntlBroadScopeAspnGateway
|
||||||
|
* &api=zeldaHttp.apikeyMgr.%2Ftokenplan%2Fpersonal%2Fapi%2Fv2%2F<endpoint>
|
||||||
|
* form body: product, action, sec_token, region, params =
|
||||||
|
* {"Api":"zeldaHttp.apikeyMgr./tokenplan/personal/api/v2/<endpoint>","V":"1.0",
|
||||||
|
* "Data":{"commodityCode":"sfm_tokenplansolo_public_intl","cornerstoneParam":{...}}}
|
||||||
|
* Auth: browser session Cookie (providerSpecificData or QWEN_CLOUD_COOKIE env).
|
||||||
|
* sec_token: best-effort — resolved from the dashboard HTML (`SEC_TOKEN: "…"`) when
|
||||||
|
* not provided; some accounts reject requests without it
|
||||||
|
* (BailianGateway.Workspace.NotAuthorised).
|
||||||
|
*
|
||||||
|
* Windows: usage returns per<Window>Percentage (fraction used, 0..1) +
|
||||||
|
* per<Window>ResetTime (epoch ms). Fields are OMITTED while a window is
|
||||||
|
* "Temporarily Removed" (observed for 5-hour), so every window is optional.
|
||||||
|
*
|
||||||
|
* Cache: usage 60s per connection; subscription/quota-config (slow-moving tier data)
|
||||||
|
* 1h per connection. Registration: registerQwenTokenPlanQuotaFetcher() at startup.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { registerQuotaFetcher, registerQuotaWindows, type QuotaInfo } from "./quotaPreflight.ts";
|
||||||
|
import { registerMonitorFetcher } from "./quotaMonitor.ts";
|
||||||
|
import { throttleQuotaFetch } from "./quotaFetchThrottle.ts";
|
||||||
|
|
||||||
|
const DEFAULT_GATEWAY_HOST = "https://cs-data.qwencloud.com";
|
||||||
|
const DEFAULT_DASHBOARD_URL = "https://home.qwencloud.com/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same personal Token Plan is sold through two consoles that share one backend.
|
||||||
|
* The gateway validates the browser session against the console identity sent in the
|
||||||
|
* request, so an Alibaba cookie paired with the QwenCloud identity is rejected with
|
||||||
|
* `BailianGateway.Login.NotLogined` (verified live 2026-08-14).
|
||||||
|
*/
|
||||||
|
export interface TokenPlanConsoleSite {
|
||||||
|
consoleSite: "QWENCLOUD" | "ALIYUN";
|
||||||
|
domain: string;
|
||||||
|
gatewayHost: string;
|
||||||
|
dashboardUrl: string;
|
||||||
|
origin: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CONSOLE_SITES: Record<"qwencloud" | "aliyun", TokenPlanConsoleSite> = {
|
||||||
|
qwencloud: {
|
||||||
|
consoleSite: "QWENCLOUD",
|
||||||
|
domain: "home.qwencloud.com",
|
||||||
|
gatewayHost: DEFAULT_GATEWAY_HOST,
|
||||||
|
dashboardUrl: DEFAULT_DASHBOARD_URL,
|
||||||
|
origin: "https://home.qwencloud.com",
|
||||||
|
},
|
||||||
|
aliyun: {
|
||||||
|
consoleSite: "ALIYUN",
|
||||||
|
domain: "modelstudio.console.alibabacloud.com",
|
||||||
|
gatewayHost: "https://bailian-singapore-cs.alibabacloud.com",
|
||||||
|
dashboardUrl: "https://modelstudio.console.alibabacloud.com/",
|
||||||
|
origin: "https://modelstudio.console.alibabacloud.com",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Providers served by the Alibaba (Model Studio) console rather than QwenCloud. */
|
||||||
|
const ALIYUN_CONSOLE_PROVIDERS = new Set(["bailian-coding-plan", "alibaba", "alibaba-cn"]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick the console identity for a cookie: the login ticket names its console
|
||||||
|
* (`login_aliyunid_ticket` vs `login_qwencloud_ticket`). Unmarked cookies fall back to
|
||||||
|
* the provider, then to QwenCloud.
|
||||||
|
*/
|
||||||
|
export function resolveConsoleSite(
|
||||||
|
cookie: string,
|
||||||
|
provider: string | undefined
|
||||||
|
): TokenPlanConsoleSite {
|
||||||
|
if (/login_aliyunid_ticket=/.test(cookie)) return CONSOLE_SITES.aliyun;
|
||||||
|
if (/login_qwencloud_ticket=/.test(cookie)) return CONSOLE_SITES.qwencloud;
|
||||||
|
if (provider && ALIYUN_CONSOLE_PROVIDERS.has(provider)) return CONSOLE_SITES.aliyun;
|
||||||
|
return CONSOLE_SITES.qwencloud;
|
||||||
|
}
|
||||||
|
const GATEWAY_REGION = "ap-southeast-1";
|
||||||
|
const GATEWAY_PRODUCT = "sfm_bailian";
|
||||||
|
const GATEWAY_ACTION = "IntlBroadScopeAspnGateway";
|
||||||
|
const COMMODITY_CODE = "sfm_tokenplansolo_public_intl";
|
||||||
|
const TOKEN_PLAN_API_PREFIX = "zeldaHttp.apikeyMgr./tokenplan/personal/api/v2/";
|
||||||
|
|
||||||
|
const USAGE_CACHE_TTL_MS = 60_000;
|
||||||
|
const TIER_CACHE_TTL_MS = 60 * 60_000;
|
||||||
|
|
||||||
|
// Window keys surfaced to the dashboard / quota-window registry
|
||||||
|
export const QWEN_TOKEN_PLAN_WINDOW_5H = "window_5h";
|
||||||
|
export const QWEN_TOKEN_PLAN_WINDOW_WEEKLY = "window_weekly";
|
||||||
|
|
||||||
|
// usage payload field prefix → window key (fields: per<prefix>Percentage / per<prefix>ResetTime)
|
||||||
|
const WINDOW_FIELD_MAP: Record<string, string> = {
|
||||||
|
"5Hour": QWEN_TOKEN_PLAN_WINDOW_5H,
|
||||||
|
"1Week": QWEN_TOKEN_PLAN_WINDOW_WEEKLY,
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface QwenTokenPlanQuota extends QuotaInfo {
|
||||||
|
windows: Record<string, { percentUsed: number; resetAt: string | null }>;
|
||||||
|
/** Which console served the quota — drives the plan label shown in the dashboard. */
|
||||||
|
consoleSite: TokenPlanConsoleSite["consoleSite"];
|
||||||
|
/** Subscription tier (e.g. "pro") or null when the subscription call failed. */
|
||||||
|
specCode: string | null;
|
||||||
|
/** Credit limits of the active tier (from quota-config), when resolvable. */
|
||||||
|
tierLimits: { fiveHour: number | null; weekly: number | null };
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UsageCacheEntry {
|
||||||
|
quota: QwenTokenPlanQuota;
|
||||||
|
fetchedAt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TierCacheEntry {
|
||||||
|
specCode: string | null;
|
||||||
|
tierLimits: { fiveHour: number | null; weekly: number | null };
|
||||||
|
fetchedAt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const usageCache = new Map<string, UsageCacheEntry>();
|
||||||
|
const tierCache = new Map<string, TierCacheEntry>();
|
||||||
|
const secTokenCache = new Map<string, { token: string; fetchedAt: number }>();
|
||||||
|
|
||||||
|
const _cacheCleanup = setInterval(() => {
|
||||||
|
const now = Date.now();
|
||||||
|
for (const [key, entry] of usageCache) {
|
||||||
|
if (now - entry.fetchedAt > USAGE_CACHE_TTL_MS * 5) usageCache.delete(key);
|
||||||
|
}
|
||||||
|
for (const [key, entry] of tierCache) {
|
||||||
|
if (now - entry.fetchedAt > TIER_CACHE_TTL_MS * 2) tierCache.delete(key);
|
||||||
|
}
|
||||||
|
for (const [key, entry] of secTokenCache) {
|
||||||
|
if (now - entry.fetchedAt > TIER_CACHE_TTL_MS * 2) secTokenCache.delete(key);
|
||||||
|
}
|
||||||
|
}, 5 * 60_000);
|
||||||
|
|
||||||
|
if (typeof _cacheCleanup === "object" && "unref" in _cacheCleanup) {
|
||||||
|
(_cacheCleanup as { unref?: () => void }).unref?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function toRecord(value: unknown): Record<string, unknown> {
|
||||||
|
return value && typeof value === "object" && !Array.isArray(value)
|
||||||
|
? (value as Record<string, unknown>)
|
||||||
|
: {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function toNumberOrNull(value: unknown): number | null {
|
||||||
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
||||||
|
if (typeof value === "string") {
|
||||||
|
const parsed = parseFloat(value);
|
||||||
|
if (Number.isFinite(parsed)) return parsed;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toTrimmedString(value: unknown): string {
|
||||||
|
return typeof value === "string" ? value.trim() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCookie(providerSpecificData: Record<string, unknown> | undefined): string {
|
||||||
|
for (const key of ["qwenCloudCookie", "alibabaConsoleCookie", "cookie"]) {
|
||||||
|
const value = toTrimmedString(providerSpecificData?.[key]);
|
||||||
|
if (value) return value;
|
||||||
|
}
|
||||||
|
return process.env.QWEN_CLOUD_COOKIE?.trim() || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getConfiguredSecToken(providerSpecificData: Record<string, unknown> | undefined): string {
|
||||||
|
for (const key of ["qwenCloudSecToken", "alibabaConsoleSecToken"]) {
|
||||||
|
const value = toTrimmedString(providerSpecificData?.[key]);
|
||||||
|
if (value) return value;
|
||||||
|
}
|
||||||
|
return process.env.QWEN_CLOUD_SEC_TOKEN?.trim() || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGatewayHost(site: TokenPlanConsoleSite): string {
|
||||||
|
const configured = process.env.QWEN_TOKEN_PLAN_HOST?.trim();
|
||||||
|
if (!configured) return site.gatewayHost;
|
||||||
|
return /^https?:\/\//i.test(configured) ? configured : `https://${configured}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDashboardUrl(site: TokenPlanConsoleSite): string {
|
||||||
|
return process.env.QWEN_TOKEN_PLAN_DASHBOARD_URL?.trim() || site.dashboardUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Extract the console `SEC_TOKEN: "…"` embedded in the logged-in dashboard HTML. */
|
||||||
|
export function extractQwenSecToken(html: string): string | null {
|
||||||
|
const match = /SEC_?TOKEN["']?\s*[:=]\s*["']([^"']+)["']/i.exec(html);
|
||||||
|
return match ? match[1] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resolveSecToken(
|
||||||
|
connectionId: string,
|
||||||
|
cookie: string,
|
||||||
|
site: TokenPlanConsoleSite
|
||||||
|
): Promise<string> {
|
||||||
|
const cached = secTokenCache.get(connectionId);
|
||||||
|
if (cached && Date.now() - cached.fetchedAt < TIER_CACHE_TTL_MS) {
|
||||||
|
return cached.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(getDashboardUrl(site), {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
Cookie: cookie,
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36",
|
||||||
|
Accept: "text/html",
|
||||||
|
},
|
||||||
|
redirect: "follow",
|
||||||
|
signal: AbortSignal.timeout(8_000),
|
||||||
|
});
|
||||||
|
const html = await response.text();
|
||||||
|
const token = extractQwenSecToken(html);
|
||||||
|
if (token) {
|
||||||
|
secTokenCache.set(connectionId, { token, fetchedAt: Date.now() });
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// best-effort — some accounts work without sec_token
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Gateway transport ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
async function callGateway(
|
||||||
|
endpoint: string,
|
||||||
|
cookie: string,
|
||||||
|
secToken: string,
|
||||||
|
site: TokenPlanConsoleSite
|
||||||
|
): Promise<unknown | null> {
|
||||||
|
const api = `${TOKEN_PLAN_API_PREFIX}${endpoint}`;
|
||||||
|
const url = `${getGatewayHost(site)}/data/api.json?product=${GATEWAY_PRODUCT}&action=${GATEWAY_ACTION}&api=${encodeURIComponent(api)}`;
|
||||||
|
|
||||||
|
const params = JSON.stringify({
|
||||||
|
Api: api,
|
||||||
|
V: "1.0",
|
||||||
|
Data: {
|
||||||
|
commodityCode: COMMODITY_CODE,
|
||||||
|
cornerstoneParam: {
|
||||||
|
console: "ONE_CONSOLE",
|
||||||
|
consoleSite: site.consoleSite,
|
||||||
|
domain: site.domain,
|
||||||
|
productCode: "p_efm",
|
||||||
|
protocol: "V2",
|
||||||
|
xsp_lang: "en-US",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const body = new URLSearchParams({
|
||||||
|
product: GATEWAY_PRODUCT,
|
||||||
|
action: GATEWAY_ACTION,
|
||||||
|
sec_token: secToken,
|
||||||
|
region: GATEWAY_REGION,
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
// #6911: space concurrent upstream quota fetches (mirrors bailianQuotaFetcher.ts).
|
||||||
|
await throttleQuotaFetch();
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Cookie: cookie,
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
Accept: "application/json",
|
||||||
|
Origin: site.origin,
|
||||||
|
Referer: `${site.origin}/`,
|
||||||
|
},
|
||||||
|
body: body.toString(),
|
||||||
|
signal: AbortSignal.timeout(8_000),
|
||||||
|
});
|
||||||
|
|
||||||
|
const raw = await response.json();
|
||||||
|
return parseGatewayEnvelope(raw);
|
||||||
|
} catch {
|
||||||
|
// Network error, timeout, non-JSON (login redirect page) — fail open
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unwrap {code:"200", data:{DataV2:{data:{code:"SUCCESS", data:<payload>}}}} → payload. */
|
||||||
|
function parseGatewayEnvelope(raw: unknown): unknown | null {
|
||||||
|
const obj = toRecord(raw);
|
||||||
|
if (obj["code"] !== "200" && obj["code"] !== 200) return null;
|
||||||
|
const inner = toRecord(toRecord(toRecord(obj["data"])["DataV2"])["data"]);
|
||||||
|
if (inner["code"] !== "SUCCESS" || inner["success"] !== true) return null;
|
||||||
|
return inner["data"] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Parsers ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function parseUsageWindows(
|
||||||
|
payload: unknown
|
||||||
|
): Record<string, { percentUsed: number; resetAt: string | null }> {
|
||||||
|
const obj = toRecord(payload);
|
||||||
|
const windows: Record<string, { percentUsed: number; resetAt: string | null }> = {};
|
||||||
|
|
||||||
|
for (const [fieldPrefix, windowKey] of Object.entries(WINDOW_FIELD_MAP)) {
|
||||||
|
const percent = toNumberOrNull(obj[`per${fieldPrefix}Percentage`]);
|
||||||
|
if (percent === null) continue; // window omitted (e.g. 5-hour "Temporarily Removed")
|
||||||
|
const resetMs = toNumberOrNull(obj[`per${fieldPrefix}ResetTime`]);
|
||||||
|
windows[windowKey] = {
|
||||||
|
percentUsed: percent,
|
||||||
|
resetAt: resetMs && resetMs > 0 ? new Date(resetMs).toISOString() : null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return windows;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resolveTierInfo(
|
||||||
|
connectionId: string,
|
||||||
|
cookie: string,
|
||||||
|
secToken: string,
|
||||||
|
site: TokenPlanConsoleSite
|
||||||
|
): Promise<TierCacheEntry> {
|
||||||
|
const cached = tierCache.get(connectionId);
|
||||||
|
if (cached && Date.now() - cached.fetchedAt < TIER_CACHE_TTL_MS) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [quotaConfig, subscription] = await Promise.all([
|
||||||
|
callGateway("quota-config", cookie, secToken, site),
|
||||||
|
callGateway("subscription", cookie, secToken, site),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const specCode = toTrimmedString(toRecord(subscription)["specCode"]) || null;
|
||||||
|
const tierRecord = specCode ? toRecord(toRecord(quotaConfig)[specCode]) : {};
|
||||||
|
const entry: TierCacheEntry = {
|
||||||
|
specCode,
|
||||||
|
tierLimits: {
|
||||||
|
fiveHour: toNumberOrNull(tierRecord["five_hour"]),
|
||||||
|
weekly: toNumberOrNull(tierRecord["weekly"]),
|
||||||
|
},
|
||||||
|
fetchedAt: Date.now(),
|
||||||
|
};
|
||||||
|
|
||||||
|
tierCache.set(connectionId, entry);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Core fetcher ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the personal Token Plan quota for a qwen-cloud-token-plan connection.
|
||||||
|
* Returns percentUsed = max across the windows present in the usage response,
|
||||||
|
* or null when no cookie is configured / the console session expired.
|
||||||
|
*/
|
||||||
|
export async function fetchQwenTokenPlanQuota(
|
||||||
|
connectionId: string,
|
||||||
|
connection?: Record<string, unknown>
|
||||||
|
): Promise<QuotaInfo | null> {
|
||||||
|
const cached = usageCache.get(connectionId);
|
||||||
|
if (cached && Date.now() - cached.fetchedAt < USAGE_CACHE_TTL_MS) {
|
||||||
|
return cached.quota;
|
||||||
|
}
|
||||||
|
|
||||||
|
const providerSpecificData =
|
||||||
|
connection?.providerSpecificData &&
|
||||||
|
typeof connection.providerSpecificData === "object" &&
|
||||||
|
!Array.isArray(connection.providerSpecificData)
|
||||||
|
? (connection.providerSpecificData as Record<string, unknown>)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const cookie = getCookie(providerSpecificData);
|
||||||
|
if (!cookie) return null;
|
||||||
|
|
||||||
|
const site = resolveConsoleSite(
|
||||||
|
cookie,
|
||||||
|
typeof connection?.provider === "string" ? connection.provider : undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
const secToken =
|
||||||
|
getConfiguredSecToken(providerSpecificData) ||
|
||||||
|
(await resolveSecToken(connectionId, cookie, site));
|
||||||
|
|
||||||
|
const usagePayload = await callGateway("usage", cookie, secToken, site);
|
||||||
|
if (usagePayload === null) return null;
|
||||||
|
|
||||||
|
const windows = parseUsageWindows(usagePayload);
|
||||||
|
const windowEntries = Object.values(windows);
|
||||||
|
if (windowEntries.length === 0) return null;
|
||||||
|
|
||||||
|
const worst = windowEntries.reduce((max, w) => (w.percentUsed > max.percentUsed ? w : max));
|
||||||
|
|
||||||
|
const tier = await resolveTierInfo(connectionId, cookie, secToken, site);
|
||||||
|
const total = tier.tierLimits.weekly ?? 100;
|
||||||
|
|
||||||
|
const quota: QwenTokenPlanQuota = {
|
||||||
|
used: Math.round(worst.percentUsed * total),
|
||||||
|
total,
|
||||||
|
percentUsed: worst.percentUsed,
|
||||||
|
resetAt: worst.resetAt,
|
||||||
|
windows,
|
||||||
|
consoleSite: site.consoleSite,
|
||||||
|
specCode: tier.specCode,
|
||||||
|
tierLimits: tier.tierLimits,
|
||||||
|
limitReached: worst.percentUsed >= 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
usageCache.set(connectionId, { quota, fetchedAt: Date.now() });
|
||||||
|
return quota;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Invalidation ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
export function invalidateQwenTokenPlanQuotaCache(connectionId: string): void {
|
||||||
|
usageCache.delete(connectionId);
|
||||||
|
tierCache.delete(connectionId);
|
||||||
|
secTokenCache.delete(connectionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Registration ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the Qwen Token Plan quota fetcher with the preflight and monitor systems.
|
||||||
|
* Call once at server startup (src/sse/handlers/chat.ts), BEFORE registerGenericQuotaFetchers().
|
||||||
|
*/
|
||||||
|
export function registerQwenTokenPlanQuotaFetcher(): void {
|
||||||
|
registerQuotaFetcher("qwen-cloud-token-plan", fetchQwenTokenPlanQuota);
|
||||||
|
registerMonitorFetcher("qwen-cloud-token-plan", fetchQwenTokenPlanQuota);
|
||||||
|
registerQuotaWindows("qwen-cloud-token-plan", [
|
||||||
|
QWEN_TOKEN_PLAN_WINDOW_5H,
|
||||||
|
QWEN_TOKEN_PLAN_WINDOW_WEEKLY,
|
||||||
|
]);
|
||||||
|
}
|
||||||
@@ -69,6 +69,7 @@ import { getXaiOauthUsage } from "./usage/xaiOauth.ts";
|
|||||||
import { getGrokCliUsage } from "./usage/grokCli.ts";
|
import { getGrokCliUsage } from "./usage/grokCli.ts";
|
||||||
import { getFirecrawlUsage } from "./usage/firecrawl.ts";
|
import { getFirecrawlUsage } from "./usage/firecrawl.ts";
|
||||||
import { getCommandCodeUsage } from "./usage/command-code.ts";
|
import { getCommandCodeUsage } from "./usage/command-code.ts";
|
||||||
|
import { getQwenTokenPlanUsage } from "./usage/qwen-token-plan.ts";
|
||||||
import { getConolUsage } from "./conolUsage.ts";
|
import { getConolUsage } from "./conolUsage.ts";
|
||||||
|
|
||||||
type JsonRecord = Record<string, unknown>;
|
type JsonRecord = Record<string, unknown>;
|
||||||
@@ -111,6 +112,7 @@ export const USAGE_FETCHER_PROVIDERS = [
|
|||||||
"minimax-cn",
|
"minimax-cn",
|
||||||
"crof",
|
"crof",
|
||||||
"bailian-coding-plan",
|
"bailian-coding-plan",
|
||||||
|
"qwen-cloud-token-plan",
|
||||||
"nanogpt",
|
"nanogpt",
|
||||||
"deepseek",
|
"deepseek",
|
||||||
"opencode",
|
"opencode",
|
||||||
@@ -202,6 +204,8 @@ export async function getUsageForProvider(
|
|||||||
return await getCrofUsage(apiKey || "");
|
return await getCrofUsage(apiKey || "");
|
||||||
case "bailian-coding-plan":
|
case "bailian-coding-plan":
|
||||||
return await getBailianCodingPlanUsage(id || "", apiKey || "", providerSpecificData);
|
return await getBailianCodingPlanUsage(id || "", apiKey || "", providerSpecificData);
|
||||||
|
case "qwen-cloud-token-plan":
|
||||||
|
return await getQwenTokenPlanUsage(id || "", apiKey || "", providerSpecificData);
|
||||||
case "nanogpt":
|
case "nanogpt":
|
||||||
return await getNanoGptUsage(apiKey || "");
|
return await getNanoGptUsage(apiKey || "");
|
||||||
case "deepseek":
|
case "deepseek":
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { fetchBailianQuota, type BailianTripleWindowQuota } from "../bailianQuotaFetcher.ts";
|
import { fetchBailianQuota, type BailianTripleWindowQuota } from "../bailianQuotaFetcher.ts";
|
||||||
|
import { getQwenTokenPlanUsage } from "./qwen-token-plan.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bailian (Alibaba Token Plan) Usage
|
* Bailian (Alibaba Token Plan) Usage
|
||||||
@@ -21,11 +22,25 @@ export async function getBailianCodingPlanUsage(
|
|||||||
providerSpecificData?: Record<string, unknown>
|
providerSpecificData?: Record<string, unknown>
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
// The catalog entry is "Alibaba Token Plan" and now points at the Token Plan
|
||||||
|
// endpoint, so prefer the Token Plan quota (console cookie) when one is
|
||||||
|
// configured. The Coding Plan path below stays as the fallback for accounts
|
||||||
|
// that really do hold a Coding Plan key (#9603).
|
||||||
|
const tokenPlanUsage = await getQwenTokenPlanUsage(
|
||||||
|
connectionId,
|
||||||
|
apiKey,
|
||||||
|
providerSpecificData,
|
||||||
|
"bailian-coding-plan"
|
||||||
|
);
|
||||||
|
if ("quotas" in tokenPlanUsage) return tokenPlanUsage;
|
||||||
|
|
||||||
const connection = { apiKey, providerSpecificData };
|
const connection = { apiKey, providerSpecificData };
|
||||||
const quota = await fetchBailianQuota(connectionId, connection);
|
const quota = await fetchBailianQuota(connectionId, connection);
|
||||||
|
|
||||||
if (!quota) {
|
if (!quota) {
|
||||||
return { message: "Alibaba Token Plan connected. Unable to fetch quota." };
|
// Neither surface answered — surface the Token Plan guidance, which tells the
|
||||||
|
// operator how to supply the cookie the console gateway requires.
|
||||||
|
return tokenPlanUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bailianQuota = quota as BailianTripleWindowQuota;
|
const bailianQuota = quota as BailianTripleWindowQuota;
|
||||||
|
|||||||
96
open-sse/services/usage/qwen-token-plan.ts
Normal file
96
open-sse/services/usage/qwen-token-plan.ts
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* usage/qwen-token-plan.ts — Qwen Cloud / Alibaba Model Studio personal Token Plan
|
||||||
|
* usage leaf (issue #9603).
|
||||||
|
*
|
||||||
|
* Delegates to qwenTokenPlanQuotaFetcher (cookie-authenticated console gateway) and
|
||||||
|
* shapes the 5-hour / weekly sliding windows into the standard usage response. The
|
||||||
|
* inference API key cannot read this quota — the connection needs a console session
|
||||||
|
* cookie in providerSpecificData (qwenCloudCookie / alibabaConsoleCookie / cookie)
|
||||||
|
* or the QWEN_CLOUD_COOKIE env var.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
fetchQwenTokenPlanQuota,
|
||||||
|
QWEN_TOKEN_PLAN_WINDOW_5H,
|
||||||
|
QWEN_TOKEN_PLAN_WINDOW_WEEKLY,
|
||||||
|
type QwenTokenPlanQuota,
|
||||||
|
} from "../qwenTokenPlanQuotaFetcher.ts";
|
||||||
|
import type { UsageQuota } from "./quota.ts";
|
||||||
|
|
||||||
|
function windowToQuota(
|
||||||
|
window: { percentUsed: number; resetAt: string | null } | undefined,
|
||||||
|
totalCredits: number | null,
|
||||||
|
displayName: string
|
||||||
|
): UsageQuota | null {
|
||||||
|
if (!window) return null;
|
||||||
|
const total = totalCredits ?? 100;
|
||||||
|
const used = Math.round(window.percentUsed * total);
|
||||||
|
const remaining = Math.max(0, total - used);
|
||||||
|
return {
|
||||||
|
used,
|
||||||
|
total,
|
||||||
|
remaining,
|
||||||
|
remainingPercentage: Math.round((1 - window.percentUsed) * 1000) / 10,
|
||||||
|
resetAt: window.resetAt,
|
||||||
|
unlimited: false,
|
||||||
|
displayName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Qwen Cloud personal Token Plan usage (5-hour + weekly sliding windows).
|
||||||
|
*/
|
||||||
|
export async function getQwenTokenPlanUsage(
|
||||||
|
connectionId: string,
|
||||||
|
apiKey: string,
|
||||||
|
providerSpecificData?: Record<string, unknown>,
|
||||||
|
provider = "qwen-cloud-token-plan"
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const quota = await fetchQwenTokenPlanQuota(connectionId, {
|
||||||
|
apiKey,
|
||||||
|
providerSpecificData,
|
||||||
|
provider,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!quota) {
|
||||||
|
return {
|
||||||
|
message:
|
||||||
|
"Qwen Token Plan connected. Quota needs a console session cookie — the inference " +
|
||||||
|
"API key cannot read it. Get it at home.qwencloud.com › Billing › Subscription " +
|
||||||
|
"(logged in): F12 › Network, reload, filter by api.json, click a request to " +
|
||||||
|
"cs-data.qwencloud.com and copy the whole Cookie value from Request Headers " +
|
||||||
|
"(it contains login_qwencloud_ticket). Paste it into the connection's " +
|
||||||
|
"'Qwen / Model Studio console cookie' field, or set QWEN_CLOUD_COOKIE. " +
|
||||||
|
"The cookie expires with the browser session — re-paste it when this message returns.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const tokenPlanQuota = quota as QwenTokenPlanQuota;
|
||||||
|
const quotas: Record<string, UsageQuota> = {};
|
||||||
|
|
||||||
|
const fiveHour = windowToQuota(
|
||||||
|
tokenPlanQuota.windows[QWEN_TOKEN_PLAN_WINDOW_5H],
|
||||||
|
tokenPlanQuota.tierLimits.fiveHour,
|
||||||
|
"5-hour window"
|
||||||
|
);
|
||||||
|
if (fiveHour) quotas.five_hour = fiveHour;
|
||||||
|
|
||||||
|
const weekly = windowToQuota(
|
||||||
|
tokenPlanQuota.windows[QWEN_TOKEN_PLAN_WINDOW_WEEKLY],
|
||||||
|
tokenPlanQuota.tierLimits.weekly,
|
||||||
|
"Weekly window"
|
||||||
|
);
|
||||||
|
if (weekly) quotas.weekly = weekly;
|
||||||
|
|
||||||
|
const specCode = tokenPlanQuota.specCode;
|
||||||
|
const brand = tokenPlanQuota.consoleSite === "ALIYUN" ? "Alibaba" : "Qwen";
|
||||||
|
const plan = specCode
|
||||||
|
? `${brand} Token Plan (${specCode.charAt(0).toUpperCase()}${specCode.slice(1)})`
|
||||||
|
: `${brand} Token Plan`;
|
||||||
|
|
||||||
|
return { plan, quotas };
|
||||||
|
} catch (error) {
|
||||||
|
return { message: `Qwen Token Plan error: ${(error as Error).message}` };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -158,6 +158,7 @@ function readCodeFacts() {
|
|||||||
'import {pluginTools} from "./open-sse/mcp-server/tools/pluginTools.ts";',
|
'import {pluginTools} from "./open-sse/mcp-server/tools/pluginTools.ts";',
|
||||||
'import {notionTools} from "./open-sse/mcp-server/tools/notionTools.ts";',
|
'import {notionTools} from "./open-sse/mcp-server/tools/notionTools.ts";',
|
||||||
'import {obsidianTools} from "./open-sse/mcp-server/tools/obsidianTools.ts";',
|
'import {obsidianTools} from "./open-sse/mcp-server/tools/obsidianTools.ts";',
|
||||||
|
'import {localCorpusTools} from "./open-sse/mcp-server/tools/localCorpusTools.ts";',
|
||||||
'import {compressionTools} from "./open-sse/mcp-server/tools/compressionTools.ts";',
|
'import {compressionTools} from "./open-sse/mcp-server/tools/compressionTools.ts";',
|
||||||
// Live provider total — the SAME collections gen-provider-reference.ts unions, so the
|
// Live provider total — the SAME collections gen-provider-reference.ts unions, so the
|
||||||
// doc-vs-live check below cannot drift from the generator's definition of "provider".
|
// doc-vs-live check below cannot drift from the generator's definition of "provider".
|
||||||
@@ -169,7 +170,7 @@ function readCodeFacts() {
|
|||||||
"const pids=new Set();",
|
"const pids=new Set();",
|
||||||
"for(const c of provCols)for(const p of Object.values(c||{}))if(p&&p.id)pids.add(p.id);",
|
"for(const c of provCols)for(const p of Object.values(c||{}))if(p&&p.id)pids.add(p.id);",
|
||||||
"const cols={MCP_TOOLS,memoryTools,skillTools,agentSkillTools,githubSkillTools,poolTools,",
|
"const cols={MCP_TOOLS,memoryTools,skillTools,agentSkillTools,githubSkillTools,poolTools,",
|
||||||
"gamificationTools,pluginTools,notionTools,obsidianTools,compressionTools};",
|
"gamificationTools,pluginTools,notionTools,obsidianTools,localCorpusTools,compressionTools};",
|
||||||
"const sc=new Set();",
|
"const sc=new Set();",
|
||||||
"for(const col of Object.values(cols))for(const t of Object.values(col))",
|
"for(const col of Object.values(cols))for(const t of Object.values(col))",
|
||||||
"for(const x of (t?.scopes||[]))sc.add(x);",
|
"for(const x of (t?.scopes||[]))sc.add(x);",
|
||||||
@@ -452,7 +453,7 @@ export function buildChecks() {
|
|||||||
// total ("33 tools (25 CLI Code's …)") are not the MCP aggregate
|
// total ("33 tools (25 CLI Code's …)") are not the MCP aggregate
|
||||||
// per-module rows read "… tool definitions (N tools" / "… management tools
|
// per-module rows read "… tool definitions (N tools" / "… management tools
|
||||||
// (N tools" — the word tool(s)/definitions sits right before the paren. The
|
// (N tools" — the word tool(s)/definitions sits right before the paren. The
|
||||||
// aggregate ("MCP Server (104 tools", "all 104 tools") never does.
|
// aggregate ("MCP Server (109 tools", "all 109 tools") never does.
|
||||||
skipBefore: /(tools?|definitions?)\s*\(\s*$/i,
|
skipBefore: /(tools?|definitions?)\s*\(\s*$/i,
|
||||||
skipAfter: /^\s*\(\d+ CLI/,
|
skipAfter: /^\s*\(\d+ CLI/,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -43,15 +43,14 @@ export const KNOWN_DUPLICATE_VERSIONS = new Set([
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// ALLOWLIST 2 — gaps de sequência CONHECIDOS.
|
// ALLOWLIST 2 — gaps de sequência CONHECIDOS.
|
||||||
// Fonte: auditoria do disco (src/lib/db/migrations/). Além dos slots legados,
|
// Fonte: auditoria do disco (src/lib/db/migrations/). Além dos slots legados,
|
||||||
// 144–145 seguem reservados pelas migrations Radar que já existem na série
|
// As migrations Radar 144–145 e a migration 143 já aterrissaram. O job registry
|
||||||
// empilhada; a migration 143 já aterrissou. O job registry foi promovido de 139
|
// foi promovido de 139 para 146 pela tabela RENAMED_MIGRATION_COMPATIBILITY. A
|
||||||
// para 146 pela tabela RENAMED_MIGRATION_COMPATIBILITY. A
|
|
||||||
// 147–149 estão reservadas por migrations atualmente em trânsito nos PRs #8228,
|
// 147–149 estão reservadas por migrations atualmente em trânsito nos PRs #8228,
|
||||||
// #9313, #10047 e #10066; esta branch usa 150 para evitar essas colisões conhecidas.
|
// #9313, #10047 e #10066; esta branch usa 150 para evitar essas colisões conhecidas.
|
||||||
// O stale-enforcement exige que cada reserva seja removida quando os arquivos
|
// O stale-enforcement exige que cada reserva seja removida quando os arquivos
|
||||||
// correspondentes aterrissarem na release.
|
// correspondentes aterrissarem na release.
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
export const KNOWN_GAPS = new Set(["026", "055", "121", "144", "145", "148", "149"]); // 121: número queimado no ciclo v3.8.47 — 122 (#6909) mergeou antes e 121 nunca aterrissou (validação e2e 2026-07-12)
|
export const KNOWN_GAPS = new Set(["026", "055", "121", "148", "149"]); // 121: número queimado no ciclo v3.8.47 — 122 (#6909) mergeou antes e 121 nunca aterrissou (validação e2e 2026-07-12)
|
||||||
|
|
||||||
function pad3(n) {
|
function pad3(n) {
|
||||||
return String(n).padStart(3, "0");
|
return String(n).padStart(3, "0");
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import { HomeProviderTopologySection } from "./HomeProviderTopologySection";
|
|||||||
import { shouldShowProviderTopologyOnHome } from "./homeAppearance";
|
import { shouldShowProviderTopologyOnHome } from "./homeAppearance";
|
||||||
|
|
||||||
const ProviderQuotaWidget = dynamic(() => import("../home/ProviderQuotaWidget"), { ssr: false });
|
const ProviderQuotaWidget = dynamic(() => import("../home/ProviderQuotaWidget"), { ssr: false });
|
||||||
import type { NewsAnnouncement } from "@/shared/utils/releaseNotes";
|
|
||||||
|
|
||||||
type UpdateStep = {
|
type UpdateStep = {
|
||||||
step: string;
|
step: string;
|
||||||
@@ -37,7 +36,6 @@ type VersionInfo = {
|
|||||||
channel: string;
|
channel: string;
|
||||||
autoUpdateSupported: boolean;
|
autoUpdateSupported: boolean;
|
||||||
autoUpdateError?: string | null;
|
autoUpdateError?: string | null;
|
||||||
news?: NewsAnnouncement | null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type HomePageClientProps = {
|
type HomePageClientProps = {
|
||||||
@@ -1047,37 +1045,6 @@ export default function HomePageClient({ machineId }: HomePageClientProps) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* News Notification Banner */}
|
|
||||||
{versionInfo?.news && (
|
|
||||||
<div className="flex min-h-[64px] items-center justify-between rounded-lg border border-border bg-surface px-5 py-4">
|
|
||||||
<div className="flex min-w-0 items-center gap-4">
|
|
||||||
<div className="flex size-10 shrink-0 items-center justify-center rounded-lg bg-bg text-text-muted">
|
|
||||||
<span className="material-symbols-outlined text-[22px] text-primary">
|
|
||||||
{versionInfo.news.icon || "campaign"}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="min-w-0">
|
|
||||||
<p className="text-sm font-semibold text-text-main">{versionInfo.news.title}</p>
|
|
||||||
<p className="mt-0.5 max-w-[560px] text-xs leading-relaxed text-text-muted">
|
|
||||||
{versionInfo.news.message}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{versionInfo.news.link && (
|
|
||||||
<a
|
|
||||||
href={versionInfo.news.link}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="ml-4 inline-flex shrink-0 items-center gap-1.5 rounded-lg border border-border bg-bg px-4 py-2 text-xs font-semibold text-text-main transition-colors hover:border-primary/30 hover:text-primary"
|
|
||||||
>
|
|
||||||
{versionInfo.news.linkLabel || t("readMore")}
|
|
||||||
<span className="material-symbols-outlined text-[14px]">arrow_forward</span>
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
119
src/app/(dashboard)/dashboard/NewsBanner.tsx
Normal file
119
src/app/(dashboard)/dashboard/NewsBanner.tsx
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState, useSyncExternalStore } from "react";
|
||||||
|
import { useLocale, useTranslations } from "next-intl";
|
||||||
|
|
||||||
|
import {
|
||||||
|
NEWS_DISMISS_EVENT,
|
||||||
|
NEWS_DISMISS_STORAGE_NAME,
|
||||||
|
fetchNewsPayload,
|
||||||
|
parseDismissedNewsIds,
|
||||||
|
selectActiveNews,
|
||||||
|
serializeDismissedNewsIds,
|
||||||
|
} from "@/shared/utils/releaseNotes";
|
||||||
|
|
||||||
|
function subscribeToDismissals(callback: () => void) {
|
||||||
|
window.addEventListener("storage", callback);
|
||||||
|
window.addEventListener(NEWS_DISMISS_EVENT, callback);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("storage", callback);
|
||||||
|
window.removeEventListener(NEWS_DISMISS_EVENT, callback);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function readDismissedIds(): string {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem(NEWS_DISMISS_STORAGE_NAME) ?? "";
|
||||||
|
} catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getServerDismissedIds(): string {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic, fail-silent reader for the public announcement feed. Fetching the
|
||||||
|
* static JSON is GET-only and does not send product state or telemetry.
|
||||||
|
*/
|
||||||
|
export default function NewsBanner() {
|
||||||
|
const locale = useLocale();
|
||||||
|
const t = useTranslations("common");
|
||||||
|
const [payload, setPayload] = useState<unknown>(null);
|
||||||
|
const dismissedSnapshot = useSyncExternalStore(
|
||||||
|
subscribeToDismissals,
|
||||||
|
readDismissedIds,
|
||||||
|
getServerDismissedIds
|
||||||
|
);
|
||||||
|
const dismissedIds = parseDismissedNewsIds(dismissedSnapshot);
|
||||||
|
const announcement = selectActiveNews(payload, locale, dismissedIds);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const controller = new AbortController();
|
||||||
|
|
||||||
|
void fetchNewsPayload(fetch, controller.signal).then((value) => {
|
||||||
|
if (value !== null) setPayload(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => controller.abort();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!announcement) return null;
|
||||||
|
|
||||||
|
const dismiss = () => {
|
||||||
|
dismissedIds.add(announcement.id);
|
||||||
|
try {
|
||||||
|
localStorage.setItem(NEWS_DISMISS_STORAGE_NAME, serializeDismissedNewsIds(dismissedIds));
|
||||||
|
} catch {
|
||||||
|
// Storage is optional; the next announcement fetch remains functional.
|
||||||
|
}
|
||||||
|
window.dispatchEvent(new Event(NEWS_DISMISS_EVENT));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
role="complementary"
|
||||||
|
aria-label={announcement.title}
|
||||||
|
className="mb-4 flex flex-col gap-3 rounded-lg border border-primary/30 bg-primary/5 px-4 py-3 sm:flex-row sm:items-center sm:justify-between"
|
||||||
|
>
|
||||||
|
<div className="flex min-w-0 items-start gap-3">
|
||||||
|
<div className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-primary/10">
|
||||||
|
<span className="material-symbols-outlined text-[22px] text-primary" aria-hidden="true">
|
||||||
|
{announcement.icon}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="min-w-0">
|
||||||
|
<p className="text-sm font-semibold text-text-main">{announcement.title}</p>
|
||||||
|
<p className="mt-0.5 text-xs leading-relaxed text-text-muted">{announcement.message}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex shrink-0 items-center gap-3 self-end sm:self-auto">
|
||||||
|
{announcement.link && (
|
||||||
|
<a
|
||||||
|
href={announcement.link}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-lg bg-primary px-3 py-1.5 text-xs font-semibold text-white transition-colors hover:brightness-110"
|
||||||
|
>
|
||||||
|
{announcement.linkLabel ?? announcement.title}
|
||||||
|
<span className="material-symbols-outlined text-[14px]" aria-hidden="true">
|
||||||
|
open_in_new
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={dismiss}
|
||||||
|
aria-label={t("dismissNotification")}
|
||||||
|
className="text-text-muted transition-colors hover:text-text-main"
|
||||||
|
>
|
||||||
|
<span className="material-symbols-outlined text-[18px]" aria-hidden="true">
|
||||||
|
close
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,39 +1,39 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useTranslations } from "next-intl";
|
import { useLocale, useTranslations } from "next-intl";
|
||||||
|
|
||||||
import { Button } from "@/shared/components";
|
import { Button } from "@/shared/components";
|
||||||
import {
|
import {
|
||||||
NEWS_JSON_URL,
|
fetchNewsPayload,
|
||||||
parseActiveNewsPayload,
|
listActiveNews,
|
||||||
type NewsAnnouncement,
|
type NewsAnnouncement,
|
||||||
} from "@/shared/utils/releaseNotes";
|
} from "@/shared/utils/releaseNotes";
|
||||||
|
|
||||||
export default function NewsViewer() {
|
export default function NewsViewer() {
|
||||||
|
const locale = useLocale();
|
||||||
const t = useTranslations("changelogPage");
|
const t = useTranslations("changelogPage");
|
||||||
const [news, setNews] = useState<NewsAnnouncement | null>(null);
|
const [news, setNews] = useState<NewsAnnouncement[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchNews() {
|
const controller = new AbortController();
|
||||||
try {
|
|
||||||
const res = await fetch(NEWS_JSON_URL, { cache: "no-store" });
|
void fetchNewsPayload(fetch, controller.signal)
|
||||||
if (res.ok) {
|
.then((payload) => {
|
||||||
const data = await res.json();
|
if (payload === null) {
|
||||||
setNews(parseActiveNewsPayload(data));
|
if (!controller.signal.aborted) setError(true);
|
||||||
} else {
|
return;
|
||||||
setError(true);
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
setNews(listActiveNews(payload, locale));
|
||||||
console.error("Failed to fetch news:", err);
|
})
|
||||||
setError(true);
|
.finally(() => {
|
||||||
} finally {
|
if (!controller.signal.aborted) setLoading(false);
|
||||||
setLoading(false);
|
});
|
||||||
}
|
|
||||||
}
|
return () => controller.abort();
|
||||||
fetchNews();
|
}, [locale]);
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
@@ -48,7 +48,7 @@ export default function NewsViewer() {
|
|||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center justify-center py-20 text-text-muted">
|
<div className="flex flex-col items-center justify-center py-20 text-text-muted">
|
||||||
<span className="material-symbols-outlined text-[48px] text-red-500/50 mb-4">
|
<span className="material-symbols-outlined mb-4 text-[48px] text-red-500/50">
|
||||||
error_outline
|
error_outline
|
||||||
</span>
|
</span>
|
||||||
<p>{t("announcementsLoadFailed")}</p>
|
<p>{t("announcementsLoadFailed")}</p>
|
||||||
@@ -56,10 +56,10 @@ export default function NewsViewer() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!news || !news.active) {
|
if (news.length === 0) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center justify-center py-20 text-text-muted">
|
<div className="flex flex-col items-center justify-center py-20 text-text-muted">
|
||||||
<span className="material-symbols-outlined text-[48px] opacity-50 mb-4">
|
<span className="material-symbols-outlined mb-4 text-[48px] opacity-50">
|
||||||
notifications_off
|
notifications_off
|
||||||
</span>
|
</span>
|
||||||
<p>{t("noAnnouncements")}</p>
|
<p>{t("noAnnouncements")}</p>
|
||||||
@@ -68,30 +68,37 @@ export default function NewsViewer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-8">
|
<div className="space-y-8 p-8">
|
||||||
<div className="flex flex-col gap-6 border-l-4 border-primary pl-5 md:flex-row md:items-center md:pl-6">
|
{news.map((announcement) => (
|
||||||
<div className="size-14 rounded-lg bg-primary/10 flex items-center justify-center shrink-0">
|
<article
|
||||||
<span className="material-symbols-outlined text-[30px] text-primary">
|
key={announcement.id}
|
||||||
{news.icon || "campaign"}
|
className="flex flex-col gap-6 border-l-4 border-primary pl-5 md:flex-row md:items-center md:pl-6"
|
||||||
</span>
|
>
|
||||||
</div>
|
<div className="flex size-14 shrink-0 items-center justify-center rounded-lg bg-primary/10">
|
||||||
|
<span className="material-symbols-outlined text-[30px] text-primary">
|
||||||
<div className="flex-1">
|
{announcement.icon}
|
||||||
<h2 className="text-xl font-bold text-text-main mb-2">{news.title}</h2>
|
</span>
|
||||||
<p className="text-sm text-text-muted leading-relaxed max-w-2xl">{news.message}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{news.link && (
|
|
||||||
<div className="shrink-0 md:ml-auto">
|
|
||||||
<a href={news.link} target="_blank" rel="noopener noreferrer">
|
|
||||||
<Button variant="primary" className="gap-2">
|
|
||||||
{news.linkLabel || t("learnMore")}
|
|
||||||
<span className="material-symbols-outlined text-[18px]">arrow_forward</span>
|
|
||||||
</Button>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</div>
|
<div className="flex-1">
|
||||||
|
<h2 className="mb-2 text-xl font-bold text-text-main">{announcement.title}</h2>
|
||||||
|
<p className="max-w-2xl text-sm leading-relaxed text-text-muted">
|
||||||
|
{announcement.message}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{announcement.link && (
|
||||||
|
<div className="shrink-0 md:ml-auto">
|
||||||
|
<a href={announcement.link} target="_blank" rel="noopener noreferrer">
|
||||||
|
<Button variant="primary" className="gap-2">
|
||||||
|
{announcement.linkLabel ?? t("learnMore")}
|
||||||
|
<span className="material-symbols-outlined text-[18px]">arrow_forward</span>
|
||||||
|
</Button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</article>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
// Issue #3501 strangler-fig decomposition — Phase 1t (final push)
|
// Issue #3501 strangler-fig decomposition — Phase 1t (final push)
|
||||||
import { useState, useEffect, useCallback, useMemo } from "react";
|
import { useState, useEffect, useCallback, useMemo } from "react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams, useSearchParams } from "next/navigation";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { Card, Button, CardSkeleton } from "@/shared/components";
|
import { Card, Button, CardSkeleton } from "@/shared/components";
|
||||||
@@ -68,6 +68,7 @@ import AnonymousFallbackToggle from "./components/AnonymousFallbackToggle";
|
|||||||
|
|
||||||
export default function ProviderDetailPageClient() {
|
export default function ProviderDetailPageClient() {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
const providerId = params.id as string;
|
const providerId = params.id as string;
|
||||||
|
|
||||||
// ── UI-only modal state (not owned by hooks) ─────────────────────────────
|
// ── UI-only modal state (not owned by hooks) ─────────────────────────────
|
||||||
@@ -357,6 +358,10 @@ export default function ProviderDetailPageClient() {
|
|||||||
setShowAddApiKeyModal(true);
|
setShowAddApiKeyModal(true);
|
||||||
}, [providerId]);
|
}, [providerId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (searchParams.get("action") === "add-api-key") gateConnectionFlow(openApiKeyAddFlow);
|
||||||
|
}, [searchParams, gateConnectionFlow, openApiKeyAddFlow]);
|
||||||
|
|
||||||
const openPrimaryAddFlow = useCallback(() => {
|
const openPrimaryAddFlow = useCallback(() => {
|
||||||
if (providerId === "kimi-coding") return setShowKimiAuthMethodModal(true);
|
if (providerId === "kimi-coding") return setShowKimiAuthMethodModal(true);
|
||||||
if (isOAuth) {
|
if (isOAuth) {
|
||||||
|
|||||||
@@ -340,6 +340,8 @@ export default function EditConnectionModal({
|
|||||||
opencodeGoAuthCookie: "",
|
opencodeGoAuthCookie: "",
|
||||||
ollamaCloudUsageCookie: "",
|
ollamaCloudUsageCookie: "",
|
||||||
alibabaConsoleCookie: stringField(connection.providerSpecificData?.alibabaConsoleCookie),
|
alibabaConsoleCookie: stringField(connection.providerSpecificData?.alibabaConsoleCookie),
|
||||||
|
qwenCloudCookie: stringField(connection.providerSpecificData?.qwenCloudCookie),
|
||||||
|
qwenCloudSecToken: stringField(connection.providerSpecificData?.qwenCloudSecToken),
|
||||||
alibabaConsoleSecToken: stringField(
|
alibabaConsoleSecToken: stringField(
|
||||||
connection.providerSpecificData?.alibabaConsoleSecToken
|
connection.providerSpecificData?.alibabaConsoleSecToken
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -3,44 +3,16 @@
|
|||||||
import { Input } from "@/shared/components";
|
import { Input } from "@/shared/components";
|
||||||
import { providerText, type ProviderMessageTranslator } from "../../providerPageHelpers";
|
import { providerText, type ProviderMessageTranslator } from "../../providerPageHelpers";
|
||||||
|
|
||||||
export type QuotaScrapingFieldValues = {
|
import {
|
||||||
opencodeGoWorkspaceId: string;
|
assignQuotaScrapingProviderData,
|
||||||
opencodeGoAuthCookie: string;
|
EMPTY_QUOTA_SCRAPING_FIELDS,
|
||||||
ollamaCloudUsageCookie: string;
|
QWEN_TOKEN_PLAN_PROVIDERS,
|
||||||
alibabaConsoleCookie: string;
|
type QuotaScrapingFieldValues,
|
||||||
alibabaConsoleSecToken: string;
|
} from "./quotaScrapingFieldValues";
|
||||||
};
|
|
||||||
|
|
||||||
export const EMPTY_QUOTA_SCRAPING_FIELDS: QuotaScrapingFieldValues = {
|
// Re-exported so existing importers (modals, tests) keep their current paths.
|
||||||
opencodeGoWorkspaceId: "",
|
export { assignQuotaScrapingProviderData, EMPTY_QUOTA_SCRAPING_FIELDS };
|
||||||
opencodeGoAuthCookie: "",
|
export type { QuotaScrapingFieldValues };
|
||||||
ollamaCloudUsageCookie: "",
|
|
||||||
alibabaConsoleCookie: "",
|
|
||||||
alibabaConsoleSecToken: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
export function assignQuotaScrapingProviderData(
|
|
||||||
provider: string | undefined,
|
|
||||||
values: QuotaScrapingFieldValues,
|
|
||||||
target: Record<string, unknown>
|
|
||||||
) {
|
|
||||||
if (provider === "opencode-go") {
|
|
||||||
target.opencodeGoWorkspaceId = values.opencodeGoWorkspaceId.trim() || undefined;
|
|
||||||
if (values.opencodeGoAuthCookie.trim()) {
|
|
||||||
target.opencodeGoAuthCookie = values.opencodeGoAuthCookie.trim();
|
|
||||||
}
|
|
||||||
} else if (provider === "ollama-cloud" && values.ollamaCloudUsageCookie.trim()) {
|
|
||||||
target.ollamaCloudUsageCookie = values.ollamaCloudUsageCookie.trim();
|
|
||||||
} else if (
|
|
||||||
(provider === "alibaba" || provider === "alibaba-cn") &&
|
|
||||||
values.alibabaConsoleCookie.trim()
|
|
||||||
) {
|
|
||||||
target.alibabaConsoleCookie = values.alibabaConsoleCookie.trim();
|
|
||||||
if (values.alibabaConsoleSecToken.trim()) {
|
|
||||||
target.alibabaConsoleSecToken = values.alibabaConsoleSecToken.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type QuotaScrapingFieldsProps = {
|
type QuotaScrapingFieldsProps = {
|
||||||
provider?: string;
|
provider?: string;
|
||||||
@@ -170,5 +142,50 @@ export default function QuotaScrapingFields({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (QWEN_TOKEN_PLAN_PROVIDERS.has(provider ?? "")) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-3 rounded-lg border border-border/50 bg-surface/20 p-4">
|
||||||
|
<Input
|
||||||
|
label={providerText(t, "qwenCloudCookieLabel", "Qwen / Model Studio console cookie")}
|
||||||
|
name="qwenCloudCookie"
|
||||||
|
type="password"
|
||||||
|
value={values.qwenCloudCookie}
|
||||||
|
onChange={(e) => onChange({ qwenCloudCookie: e.target.value })}
|
||||||
|
placeholder="cna=...; login_qwencloud_ticket=...; ..."
|
||||||
|
hint={providerText(
|
||||||
|
t,
|
||||||
|
"qwenCloudCookieHint",
|
||||||
|
(editMode ? "Leave blank to keep the stored cookie. " : "") +
|
||||||
|
"Required for Token Plan quota — the inference API key cannot read it. " +
|
||||||
|
"How to get it: open home.qwencloud.com › Billing › Subscription while logged in, " +
|
||||||
|
"press F12 › Network, reload the page, filter by api.json, click any request to " +
|
||||||
|
"cs-data.qwencloud.com, then under Request Headers copy the WHOLE Cookie value " +
|
||||||
|
"(it contains login_qwencloud_ticket). It expires with the browser session — " +
|
||||||
|
"re-paste it when the quota reports an expired session."
|
||||||
|
)}
|
||||||
|
autoComplete="off"
|
||||||
|
spellCheck={false}
|
||||||
|
autoCapitalize="off"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label={providerText(t, "qwenCloudSecTokenLabel", "Qwen console sec_token (optional)")}
|
||||||
|
name="qwenCloudSecToken"
|
||||||
|
type="password"
|
||||||
|
value={values.qwenCloudSecToken}
|
||||||
|
onChange={(e) => onChange({ qwenCloudSecToken: e.target.value })}
|
||||||
|
placeholder="GjRV..."
|
||||||
|
hint={providerText(
|
||||||
|
t,
|
||||||
|
"qwenCloudSecTokenHint",
|
||||||
|
"Optional — resolved automatically from the dashboard. Set it only if quota sync reports a permission error."
|
||||||
|
)}
|
||||||
|
autoComplete="off"
|
||||||
|
spellCheck={false}
|
||||||
|
autoCapitalize="off"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* quotaScrapingFieldValues.ts — form-state shape + persistence rules for the
|
||||||
|
* quota-scraping credential fields (cookies / workspace ids) rendered by
|
||||||
|
* QuotaScrapingFields.tsx.
|
||||||
|
*
|
||||||
|
* Kept in a UI-free module on purpose: importing the .tsx pulls in
|
||||||
|
* `@/shared/components`, whose barrel reaches untranspiled ESM deps
|
||||||
|
* (@lobehub/icons) that the node:test runner cannot parse. Unit tests import
|
||||||
|
* this file instead; the component re-exports it for existing callers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Providers whose quota lives behind the Qwen/Model Studio console gateway (#9603). */
|
||||||
|
export const QWEN_TOKEN_PLAN_PROVIDERS = new Set(["qwen-cloud-token-plan", "bailian-coding-plan"]);
|
||||||
|
|
||||||
|
export type QuotaScrapingFieldValues = {
|
||||||
|
opencodeGoWorkspaceId: string;
|
||||||
|
opencodeGoAuthCookie: string;
|
||||||
|
ollamaCloudUsageCookie: string;
|
||||||
|
alibabaConsoleCookie: string;
|
||||||
|
alibabaConsoleSecToken: string;
|
||||||
|
qwenCloudCookie: string;
|
||||||
|
qwenCloudSecToken: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EMPTY_QUOTA_SCRAPING_FIELDS: QuotaScrapingFieldValues = {
|
||||||
|
opencodeGoWorkspaceId: "",
|
||||||
|
opencodeGoAuthCookie: "",
|
||||||
|
ollamaCloudUsageCookie: "",
|
||||||
|
alibabaConsoleCookie: "",
|
||||||
|
alibabaConsoleSecToken: "",
|
||||||
|
qwenCloudCookie: "",
|
||||||
|
qwenCloudSecToken: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
export function assignQuotaScrapingProviderData(
|
||||||
|
provider: string | undefined,
|
||||||
|
values: QuotaScrapingFieldValues,
|
||||||
|
target: Record<string, unknown>
|
||||||
|
) {
|
||||||
|
if (provider === "opencode-go") {
|
||||||
|
target.opencodeGoWorkspaceId = values.opencodeGoWorkspaceId.trim() || undefined;
|
||||||
|
if (values.opencodeGoAuthCookie.trim()) {
|
||||||
|
target.opencodeGoAuthCookie = values.opencodeGoAuthCookie.trim();
|
||||||
|
}
|
||||||
|
} else if (provider === "ollama-cloud" && values.ollamaCloudUsageCookie.trim()) {
|
||||||
|
target.ollamaCloudUsageCookie = values.ollamaCloudUsageCookie.trim();
|
||||||
|
} else if (
|
||||||
|
(provider === "alibaba" || provider === "alibaba-cn") &&
|
||||||
|
values.alibabaConsoleCookie.trim()
|
||||||
|
) {
|
||||||
|
target.alibabaConsoleCookie = values.alibabaConsoleCookie.trim();
|
||||||
|
if (values.alibabaConsoleSecToken.trim()) {
|
||||||
|
target.alibabaConsoleSecToken = values.alibabaConsoleSecToken.trim();
|
||||||
|
}
|
||||||
|
} else if (QWEN_TOKEN_PLAN_PROVIDERS.has(provider ?? "") && values.qwenCloudCookie?.trim()) {
|
||||||
|
// Optional access: callers (AddApiKeyModal/EditConnectionModal form state, and
|
||||||
|
// existing tests) may pass a partial form object without the newer fields —
|
||||||
|
// bailian-coding-plan previously matched no branch here at all.
|
||||||
|
target.qwenCloudCookie = values.qwenCloudCookie.trim();
|
||||||
|
if (values.qwenCloudSecToken?.trim()) {
|
||||||
|
target.qwenCloudSecToken = values.qwenCloudSecToken.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
381
src/app/(dashboard)/dashboard/radar/RadarCatalogTable.tsx
Normal file
381
src/app/(dashboard)/dashboard/radar/RadarCatalogTable.tsx
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Card } from "@/shared/components";
|
||||||
|
|
||||||
|
export interface RadarMergedEntry {
|
||||||
|
provider: string;
|
||||||
|
modelId: string;
|
||||||
|
displayName: string;
|
||||||
|
monthlyTokens: number;
|
||||||
|
creditTokens: number;
|
||||||
|
freeType: string;
|
||||||
|
poolKey: string | null;
|
||||||
|
tos: string;
|
||||||
|
trainsOnPrompts?: boolean;
|
||||||
|
enabled?: boolean;
|
||||||
|
origin: "baseline" | "radar" | "local";
|
||||||
|
disabledBy?: "radar";
|
||||||
|
contextWindow?: number | null;
|
||||||
|
capabilities?: {
|
||||||
|
tools: boolean | null;
|
||||||
|
vision: boolean | null;
|
||||||
|
thinking: boolean | null;
|
||||||
|
};
|
||||||
|
metadataEvidenceUrls?: string[];
|
||||||
|
budget?: { kind: string; tokensPerMonth?: number; poolId?: string };
|
||||||
|
limits?: { rpm: number | null; rpd: number | null; tpm: number | null; tpd: number | null };
|
||||||
|
setup?: { keyUrl: string | null; steps: string[] } | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RadarLocalModelState {
|
||||||
|
provider: string;
|
||||||
|
modelId: string;
|
||||||
|
displayName: string | null;
|
||||||
|
enabled: boolean | null;
|
||||||
|
tombstoned: boolean;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RadarCatalogTableProps {
|
||||||
|
entries: RadarMergedEntry[];
|
||||||
|
refreshCatalog: () => Promise<void>;
|
||||||
|
onError: (message: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatTokens(value: number): string {
|
||||||
|
if (value === 0) return "rate-only";
|
||||||
|
if (value >= 1_000_000) return `${(value / 1_000_000).toFixed(1)}M`;
|
||||||
|
if (value >= 1_000) return `${(value / 1_000).toFixed(0)}K`;
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function budgetLabel(entry: RadarMergedEntry): string {
|
||||||
|
if (entry.budget?.kind === "shared_pool") {
|
||||||
|
return `shared (${formatTokens(entry.budget.tokensPerMonth ?? entry.monthlyTokens)}/mo)`;
|
||||||
|
}
|
||||||
|
if (entry.budget?.kind === "rate_only" || entry.monthlyTokens === 0) return "rate-only";
|
||||||
|
return `${formatTokens(entry.monthlyTokens)}/mo`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function capabilityBadge(label: string, value: boolean | null | undefined, trueClass: string) {
|
||||||
|
const state = value === true ? "✓" : value === false ? "✕" : "?";
|
||||||
|
const stateClass =
|
||||||
|
value === true
|
||||||
|
? trueClass
|
||||||
|
: value === false
|
||||||
|
? "bg-red-500/10 text-red-400"
|
||||||
|
: "bg-gray-500/10 text-gray-400";
|
||||||
|
return (
|
||||||
|
<span className={`text-[10px] px-1.5 py-0.5 rounded ${stateClass}`}>
|
||||||
|
{label} {state}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RadarCatalogTable({ entries, refreshCatalog, onError }: RadarCatalogTableProps) {
|
||||||
|
const t = useTranslations("radarPage");
|
||||||
|
const [states, setStates] = useState<RadarLocalModelState[]>([]);
|
||||||
|
const [editingKey, setEditingKey] = useState<string | null>(null);
|
||||||
|
const [displayName, setDisplayName] = useState("");
|
||||||
|
const [enabled, setEnabled] = useState(true);
|
||||||
|
const [saving, setSaving] = useState(false);
|
||||||
|
|
||||||
|
const loadState = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/radar/local-model-state");
|
||||||
|
if (!response.ok) return;
|
||||||
|
const payload = await response.json();
|
||||||
|
setStates(Array.isArray(payload.states) ? payload.states : []);
|
||||||
|
} catch {
|
||||||
|
onError(t("errorLoading"));
|
||||||
|
}
|
||||||
|
}, [onError, t]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
void loadState();
|
||||||
|
}, [loadState]);
|
||||||
|
|
||||||
|
const stateByKey = useMemo(
|
||||||
|
() => new Map(states.map((state) => [`${state.provider}:${state.modelId}`, state])),
|
||||||
|
[states]
|
||||||
|
);
|
||||||
|
const hiddenModels = useMemo(() => states.filter((state) => state.tombstoned), [states]);
|
||||||
|
|
||||||
|
const applyResponse = useCallback(async (response: Response) => {
|
||||||
|
if (!response.ok) throw new Error("save_failed");
|
||||||
|
const payload = await response.json();
|
||||||
|
setStates(Array.isArray(payload.states) ? payload.states : []);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const mutate = useCallback(
|
||||||
|
async (operation: () => Promise<Response>) => {
|
||||||
|
setSaving(true);
|
||||||
|
onError("");
|
||||||
|
try {
|
||||||
|
await applyResponse(await operation());
|
||||||
|
setEditingKey(null);
|
||||||
|
await refreshCatalog();
|
||||||
|
} catch {
|
||||||
|
onError(t("localStateSaveFailed"));
|
||||||
|
} finally {
|
||||||
|
setSaving(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[applyResponse, onError, refreshCatalog, t]
|
||||||
|
);
|
||||||
|
|
||||||
|
const beginEdit = useCallback((entry: RadarMergedEntry) => {
|
||||||
|
setEditingKey(`${entry.provider}:${entry.modelId}`);
|
||||||
|
setDisplayName(entry.displayName);
|
||||||
|
setEnabled(entry.enabled !== false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const saveOverride = useCallback(
|
||||||
|
(entry: RadarMergedEntry) =>
|
||||||
|
mutate(() =>
|
||||||
|
fetch("/api/radar/local-model-state", {
|
||||||
|
method: "PATCH",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
provider: entry.provider,
|
||||||
|
modelId: entry.modelId,
|
||||||
|
displayName,
|
||||||
|
enabled,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
[displayName, enabled, mutate]
|
||||||
|
);
|
||||||
|
|
||||||
|
const resetOverride = useCallback(
|
||||||
|
(entry: Pick<RadarMergedEntry, "provider" | "modelId">) => {
|
||||||
|
const query = new URLSearchParams({ provider: entry.provider, modelId: entry.modelId });
|
||||||
|
return mutate(() =>
|
||||||
|
fetch(`/api/radar/local-model-state?${query.toString()}`, { method: "DELETE" })
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[mutate]
|
||||||
|
);
|
||||||
|
|
||||||
|
const setTombstone = useCallback(
|
||||||
|
(provider: string, modelId: string, tombstoned: boolean) =>
|
||||||
|
mutate(() =>
|
||||||
|
fetch("/api/radar/local-model-state", {
|
||||||
|
method: "PUT",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ provider, modelId, tombstoned }),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
[mutate]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card>
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full">
|
||||||
|
<thead>
|
||||||
|
<tr className="text-left text-sm text-text-muted border-b border-border">
|
||||||
|
<th className="pb-3 font-medium">{t("colProvider")}</th>
|
||||||
|
<th className="pb-3 font-medium">{t("colModel")}</th>
|
||||||
|
<th className="pb-3 font-medium">{t("colQuota")}</th>
|
||||||
|
<th className="pb-3 font-medium">{t("colContext")}</th>
|
||||||
|
<th className="pb-3 font-medium">{t("colCapabilities")}</th>
|
||||||
|
<th className="pb-3 font-medium">{t("colTos")}</th>
|
||||||
|
<th className="pb-3 font-medium text-right">{t("colActions")}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{entries.map((entry) => {
|
||||||
|
const key = `${entry.provider}:${entry.modelId}`;
|
||||||
|
const localState = stateByKey.get(key);
|
||||||
|
const hasOverride =
|
||||||
|
localState && (localState.displayName !== null || localState.enabled !== null);
|
||||||
|
return (
|
||||||
|
<tr
|
||||||
|
key={key}
|
||||||
|
className={`border-b border-border/50 last:border-b-0 ${
|
||||||
|
entry.enabled === false ? "opacity-50" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<td className="py-3">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="font-medium">{entry.provider}</span>
|
||||||
|
{entry.origin === "radar" && (
|
||||||
|
<span className="text-[10px] px-1.5 py-0.5 rounded bg-violet-500/10 text-violet-400 font-medium">
|
||||||
|
{t("newBadge")}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{entry.origin === "local" && (
|
||||||
|
<span className="text-[10px] px-1.5 py-0.5 rounded bg-blue-500/10 text-blue-400 font-medium">
|
||||||
|
{t("localBadge")}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{entry.setup?.keyUrl && (
|
||||||
|
<Link
|
||||||
|
href={`/dashboard/radar/setup?provider=${encodeURIComponent(entry.provider)}`}
|
||||||
|
className="text-xs text-violet-400 hover:underline"
|
||||||
|
title={t("setupGuide")}
|
||||||
|
>
|
||||||
|
⚙
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{entry.enabled === false && entry.disabledBy === "radar" && (
|
||||||
|
<p className="text-xs text-red-400 mt-0.5">{t("disabledByFeed")}</p>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="py-3 text-text-muted text-sm font-mono max-w-[240px]">
|
||||||
|
{editingKey === key ? (
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={displayName}
|
||||||
|
onChange={(event) => setDisplayName(event.target.value)}
|
||||||
|
aria-label={t("modelDisplayName")}
|
||||||
|
maxLength={160}
|
||||||
|
className="w-full min-w-[180px] px-2 py-1 rounded border border-border bg-transparent text-text-main focus:outline-none focus:ring-2 focus:ring-violet-500"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span className="block truncate">{entry.displayName}</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="py-3 text-sm">{budgetLabel(entry)}</td>
|
||||||
|
<td className="py-3 text-sm text-text-muted">
|
||||||
|
{entry.contextWindow ? `${(entry.contextWindow / 1000).toFixed(0)}K` : "—"}
|
||||||
|
</td>
|
||||||
|
<td className="py-3">
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{capabilityBadge(
|
||||||
|
t("capTools"),
|
||||||
|
entry.capabilities?.tools,
|
||||||
|
"bg-blue-500/10 text-blue-400"
|
||||||
|
)}
|
||||||
|
{capabilityBadge(
|
||||||
|
t("capVision"),
|
||||||
|
entry.capabilities?.vision,
|
||||||
|
"bg-purple-500/10 text-purple-400"
|
||||||
|
)}
|
||||||
|
{capabilityBadge(
|
||||||
|
t("capThinking"),
|
||||||
|
entry.capabilities?.thinking,
|
||||||
|
"bg-amber-500/10 text-amber-400"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3">
|
||||||
|
<span
|
||||||
|
className={`text-xs px-2 py-1 rounded ${
|
||||||
|
entry.tos === "ok"
|
||||||
|
? "bg-green-500/10 text-green-400"
|
||||||
|
: entry.tos === "caution"
|
||||||
|
? "bg-yellow-500/10 text-yellow-400"
|
||||||
|
: entry.tos === "avoid"
|
||||||
|
? "bg-red-500/10 text-red-400"
|
||||||
|
: "bg-gray-500/10 text-gray-400"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{entry.tos}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 pl-3">
|
||||||
|
{editingKey === key ? (
|
||||||
|
<div className="flex flex-wrap items-center justify-end gap-2">
|
||||||
|
<label className="inline-flex items-center gap-1 text-xs text-text-muted">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={enabled}
|
||||||
|
disabled={entry.disabledBy === "radar"}
|
||||||
|
onChange={(event) => setEnabled(event.target.checked)}
|
||||||
|
/>
|
||||||
|
{t("modelEnabled")}
|
||||||
|
</label>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
disabled={saving || displayName.trim().length === 0}
|
||||||
|
onClick={() => void saveOverride(entry)}
|
||||||
|
className="text-xs text-violet-400 hover:underline disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{t("saveModel")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
disabled={saving}
|
||||||
|
onClick={() => setEditingKey(null)}
|
||||||
|
className="text-xs text-text-muted hover:text-text-main disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{t("cancelEdit")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-wrap items-center justify-end gap-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
disabled={saving}
|
||||||
|
onClick={() => beginEdit(entry)}
|
||||||
|
className="text-xs text-violet-400 hover:underline disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{t("editModel")}
|
||||||
|
</button>
|
||||||
|
{hasOverride && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
disabled={saving}
|
||||||
|
onClick={() => void resetOverride(entry)}
|
||||||
|
className="text-xs text-text-muted hover:text-text-main disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{t("resetModel")}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
disabled={saving}
|
||||||
|
onClick={() => void setTombstone(entry.provider, entry.modelId, true)}
|
||||||
|
className="text-xs text-red-400 hover:underline disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{t("hideModel")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{hiddenModels.length > 0 && (
|
||||||
|
<Card>
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
<h3 className="text-sm font-semibold">{t("hiddenModelsTitle")}</h3>
|
||||||
|
{hiddenModels.map((state) => (
|
||||||
|
<div
|
||||||
|
key={`${state.provider}:${state.modelId}:hidden`}
|
||||||
|
className="flex flex-wrap items-center justify-between gap-3 border-b border-border/50 pb-3 last:border-b-0 last:pb-0"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<span className="font-medium">{state.provider}</span>
|
||||||
|
<span className="ml-2 text-sm font-mono text-text-muted">
|
||||||
|
{state.displayName ?? state.modelId}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
disabled={saving}
|
||||||
|
onClick={() => void setTombstone(state.provider, state.modelId, false)}
|
||||||
|
className="text-sm text-violet-400 hover:underline disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{t("restoreModel")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
201
src/app/(dashboard)/dashboard/radar/combos/page.tsx
Normal file
201
src/app/(dashboard)/dashboard/radar/combos/page.tsx
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { notFound } from "next/navigation";
|
||||||
|
|
||||||
|
import type { ComboBuilderOptionsPayload } from "@/lib/combos/builderOptions";
|
||||||
|
import type { MergedEntry } from "@/lib/radar/applyFeed";
|
||||||
|
import {
|
||||||
|
buildRadarComboSuggestions,
|
||||||
|
type RadarComboSuggestion,
|
||||||
|
} from "@/lib/radar/comboSuggestions";
|
||||||
|
import { Card } from "@/shared/components";
|
||||||
|
|
||||||
|
interface RadarCatalogPayload {
|
||||||
|
entries?: MergedEntry[];
|
||||||
|
meta?: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
function comboNames(payload: ComboBuilderOptionsPayload): Set<string> {
|
||||||
|
return new Set(payload.comboRefs.map((combo) => combo.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RadarCombosPage() {
|
||||||
|
const t = useTranslations("radarCombosPage");
|
||||||
|
const [entries, setEntries] = useState<MergedEntry[]>([]);
|
||||||
|
const [providers, setProviders] = useState<ComboBuilderOptionsPayload["providers"]>([]);
|
||||||
|
const [existingNames, setExistingNames] = useState<Set<string>>(new Set());
|
||||||
|
const [createdNames, setCreatedNames] = useState<Set<string>>(new Set());
|
||||||
|
const [hasCatalog, setHasCatalog] = useState(false);
|
||||||
|
const [flagOff, setFlagOff] = useState(false);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [creatingName, setCreatingName] = useState<string | null>(null);
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function load() {
|
||||||
|
try {
|
||||||
|
const [catalogResponse, optionsResponse] = await Promise.all([
|
||||||
|
fetch("/api/radar/catalog"),
|
||||||
|
fetch("/api/combos/builder/options"),
|
||||||
|
]);
|
||||||
|
if (catalogResponse.status === 404) {
|
||||||
|
setFlagOff(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!catalogResponse.ok || !optionsResponse.ok) throw new Error("load_failed");
|
||||||
|
|
||||||
|
const catalog = (await catalogResponse.json()) as RadarCatalogPayload;
|
||||||
|
const options = (await optionsResponse.json()) as ComboBuilderOptionsPayload;
|
||||||
|
if (!Array.isArray(catalog.entries) || !Array.isArray(options.providers)) {
|
||||||
|
throw new Error("invalid_shape");
|
||||||
|
}
|
||||||
|
|
||||||
|
setEntries(catalog.entries);
|
||||||
|
setProviders(options.providers);
|
||||||
|
setExistingNames(comboNames(options));
|
||||||
|
setHasCatalog(catalog.meta != null);
|
||||||
|
} catch {
|
||||||
|
setError(t("loadFailed"));
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void load();
|
||||||
|
}, [t]);
|
||||||
|
|
||||||
|
const suggestions = useMemo(
|
||||||
|
() => buildRadarComboSuggestions({ entries, providers, existingComboNames: existingNames }),
|
||||||
|
[entries, providers, existingNames]
|
||||||
|
);
|
||||||
|
|
||||||
|
const refreshExistingName = useCallback(async (name: string): Promise<boolean> => {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/combos/builder/options");
|
||||||
|
if (!response.ok) return false;
|
||||||
|
const options = (await response.json()) as ComboBuilderOptionsPayload;
|
||||||
|
if (!Array.isArray(options.comboRefs)) return false;
|
||||||
|
const names = comboNames(options);
|
||||||
|
if (![...names].some((candidate) => candidate.toLowerCase() === name.toLowerCase())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
setExistingNames(names);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const createSuggestion = useCallback(
|
||||||
|
async (suggestion: RadarComboSuggestion) => {
|
||||||
|
setCreatingName(suggestion.name);
|
||||||
|
setError("");
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/combos", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(suggestion.payload),
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
if (response.status === 400 && (await refreshExistingName(suggestion.name))) return;
|
||||||
|
throw new Error("create_failed");
|
||||||
|
}
|
||||||
|
setExistingNames((current) => new Set([...current, suggestion.name]));
|
||||||
|
setCreatedNames((current) => new Set([...current, suggestion.name]));
|
||||||
|
} catch {
|
||||||
|
setError(t("createFailed"));
|
||||||
|
} finally {
|
||||||
|
setCreatingName(null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[refreshExistingName, t]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (flagOff) notFound();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-6">
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
<Link
|
||||||
|
href="/dashboard/radar"
|
||||||
|
className="text-sm text-text-muted hover:text-text-main transition-colors w-fit"
|
||||||
|
>
|
||||||
|
← {t("backToRadar")}
|
||||||
|
</Link>
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">{t("title")}</h1>
|
||||||
|
<p className="text-sm text-text-muted mt-1">{t("subtitle")}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{error && <div className="p-3 rounded-lg bg-red-500/10 text-red-400 text-sm">{error}</div>}
|
||||||
|
|
||||||
|
{loading ? (
|
||||||
|
<div className="flex items-center justify-center min-h-[200px] text-text-muted">
|
||||||
|
{t("loading")}
|
||||||
|
</div>
|
||||||
|
) : !hasCatalog ? (
|
||||||
|
<Card>
|
||||||
|
<p className="text-center text-text-muted py-8">{t("catalogRequired")}</p>
|
||||||
|
</Card>
|
||||||
|
) : suggestions.length === 0 ? (
|
||||||
|
<Card>
|
||||||
|
<p className="text-center text-text-muted py-8">{t("noSuggestions")}</p>
|
||||||
|
</Card>
|
||||||
|
) : (
|
||||||
|
<div className="grid gap-4">
|
||||||
|
{suggestions.map((suggestion) => {
|
||||||
|
const creating = creatingName === suggestion.name;
|
||||||
|
const created = createdNames.has(suggestion.name);
|
||||||
|
return (
|
||||||
|
<Card key={suggestion.familyId}>
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<span className="text-xs uppercase tracking-wide text-text-muted">
|
||||||
|
{t("familyLabel")}
|
||||||
|
</span>
|
||||||
|
<h2 className="text-lg font-semibold font-mono">{suggestion.familyId}</h2>
|
||||||
|
<p className="text-sm text-text-muted">{t("strategyReason")}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<span className="text-sm font-medium">{t("modelsLabel")}</span>
|
||||||
|
{suggestion.models.map((model) => (
|
||||||
|
<div
|
||||||
|
key={`${model.providerId}:${model.modelId}`}
|
||||||
|
className="flex flex-wrap items-center justify-between gap-2 rounded-lg border border-border px-3 py-2"
|
||||||
|
>
|
||||||
|
<span className="font-medium">{model.providerName}</span>
|
||||||
|
<span className="font-mono text-sm text-text-muted">
|
||||||
|
{model.qualifiedModel}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => void createSuggestion(suggestion)}
|
||||||
|
disabled={creating || suggestion.alreadyExists}
|
||||||
|
className="self-start px-4 py-2 text-sm font-medium rounded-lg bg-violet-500 text-white hover:bg-violet-600 transition-colors disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{created
|
||||||
|
? t("created")
|
||||||
|
: suggestion.alreadyExists
|
||||||
|
? t("alreadyCreated")
|
||||||
|
: creating
|
||||||
|
? t("generating")
|
||||||
|
: t("generateButton")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user