Compare commits

...

41 Commits

Author SHA1 Message Date
Diego Rodrigues de Sa e Souza 9e4495b85b Merge pull request #1144 from diegosouzapw/release/v3.6.2
Build Electron Desktop App / Validate version (push) Failing after 41s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
chore(release): v3.6.2 — Provider Expansion and Stabilization
2026-04-11 15:17:58 -03:00
diegosouzapw b5e1c8e47b fix: remove outdated assertions in cache page integration test 2026-04-11 15:12:27 -03:00
diegosouzapw 36a05831ab chore(release): v3.6.2 — provider expansion and stabilization 2026-04-11 13:11:57 -03:00
diegosouzapw 12b895f94a fix(tests): accept both cloudflared error message variants in tunnel test regex 2026-04-11 12:28:35 -03:00
diegosouzapw e89015649e fix(tests): align maskEmail test assertions with new less-aggressive masking behavior
Updated mask-email.test.mjs and model-sync-route.test.mjs to match
the revised maskEmail function that preserves full domain names for
account differentiation (die********@gmail.com vs old di*********@g****.com).
2026-04-11 12:09:20 -03:00
diegosouzapw 86fc7841b8 docs: update provider counts to 100+ across all documentation (33 new providers added)
- CHANGELOG: documented 33 new API Key providers (DeepInfra, SambaNova, Meta Llama API, AI21 Labs, Databricks, Snowflake, GigaChat, etc.)
- README: updated tagline, unified endpoint, and feature descriptions from 60+ to 100+
- AGENTS.md: updated project description and full API Key provider list (48+ → 91)
- ARCHITECTURE.md: updated executive summary
- i18n: synced all 33 language README and ARCHITECTURE files
2026-04-11 12:01:13 -03:00
diegosouzapw 76e920fc1a docs(changelog): update for bugs #993 and #988 2026-04-11 11:49:54 -03:00
diegosouzapw 99591a2b0f fix: resolve PDF attachment drops in Gemini translation via OpenAI-compatible endpoints (#993) 2026-04-11 11:48:20 -03:00
diegosouzapw 770b70a135 fix: correct SkillsMP marketplace API response mapping for Docker instances (#988) 2026-04-11 11:48:13 -03:00
diegosouzapw 6845ef6bde chore(security): add electron and docker ecosystems to dependabot 2026-04-11 11:36:58 -03:00
diegosouzapw d4609762bb fix: resolve macOS Electron ABI mismatch and test regressions (#1081) 2026-04-11 11:36:58 -03:00
diegosouzapw ebf63a75d5 fix: include Next build isolation script in published package files (#1126) 2026-04-11 11:36:58 -03:00
diegosouzapw 3effbe5f06 fix: decrease email mask aggression to maintain account distinction (#1137) 2026-04-11 11:36:58 -03:00
diegosouzapw c742433d34 fix: enforce persistent local bind mounts for docker data volumes 2026-04-11 11:36:58 -03:00
gfhfyjbr bd33b53805 fix(stream): harden responses SSE keepalives (#1146)
Integrated into release/v3.6.2
2026-04-11 11:36:40 -03:00
Randi 1d6739b683 fix semantic cache toggle and redesign cache management (#1135)
Integrated into release/v3.6.2
2026-04-11 09:44:48 -03:00
jonesfernandess e75baed4b6 docs: add macOS better-sqlite3 rebuild fix to troubleshooting (#1119)
Integrated into release/v3.6.2
2026-04-11 09:44:45 -03:00
dependabot[bot] 55f73d34e1 deps: bump next-intl from 4.9.0 to 4.9.1 (#1128)
Integrated into release/v3.6.2
2026-04-11 09:44:34 -03:00
dependabot[bot] 557157c2d6 build(deps): bump docker/login-action from 3 to 4 (#1124)
Integrated into release/v3.6.2
2026-04-11 09:44:30 -03:00
dependabot[bot] 0bae35d387 build(deps): bump peter-evans/dockerhub-description from 4 to 5 (#1123)
Integrated into release/v3.6.2
2026-04-11 09:44:27 -03:00
dependabot[bot] c7062bc560 build(deps): bump actions/github-script from 8 to 9 (#1122)
Integrated into release/v3.6.2
2026-04-11 09:44:24 -03:00
dependabot[bot] a344352365 build(deps): bump actions/cache from 4 to 5 (#1121)
Integrated into release/v3.6.2
2026-04-11 09:44:21 -03:00
dependabot[bot] 33d86ad3b5 build(deps): bump actions/upload-artifact from 4 to 7 (#1120)
Integrated into release/v3.6.2
2026-04-11 09:44:18 -03:00
diegosouzapw 8bacde0262 feat: global email privacy toggle with eye icon button
- Add emailPrivacyStore (Zustand + persist) for global toggle state
- Add EmailPrivacyToggle component with eye open/closed icons
- Add pickDisplayValue() visibility-aware masking function
- Integrate toggle into provider detail, usage limits & playground pages
- Per-modal showEmail now uses global store (synced across all pages)
- Default: emails hidden; toggle persists across page reloads
- Add showEmails/hideEmails i18n keys
- Update CHANGELOG.md and openapi.yaml to v3.6.2
2026-04-11 09:38:17 -03:00
diegosouzapw 87c82071c0 docs(i18n): sync uninstall instructions to all templates 2026-04-10 15:11:18 -03:00
diegosouzapw 1f72810649 feat: add uninstall and full-uninstall npm scripts for cleaner removals 2026-04-10 15:07:57 -03:00
diegosouzapw 6711095dd6 docs(agents): add stale issue closure policy to resolve-issues workflow 2026-04-10 15:04:27 -03:00
diegosouzapw e39a42464e fix: ensure graceful next js shutdown on electron before-quit to prevent sqlite db locks (#1081) 2026-04-10 12:51:18 -03:00
Diego Rodrigues de Sa e Souza 515674b6cf chore(release): v3.6.1 — OAuth env repair + i18n fix (#1117)
Build Electron Desktop App / Validate version (push) Failing after 41s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
* chore: bump to v3.6.1

* fix(i18n): add missing provider messages across locales (#1111)

Integrated into release/v3.6.1 — adds missing filterModels, modelsActive, showModel, hideModel i18n keys across all 32 locales

* fix: add Repair env action for OAuth providers (#1116)

Integrated into release/v3.6.1 — adds OAuth env repair feature with full 33-language i18n support and backupPath security fix

* chore(release): v3.6.1 — OAuth env repair + i18n fix

* fix: add targetFormat openai-responses to gpt-5.4 and gpt-5.4-mini (#1114)

* fix: add targetFormat openai-responses to gpt-5.4 and gpt-5.4-mini (#1114)

* chore: force CI trigger

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: Ilham Ramadhan <28677129+rilham97@users.noreply.github.com>
Co-authored-by: Artёm <470045+yart@users.noreply.github.com>
2026-04-10 12:19:15 -03:00
Diego Rodrigues de Sa e Souza 37cc63e493 Release v3.6.0 (#1109)
Build Electron Desktop App / Validate version (push) Failing after 31s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
* chore: create release/v3.6.0 branch

* fix: add row count limits to prevent DB bloat and handle HTML error responses (#1104)

Integrated into release/v3.6.0

* fix combo smoke test payload for thinking models (#1105)

Integrated into release/v3.6.0

* fix: improve Android/Termux ARM64 support for better-sqlite3 (#1107)

Integrated into release/v3.6.0

* chore: finalize CHANGELOG and sync versions for v3.6.0

* fix(tests): align CI tests with v3.6.0 changes

- compliance: match new cleanupExpiredLogs return shape (trimmed/maxRows)
- model-sync: accept masked email in account field
- e2e: allow 401/403/307 for auth-protected /api/providers endpoint

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com>
Co-authored-by: Randi <55005611+rdself@users.noreply.github.com>
Co-authored-by: Suhayli <73960279+Suhay1i@users.noreply.github.com>
2026-04-10 09:56:42 -03:00
diegosouzapw 4cd43f9c93 fix(test): make token layout test locale-agnostic
Build Electron Desktop App / Validate version (push) Failing after 28s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
2026-04-09 22:28:01 -03:00
Diego Rodrigues de Sa e Souza 691d83e596 Merge pull request #1102 from diegosouzapw/release/v3.5.9
Release v3.5.9 merged to main
2026-04-09 22:22:28 -03:00
diegosouzapw 4bca25d783 chore(release): v3.5.9 — combo ordering, stream failures, Docker EXDEV, token layout 2026-04-09 22:22:02 -03:00
Randi 74a5bcb3a9 Add persistent combo ordering and reorder sidebar items (#1095)
Integrated into release/v3.5.9 with openapi.yaml version fix
2026-04-09 21:16:42 -03:00
Randi 9f55159bd5 Fix request log detail token layout (#1096)
Integrated into release/v3.5.9
2026-04-09 21:15:14 -03:00
Randi f118082f6b fix(docker): handle EXDEV in isolated build (#1097)
Integrated into release/v3.5.9
2026-04-09 21:15:12 -03:00
Artёm 586e9f328f fix(stream): surface Responses failures and preserve upstream model (#1098)
Integrated into release/v3.5.9
2026-04-09 21:15:09 -03:00
diegosouzapw fb9d52a19b chore: create release/v3.5.9 branch 2026-04-09 21:10:06 -03:00
diegosouzapw 815a7b6e1d chore(release): verify v3.5.8 sync (changelog, docs)
Build Electron Desktop App / Validate version (push) Failing after 33s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
2026-04-09 19:12:01 -03:00
Diego Rodrigues de Sa e Souza 336d889034 Release v3.5.8 (#1092)
* chore: bump to v3.5.8-dev

* fix(combo): quarantine degraded provider-model pairs adaptively (#1090)

Integrated into release/v3.5.8

* fix(healthcheck): keep active accounts routable after refresh failure (#1085)

Integrated into release/v3.5.8

* chore: squash PR 1089

* Merge PR 1088: docs(deps): bump axios from 1.14.0 to 1.15.0

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: Wellington Fonseca <wf.tecnologia@hotmail.com>
Co-authored-by: xiaoge1688 <129356184+xiaoge1688@users.noreply.github.com>
2026-04-09 18:18:45 -03:00
diegosouzapw bba7479688 fix(build): force webpack in Next.js 16 and prevent app/ routing conflicts 2026-04-09 18:03:42 -03:00
218 changed files with 20065 additions and 11183 deletions
+182
View File
@@ -0,0 +1,182 @@
# Fix CI Workflow
Look up the latest GitHub Actions CI run for the current release branch, diagnose all failures, fix them locally, push, and wait for the new CI run to go green before notifying the user.
---
## Phase 1: Identify the Failing CI Run
### 1. Determine the current release version and branch
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router
VERSION=$(node -p "require('./package.json').version")
BRANCH=$(git branch --show-current)
echo "Version: $VERSION"
echo "Branch: $BRANCH"
```
### 2. Find the latest CI run for the release PR
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router
# Find the PR number for the release branch
PR_NUMBER=$(gh pr list --repo diegosouzapw/OmniRoute --head "$BRANCH" --json number --jq '.[0].number')
echo "PR: #$PR_NUMBER"
# Get the latest CI run
RUN_ID=$(gh run list --repo diegosouzapw/OmniRoute --branch "$BRANCH" --workflow ci.yml --limit 1 --json databaseId --jq '.[0].databaseId')
echo "Latest CI Run: $RUN_ID"
echo "URL: https://github.com/diegosouzapw/OmniRoute/actions/runs/$RUN_ID"
```
---
## Phase 2: Diagnose Failures
### 3. List all failing jobs
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router
RUN_ID=$(gh run list --repo diegosouzapw/OmniRoute --branch "$(git branch --show-current)" --workflow ci.yml --limit 1 --json databaseId --jq '.[0].databaseId')
gh run view "$RUN_ID" --repo diegosouzapw/OmniRoute --json jobs --jq '.jobs[] | select(.conclusion == "failure") | {name: .name, conclusion: .conclusion, steps: [.steps[] | select(.conclusion == "failure") | .name]}'
```
### 4. Download and analyze failure logs
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router
RUN_ID=$(gh run list --repo diegosouzapw/OmniRoute --branch "$(git branch --show-current)" --workflow ci.yml --limit 1 --json databaseId --jq '.[0].databaseId')
gh run view "$RUN_ID" --repo diegosouzapw/OmniRoute --log-failed 2>&1 | grep -aE "not ok|FAIL|Error:|error:|AssertionError|expected|actual" | grep -v "node_modules\|runner\|git version" | head -50
```
### 5. Classify each failure
For each failing job, determine the root cause category:
| Category | Pattern | Fix Strategy |
| ------------------ | ---------------------------------- | ------------------------------------------ |
| **docs-sync** | OpenAPI/CHANGELOG version mismatch | Run `/version-bump` step 7-8 |
| **Test assertion** | `not ok` + `AssertionError` | Update test expectations to match new code |
| **E2E flaky** | Auth-related 401/403/307 | Make tests tolerate auth states |
| **Coverage gate** | `below threshold` | Add more tests or adjust threshold |
| **Lint** | ESLint errors | Fix code or update rules |
| **Build** | Compilation errors | Fix TypeScript issues |
---
## Phase 3: Apply Fixes
### 6. Fix each failure
For each classified failure:
1. **Read the failing test file** to understand the assertion
2. **Read the production source** to understand the new behavior
3. **Update the test** to match the current behavior
4. **Run the test locally** to verify the fix
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router
# Run the specific failing test file(s) to confirm fixes
# Example: node --import tsx/esm --test tests/unit/FAILING_FILE.test.mjs
```
### 7. Run the full local test suite
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router
npm test
```
### 8. Run docs-sync check
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router
npm run check:docs-sync
```
---
## Phase 4: Push and Monitor
### 9. Commit and push fixes
// turbo-all
```bash
cd /home/diegosouzapw/dev/proxys/9router
git add -A
git commit -m "fix(tests): align CI tests with release changes"
git push origin "$(git branch --show-current)"
```
### 10. Wait for CI to trigger and find the new run
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router
sleep 15
BRANCH=$(git branch --show-current)
NEW_RUN_ID=$(gh run list --repo diegosouzapw/OmniRoute --branch "$BRANCH" --workflow ci.yml --limit 1 --json databaseId --jq '.[0].databaseId')
echo "New CI Run: $NEW_RUN_ID"
echo "URL: https://github.com/diegosouzapw/OmniRoute/actions/runs/$NEW_RUN_ID"
```
### 11. Monitor the CI run
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router
BRANCH=$(git branch --show-current)
NEW_RUN_ID=$(gh run list --repo diegosouzapw/OmniRoute --branch "$BRANCH" --workflow ci.yml --limit 1 --json databaseId --jq '.[0].databaseId')
gh run watch "$NEW_RUN_ID" --repo diegosouzapw/OmniRoute --exit-status
```
If `gh run watch` exits with 0, the CI is green. If it exits with non-zero, go back to Phase 2 and repeat.
### 12. 🛑 STOP — Notify User
Present a summary to the user:
- **Previous CI run**: URL, list of failures
- **Root causes**: What broke and why
- **Fixes applied**: What tests were changed
- **New CI run**: URL, all-green status
- **PR status**: Ready for review/merge
---
## Common CI Failure Patterns
| Failure | Root Cause | Fix |
| ------------------------------------------ | -------------------------------------- | ----------------------------- |
| `docs-sync FAIL - OpenAPI version differs` | Version not synced after bump | `sed -i` openapi.yaml |
| `docs-sync FAIL - CHANGELOG first section` | Missing `## [Unreleased]` header | Add unreleased section |
| `not ok - cleanupExpiredLogs` | Return shape changed (new fields) | Update `assert.deepEqual` |
| `not ok - email masking` | Email now masked in call logs | Assert masked pattern instead |
| `E2E /api/providers` returns non-200 | Auth enabled in CI, endpoint protected | Accept 401/403 as valid |
| `coverage below 60%` | New untested code | Add unit tests |
## Notes
- This workflow is **iterative**: if the first fix attempt doesn't clear all failures, repeat Phases 2-4.
- Always run tests **locally** before pushing to avoid wasting CI minutes.
- The CI is triggered automatically on push to branches with open PRs to `main`.
- Use `gh run watch` to monitor in real-time instead of polling.
+1
View File
@@ -100,6 +100,7 @@ For each bug, classify into one of 5 actions:
| ---------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| **✅ CLOSE — Already Fixed** | Owner responded with fix + no user follow-up, OR community confirmed fix | Close with comment citing which version fixed it |
| **✅ CLOSE — Duplicate** | Bot flagged >85% similarity + user provides no new info | Close referencing the original issue |
| **✅ CLOSE — Stale** | We requested logs/info > 7 days ago with no reply | Close thanking the user, invite to reopen if needed |
| **📝 RESPOND — Needs Info** | Issue is real but missing critical reproduction details | Comment asking for specifics per `/issue-triage` |
| **📝 RESPOND — User Config** | Error is caused by unsupported env (Node version, wrong model path, missing API enablement) | Comment explaining the user-side fix |
| **🔧 FIX — Code Change** | Root cause is confirmed in the codebase | Research, implement, test, commit on release branch |
+1 -1
View File
@@ -10,7 +10,7 @@ JWT_SECRET=
API_KEY_SECRET=
# Initial admin password — CHANGE THIS before first use!
INITIAL_PASSWORD=CHANGEME
INITIAL_PASSWORD=123456
# DATA_DIR=/var/lib/omniroute
# Storage (SQLite)
+16
View File
@@ -29,3 +29,19 @@ updates:
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "npm"
directory: "/electron"
schedule:
interval: "weekly"
day: "monday"
commit-message:
prefix: "deps"
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
commit-message:
prefix: "deps"
+3 -3
View File
@@ -67,7 +67,7 @@ jobs:
- name: Upload result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: i18n-${{ matrix.lang }}
path: result.txt
@@ -201,7 +201,7 @@ jobs:
cat coverage/coverage-report.md >> "$GITHUB_STEP_SUMMARY"
- name: Upload coverage artifacts
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: coverage-report
path: |
@@ -281,7 +281,7 @@ jobs:
echo "This PR changes production code in \`src/\`, \`open-sse/\`, \`electron/\`, or \`bin/\` without accompanying automated tests."
fi
} > .artifacts/pr-coverage-comment.md
- uses: actions/github-script@v8
- uses: actions/github-script@v9
with:
script: |
const fs = require("fs");
+3 -3
View File
@@ -36,13 +36,13 @@ jobs:
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -83,7 +83,7 @@ jobs:
docker buildx imagetools inspect "${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}"
- name: Update Docker Hub description
uses: peter-evans/dockerhub-description@v4
uses: peter-evans/dockerhub-description@v5
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
+2 -2
View File
@@ -81,7 +81,7 @@ jobs:
cache: npm
- name: Cache node_modules
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
@@ -148,7 +148,7 @@ jobs:
fi
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: electron-${{ matrix.platform }}
path: release-assets/
+10 -4
View File
@@ -3,8 +3,9 @@
## Project
Unified AI proxy/router — route any LLM through one endpoint. Multi-provider support
with **60+ providers** (OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Fireworks,
Cohere, NVIDIA, Cerebras, Pollinations, Puter, Cloudflare AI, HuggingFace, and many more)
with **100+ providers** (OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Fireworks,
Cohere, NVIDIA, Cerebras, Pollinations, Puter, Cloudflare AI, HuggingFace, DeepInfra,
SambaNova, Meta Llama API, Moonshot AI, AI21 Labs, Databricks, Snowflake, and many more)
with **MCP Server** (25 tools), **A2A v0.3 Protocol**, and **Electron desktop app**.
## Stack
@@ -157,13 +158,18 @@ Zod schemas, and unit tests aligned when editing.
- **Free** (4): Qoder AI, Qwen Code, Gemini CLI (deprecated), Kiro AI
- **OAuth** (8): Claude Code, Antigravity, Codex, GitHub Copilot, Cursor, Kimi Coding, Kilo Code, Cline
- **API Key** (48+): OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Perplexity,
- **API Key** (91): OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Perplexity,
Together, Fireworks, Cerebras, Cohere, NVIDIA, Nebius, SiliconFlow, Hyperbolic,
HuggingFace, OpenRouter, Vertex AI, Cloudflare AI, Scaleway, AI/ML API, Pollinations,
Puter, Longcat, Alibaba, Kimi, Minimax, Blackbox, Synthetic, Kilo Gateway,
Z.AI, GLM, Deepgram, AssemblyAI, ElevenLabs, Cartesia, PlayHT, Inworld,
NanoBanana, SD WebUI, ComfyUI, Ollama Cloud, Perplexity Search, Serper, Brave, Exa,
Tavily, OpenCode Zen/Go, Bailian Coding Plan, and more.
Tavily, OpenCode Zen/Go, Bailian Coding Plan, DeepInfra, Vercel AI Gateway,
Lambda AI, SambaNova, nScale, OVHcloud AI, Baseten, PublicAI, Moonshot AI,
Meta Llama API, v0 (Vercel), Morph, Featherless AI, FriendliAI, LlamaGate,
Galadriel, Weights & Biases Inference, Volcengine, AI21 Labs, Venice.ai,
Codestral, Upstage, Maritalk, Xiaomi MiMo, Inference.net, NanoGPT, Predibase,
Bytez, Heroku AI, Databricks, Snowflake Cortex, GigaChat (Sber), and more.
- **Custom**: OpenAI-compatible (`openai-compatible-*`) and Anthropic-compatible (`anthropic-compatible-*`) prefixes
Providers are registered in `src/shared/constants/providers.ts` with Zod validation at module load.
+78
View File
@@ -4,6 +4,84 @@
---
## [3.6.2] — 2026-04-11
### ✨ New Features
- **33 New API Key Providers:** Massive provider expansion adding DeepInfra, Vercel AI Gateway, Lambda AI, SambaNova, nScale, OVHcloud AI, Baseten, PublicAI, Moonshot AI, Meta Llama API, v0 (Vercel), Morph, Featherless AI, FriendliAI, LlamaGate, Galadriel, Weights & Biases Inference, Volcengine, AI21 Labs, Venice.ai, Codestral, Upstage, Maritalk, Xiaomi MiMo, Inference.net, NanoGPT, Predibase, Bytez, Heroku AI, Databricks, Snowflake Cortex, and GigaChat (Sber). OmniRoute now supports **100+ providers** (4 Free + 8 OAuth + 91 API Key + Custom compatible)
- **Global Email Privacy Toggle:** Added a persistent eye-icon toggle button across all dashboard pages (Providers, Usage Limits, Playground) that reveals or hides masked email addresses. Toggle state is stored in localStorage and synced globally via Zustand store
- **Documentation Refresh:** Updated README, ARCHITECTURE, FEATURES, AGENTS.md, and API_REFERENCE for v3.6.2 with accurate provider counts (100+), new executor list, and system API documentation
- **Uninstall Guide:** Created comprehensive `docs/UNINSTALL.md` covering clean uninstallation for all deployment methods (npm, Docker, Electron, source)
### 🐛 Bug Fixes
- **PDF Attachments:** Unlocked deep string object parsing (`geminiHelper`) ensuring Gemini translation successfully passes complex PDF payloads from OpenAI-compatible streams without dropping them silently (#993)
- **SkillsMP Engine:** Corrected object extraction path mappings inside the API router to fix UI marketplace rendering under Docker/Standalone Node isolated deployments (#988)
---
## [3.6.1] — 2026-04-10
### ✨ New Features
- **OAuth Env Repair Action:** Added a "Repair env" button to the OAuth Providers dashboard that detects and restores missing OAuth client IDs from `.env.example` — with timestamped backup and append-only safety. Includes full 33-language i18n support and sanitized API responses (#1116, by @yart)
### 🐛 Bug Fixes
- **i18n: Missing Provider Keys:** Added missing `filterModels`, `modelsActive`, `showModel`, `hideModel` keys across all 32 locale files, fixing runtime `MISSING_MESSAGE` errors in the providers UI. Also cleaned up duplicate keys in `en.json` (#1111, by @rilham97)
- **GPT-5.4 Routing:** Added missing `targetFormat: "openai-responses"` to `gpt-5.4` and `gpt-5.4-mini` models in both the Codex and GitHub Copilot providers, fixing `[400]: model not accessible via /chat/completions` errors (#1114, by @ask33r)
---
## [3.6.0] — 2026-04-10
### ✨ New Features & Analytics
- **Combo Smoke Test:** Raised the default token budget to 2048 to prevent truncation of thinking models during preflight checks, and fully randomized the arithmetic probe prompt to bypass deterministic caching from upstream relays (#1105)
### 🐛 Bug Fixes & Compliance
- **DB Bloat / Row Limits:** Added `CALL_LOGS_TABLE_MAX_ROWS` and `PROXY_LOGS_TABLE_MAX_ROWS` (default: 100,000) to the backend DB compliance cleaner to prevent runaway SQLite growth. Limits are enforced automatically on the TTL cycle (#1104, fixes #1101)
- **HTML Error Handling:** The router now correctly identifies unexpected HTML responses (e.g. `<!DOCTYPE html>`) sent by upstream providers (like Azure/Copilot) instead of throwing obscure `Unexpected token '<'` JSON parse errors, bubbling up a clean 502 Bad Gateway (#1104, fixes #1066)
- **Android/Termux SQLite Native Support:** `better-sqlite3` is now correctly built from source with cross-compilation flags in ARM64 local Termux deployments without failing on missing prebuilt binaries (#1107)
---
## [3.5.9] — 2026-04-09
### ✨ New Features
- **Persistent Combo Ordering:** Drag combo cards by handle to reorder them in the dashboard; order is persisted to SQLite via a new `sort_order` column and `POST /api/combos/reorder` endpoint. Includes DB migration `020_combo_sort_order.sql` and JSON import preservation (#1095)
- **Sidebar Group Reorder:** Moved "Logs" before "Health" in the System section and "Limits & Quotas" after "Cache" in the Primary section for a more logical navigation flow (#1095)
### 🐛 Bug Fixes
- **Stream Failure Surfacing:** Upstream `response.failed` events (e.g. Codex rate-limit errors) are now properly surfaced as non-200 errors instead of being silently swallowed as empty 200 OK streams. Rate-limit failures return HTTP 429 (#1098, closes #1093)
- **Upstream Model Preservation:** The Responses-to-OpenAI stream translator now preserves the actual upstream model (e.g. `gpt-5.4`) instead of hardcoding a `gpt-4` fallback (#1098, closes #1094)
- **Docker EXDEV Fix:** `build-next-isolated.mjs` now falls back from `fs.rename()` to `cp/rm` when Docker buildx raises `EXDEV` (cross-device link), unblocking the Docker image publish workflow (#1097)
- **macOS CLI Path Resolution:** `cliRuntime.ts` resolves symlink parents with `fs.realpath()` to handle macOS `/var``/private/var` chains, preventing false `symlink_escape` rejections (#1097)
- **Request Log Token Layout:** Split token badges into separate Input (Total In, Cache Read, Cache Write) and Output (Total Out, Reasoning) groups for clearer readability; renamed "Time" label to "Completed Time" (#1096)
---
## [3.5.8] — 2026-04-09
### ✨ New Features & Analytics
- **Analytics Layout Redesign:** Replaced flat metrics with a responsive `CompactStatGrid`, grouping data visually across sections (#1089)
### 🐛 Bug Fixes
- **Build Core:** Force Turbopack cleanup via Prepbulish script to prevent Next.js 16 app/ routing conflicts on runtime.
- **Provider Quarantine:** Introduces model/provider circuit-breakers with adaptive TTL exponential backoff for recurring upstream errors (#1090)
- **Oauth Keep-Alive:** Safely protects authenticated active accounts against spontaneous dropping from router due to transient token refresh failures (#1085)
### 🔒 Security & Maintenance
- **Dependabot:** bumped axios from 1.14.0 to 1.15.0 addressing SSRF flags (#1088)
---
## [3.5.7] — 2026-04-09
### 🐛 Bug Fixes & Security
+49 -30
View File
@@ -2,7 +2,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -255,7 +255,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -341,7 +341,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -486,6 +486,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -774,6 +775,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
@@ -1057,7 +1069,7 @@ volumes:
| Image | Tag | Size | Description |
| ------------------------ | -------- | ------ | --------------------- |
| `diegosouzapw/omniroute` | `latest` | ~250MB | Latest stable release |
| `diegosouzapw/omniroute` | `1.0.3` | ~250MB | Current version |
| `diegosouzapw/omniroute` | `3.6.2` | ~250MB | Current version |
---
@@ -1304,17 +1316,22 @@ Then in `/dashboard/media` → **Transcription** tab: upload any audio or video
## 💡 Key Features
OmniRoute v3.5 is built as an operational platform, not just a relay proxy.
OmniRoute v3.6 is built as an operational platform, not just a relay proxy.
### 🆕 New — v3.5.5 Highlights (Apr 2026)
### 🆕 New — v3.6.x Highlights (Apr 2026)
| Feature | What It Does |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation |
| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs |
| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions |
| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection |
| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts |
| Feature | What It Does |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| 🗑️ **Uninstall / Full Uninstall** | `npm run uninstall` keeps data, `npm run uninstall:full` removes everything — clean removal scripts for all install methods |
| 🔧 **OAuth Env Repair** | One-click "Repair env" action for OAuth providers restores missing environment variables and fixes broken auth state |
| 🔒 **Graceful Electron Shutdown** | Electron `before-quit` now shuts down Next.js gracefully, preventing SQLite WAL database locks on desktop app close |
| 👁️ **Model Visibility Toggle** | Per-model visibility toggle (👁 icon) with search filter and active-count badge (`N/M active`) on provider pages |
| 📧 **Email Privacy Masking** | OAuth account emails masked in provider dashboard (`di*****@g****.com`), full address visible on hover |
| 🔗 **Context Relay Strategy** | Combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation |
| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs |
| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions |
| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection |
| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts |
### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026)
@@ -2172,7 +2189,7 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
- **Runtime**: Node.js 1822 LTS (⚠️ Node.js 24+ is **not supported**`better-sqlite3` native binaries are incompatible)
- **Language**: TypeScript 5.9 — **100% TypeScript** across `src/` and `open-sse/` (zero `any` in core modules since v2.0)
- **Framework**: Next.js 16 + React 19 + Tailwind CSS 4
- **Database**: LowDB (JSON) + SQLite (domain state + proxy logs + MCP audit + routing decisions)
- **Database**: better-sqlite3 (SQLite) + LowDB (JSON legacy) — domain state, proxy logs, MCP audit, routing decisions, memory, skills
- **Schemas**: Zod (MCP tool I/O validation, API contracts)
- **Protocols**: MCP (stdio/HTTP) + A2A v0.3 (JSON-RPC 2.0 + SSE)
- **Streaming**: Server-Sent Events (SSE)
@@ -2190,22 +2207,24 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
## 📖 Documentation
| Document | Description |
| ----------------------------------------------- | --------------------------------------------------- |
| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment |
| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples |
| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients |
| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt |
| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing |
| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation |
| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions |
| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals |
| [Contributing](CONTRIBUTING.md) | Development setup and guidelines |
| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification |
| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices |
| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup |
| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots |
| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps |
| Document | Description |
| -------------------------------------------------------- | --------------------------------------------------- |
| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment |
| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples |
| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients |
| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt |
| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing |
| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation |
| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions |
| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals |
| [Codebase Documentation](docs/CODEBASE_DOCUMENTATION.md) | Beginner-friendly codebase walkthrough |
| [Uninstall Guide](docs/UNINSTALL.md) | Clean removal for all install methods |
| [Contributing](CONTRIBUTING.md) | Development setup and guidelines |
| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification |
| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices |
| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup |
| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots |
| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps |
---
+3 -5
View File
@@ -28,7 +28,7 @@ x-common: &common
- API_PORT=${API_PORT:-20129}
- API_HOST=${API_HOST:-0.0.0.0}
volumes:
- omniroute-data:/app/data
- ./data:/app/data
healthcheck:
test: ["CMD", "node", "healthcheck.mjs"]
interval: 30s
@@ -63,7 +63,7 @@ services:
- "${DASHBOARD_PORT:-${PORT:-20128}}:${DASHBOARD_PORT:-${PORT:-20128}}"
- "${API_PORT:-20129}:${API_PORT:-20129}"
volumes:
- omniroute-data:/app/data
- ./data:/app/data
- /var/run/docker.sock:/var/run/docker.sock
- /usr/libexec/docker/cli-plugins:/usr/libexec/docker/cli-plugins:ro
- ${AUTO_UPDATE_HOST_REPO_DIR:-.}:/workspace/omniroute:rw
@@ -96,7 +96,7 @@ services:
# - CLI_CLINE_BIN=cline
# - CLI_CONTINUE_BIN=cn
volumes:
- omniroute-data:/app/data
- ./data:/app/data
# ── Host binary mounts (read-only) ──
# Adjust paths below to match YOUR host system.
- ~/.local/bin:/host-local/bin:ro
@@ -135,7 +135,5 @@ services:
- cliproxyapi
volumes:
omniroute-data:
name: omniroute-data
cliproxyapi-data:
name: cliproxyapi-data
+29 -6
View File
@@ -320,15 +320,38 @@ These endpoints mirror Gemini's API format for clients that expect native Gemini
### Internal / System APIs
| Endpoint | Method | Description |
| --------------- | ------ | ---------------------------------------------------- |
| `/api/init` | GET | Application initialization check (used on first run) |
| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
| `/api/restart` | POST | Trigger graceful server restart |
| `/api/shutdown` | POST | Trigger graceful server shutdown |
| Endpoint | Method | Description |
| ------------------------ | ------ | ---------------------------------------------------- |
| `/api/init` | GET | Application initialization check (used on first run) |
| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
| `/api/restart` | POST | Trigger graceful server restart |
| `/api/shutdown` | POST | Trigger graceful server shutdown |
| `/api/system/env/repair` | POST | Repair OAuth provider environment variables |
| `/api/system-info` | GET | Generate system diagnostics report |
> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
### OAuth Environment Repair _(v3.6.1+)_
```bash
POST /api/system/env/repair
Content-Type: application/json
{
"provider": "claude-code"
}
```
Repairs missing or corrupted OAuth environment variables for a specific provider. Returns:
```json
{
"success": true,
"repaired": ["CLAUDE_CODE_OAUTH_CLIENT_ID", "CLAUDE_CODE_OAUTH_CLIENT_SECRET"],
"backupPath": "/home/user/.omniroute/backups/env-repair-2026-04-11.bak"
}
```
---
## Audio Transcription
+55 -18
View File
@@ -2,7 +2,7 @@
🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) | 🇨🇿 [Čeština](i18n/cs/ARCHITECTURE.md)
_Last updated: 2026-03-28_
_Last updated: 2026-04-11_
## Executive Summary
@@ -11,18 +11,25 @@ It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic acr
Core capabilities:
- OpenAI-compatible API surface for CLI/tools (28 providers)
- OpenAI-compatible API surface for CLI/tools (100+ providers, 16 executors)
- Request/response translation across provider formats
- Model combo fallback (multi-model sequence)
- Account-level fallback (multi-account per provider)
- OAuth + API-key provider connection management
- OAuth + API-key provider connection management (13 OAuth modules)
- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
- Image generation via `/v1/images/generations` (4 providers, 9 models)
- Image generation via `/v1/images/generations` (10+ providers, 20+ models)
- Audio transcription via `/v1/audio/transcriptions` (7 providers)
- Text-to-speech via `/v1/audio/speech` (10 providers)
- Video generation via `/v1/videos/generations` (ComfyUI + SD WebUI)
- Music generation via `/v1/music/generations` (ComfyUI)
- Web search via `/v1/search` (5 providers)
- Moderations via `/v1/moderations`
- Reranking via `/v1/rerank`
- Think tag parsing (`<think>...</think>`) for reasoning models
- Response sanitization for strict OpenAI SDK compatibility
- Role normalization (developer→system, system→user) for cross-provider compatibility
- Structured output conversion (json_schema → Gemini responseSchema)
- Local persistence for providers, keys, aliases, combos, settings, pricing
- Local persistence for providers, keys, aliases, combos, settings, pricing (26 DB modules)
- Usage/cost tracking and request logging
- Optional cloud sync for multi-device/state sync
- IP allowlist/blocklist for API access control
@@ -42,7 +49,16 @@ Core capabilities:
- Compliance audit logging with opt-out per API key
- Eval framework for LLM quality assurance
- Resilience UI dashboard with real-time circuit breaker status
- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
- MCP Server (25 tools) with 3 transports (stdio/SSE/Streamable HTTP)
- A2A Server (JSON-RPC 2.0 + SSE) with skills and task lifecycle
- Memory system (extraction, injection, retrieval, summarization)
- Skills system (registry, executor, sandbox, built-in skills)
- MITM proxy with certificate management and DNS handling
- Prompt injection guard middleware
- ACP (Agent Communication Protocol) registry
- Modular OAuth providers (13 individual modules under `src/lib/oauth/providers/`)
- Uninstall/full-uninstall scripts
- OAuth environment repair action
Primary runtime model:
@@ -73,7 +89,7 @@ Main pages under `src/app/(dashboard)/dashboard/`:
- `/dashboard` — quick start + provider overview
- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
- `/dashboard/providers` — provider connections and credentials
- `/dashboard/combos` — combo strategies, templates, model routing rules
- `/dashboard/combos` — combo strategies, templates, model routing rules, manual persisted ordering
- `/dashboard/costs` — cost aggregation and pricing visibility
- `/dashboard/analytics` — usage analytics and evaluations
- `/dashboard/limits` — quota/rate controls
@@ -240,7 +256,7 @@ Domain layer modules:
- Eval runner: `src/lib/domain/evalRunner.ts`
- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
OAuth provider modules (13 individual files under `src/lib/oauth/providers/`):
- Registry index: `src/lib/oauth/providers/index.ts`
- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
@@ -615,15 +631,22 @@ flowchart LR
Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
| Executor | Provider(s) | Special Handling |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
| Executor | Provider(s) | Special Handling |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA, etc. | Dynamic URL/header config per provider |
| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
| `CliProxyApiExecutor` | CLIProxyAPI-compatible providers | Custom auth and protocol handling |
| `CloudflareAiExecutor` | Cloudflare Workers AI | Account ID injection, Neurons-based usage tracking |
| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
| `OpenCodeExecutor` | OpenCode | AI SDK compatible provider setup |
| `PollinationsExecutor` | Pollinations AI | No API key required, rate-limited requests |
| `PuterExecutor` | Puter | Browser-based provider integration |
| `QoderExecutor` | Qoder AI | PAT and OAuth support, multi-model free tier |
| `VertexExecutor` | Google Vertex AI | Service account auth, region-based endpoints |
All other providers (including custom compatible nodes) use the `DefaultExecutor`.
@@ -641,7 +664,10 @@ All other providers (including custom compatible nodes) use the `DefaultExecutor
| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
| Qoder | openai | OAuth / PAT | ✅ | ✅ | ✅ | ⚠️ Per request |
| Kilo Code | openai | OAuth | ✅ | ✅ | ✅ | ❌ |
| Cline | openai | OAuth | ✅ | ✅ | ✅ | ❌ |
| Kimi Coding | openai | OAuth | ✅ | ✅ | ✅ | ❌ |
| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
@@ -654,6 +680,17 @@ All other providers (including custom compatible nodes) use the `DefaultExecutor
| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
| Cloudflare AI | openai | API Token + Acct ID | ✅ | ✅ | ❌ | ❌ |
| Pollinations | openai | None (no key) | ✅ | ✅ | ❌ | ❌ |
| Scaleway AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
| LongCat | openai | API Key | ✅ | ✅ | ❌ | ❌ |
| Ollama Cloud | openai | API Key (optional) | ✅ | ✅ | ❌ | ❌ |
| HuggingFace | openai | API Key | ✅ | ✅ | ❌ | ❌ |
| Nebius | openai | API Key | ✅ | ✅ | ❌ | ❌ |
| SiliconFlow | openai | API Key | ✅ | ✅ | ❌ | ❌ |
| Hyperbolic | openai | API Key | ✅ | ✅ | ❌ | ❌ |
| Vertex AI | gemini | Service Account | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
| Puter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
## Format Translation Coverage
+39
View File
@@ -97,6 +97,7 @@ Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in a
A combo strategy that preserves session continuity when account rotation happens mid-conversation. Before the active account is exhausted, OmniRoute generates a structured handoff summary in the background. After the next request resolves to a different account, the summary is injected as a system message so the new account continues with full context.
Configurable via combo-level or global settings:
- **Handoff Threshold** — Quota usage percentage that triggers summary generation (default 85%)
- **Max Messages For Summary** — How much recent history to condense
- **Summary Model** — Optional override model for generating the handoff summary
@@ -116,6 +117,43 @@ Comprehensive proxy configuration enforcement across the entire request pipeline
---
## 📧 Email Privacy Masking _(v3.5.6+)_
OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots or recording demos. The full email address remains accessible via hover tooltip (`title` attribute).
---
## 👁️ Model Visibility Toggle _(v3.5.6+)_
The provider page model list now includes:
- **Real-time search/filter bar** — Quickly find specific models
- **Per-model visibility toggle** (👁 icon) — Hidden models are grayed out and excluded from the `/v1/models` catalog
- **Active-count badge** (`N/M active`) — Shows at a glance how many models are enabled vs total
---
## 🔧 OAuth Env Repair _(v3.6.1+)_
One-click "Repair env" action for OAuth providers that restores missing environment variables and fixes broken auth state. Accessible from `Dashboard → Providers → [OAuth Provider] → Repair env`. Automatically detects and repairs:
- Missing OAuth client credentials
- Corrupted env file entries
- Backup path sanitization
---
## 🗑️ Uninstall / Full Uninstall _(v3.6.2+)_
Clean removal scripts for all installation methods:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
---
## 🖼️ Media _(v2.0.3+)_
Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
@@ -163,5 +201,6 @@ Key features:
- Auto-update on restart
- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
- **Graceful shutdown** — Electron `before-quit` shuts down Next.js cleanly, preventing SQLite WAL database locks (v3.6.2+)
📖 See [`electron/README.md`](../electron/README.md) for full documentation.
+27
View File
@@ -16,6 +16,7 @@ Common problems and solutions for OmniRoute.
| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below |
| `dlopen` / `slice is not valid mach-o file` (macOS) | Run `cd $(npm root -g)/omniroute/app && npm rebuild better-sqlite3 && omniroute` — see [macOS native module rebuild](#macos-native-module-rebuild) below |
| Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below |
---
@@ -47,6 +48,32 @@ Common problems and solutions for OmniRoute.
> **Supported versions:** Node.js 18, 20, or 22 LTS. Node.js 24+ is **not supported**.
### macOS: `dlopen` / "slice is not valid mach-o file"
<a name="macos-native-module-rebuild"></a>
**Cause:** After a global `npm install -g omniroute`, the `better-sqlite3` native binary inside the package may have been compiled for a different architecture or Node.js ABI than what is running locally. This is common on macOS (both Apple Silicon and Intel) when the pre-built binary does not match your environment.
**Symptoms:**
- Server fails immediately on startup with a `dlopen` error
- Error contains `slice is not valid mach-o file`
- Full example:
```
dlopen(/Users/<user>/.nvm/versions/node/v24.13.1/lib/node_modules/omniroute/app/node_modules/better-sqlite3/build/Release/better_sqlite3.node, 0x0001): tried: '...' (slice is not valid mach-o file)
```
**Fix — rebuild for your local environment (no Node.js downgrade required):**
```bash
cd $(npm root -g)/omniroute/app
npm rebuild better-sqlite3
omniroute
```
> **Note:** This recompiles the native binding against your local Node.js version and CPU architecture, resolving the binary mismatch. The officially supported range remains **Node.js 18, 20, or 22 LTS** (`engines` field in `package.json`). If you are on Node.js 24, the rebuild may silence this specific startup error but other issues can still occur — downgrading to Node.js 22 LTS remains the recommended path.
---
## Proxy Issues
+13
View File
@@ -221,6 +221,8 @@ Models: kr/claude-sonnet-4.5, kr/claude-haiku-4.5
## 🎨 Combos
You can reorder combo cards directly in **Dashboard → Combos** by dragging the handle on each card. The order is stored in SQLite and restored on reload.
### Example 1: Maximize Subscription → Cheap Backup
```
@@ -337,6 +339,17 @@ omniroute --port 3000
The CLI automatically loads `.env` from `~/.omniroute/.env` or `./.env`.
### Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| --- | --- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### VPS Deployment
```bash
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
+15
View File
@@ -4,6 +4,8 @@
---
Complete guide for configuring providers, creating combos, integrating CLI tools, and deploying OmniRoute.
---
@@ -223,6 +225,8 @@ Models: kr/claude-sonnet-4.5, kr/claude-haiku-4.5
## 🎨 Combos
You can reorder combo cards directly in **Dashboard → Combos** by dragging the handle on each card. The order is stored in SQLite and restored on reload.
### Example 1: Maximize Subscription → Cheap Backup
```
@@ -339,6 +343,17 @@ omniroute --port 3000
The CLI automatically loads `.env` from `~/.omniroute/.env` or `./.env`.
### Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| --- | --- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### VPS Deployment
```bash
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
+30 -3
View File
@@ -17,8 +17,9 @@ Common problems and solutions for OmniRoute.
| No logs written to disk | Set `APP_LOG_TO_FILE=true` and verify call log capture is enabled |
| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below |
| Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below |
| Login crash / tela em branco | Pode ser Node.js 24+ — veja [Compatibilidade com Node.js](#nodejs-compatibility) abaixo |
| `dlopen` / `slice is not valid mach-o file` (macOS) | Execute `cd $(npm root -g)/omniroute/app && npm rebuild better-sqlite3 && omniroute` — veja [Rebuild nativo no macOS](#macos-native-module-rebuild) abaixo |
| Proxy "fetch failed" | Verifique se o proxy está configurado no nível correto — veja [Problemas de Proxy](#proxy-issues) abaixo |
---
@@ -47,7 +48,33 @@ Common problems and solutions for OmniRoute.
3. Reinstall OmniRoute: `npm install -g omniroute`
4. Restart: `omniroute`
> **Supported versions:** Node.js 18, 20, or 22 LTS. Node.js 24+ is **not supported**.
> **Versões suportadas:** Node.js 18, 20 ou 22 LTS. Node.js 24+ **não é suportado**.
### macOS: `dlopen` / "slice is not valid mach-o file"
<a name="macos-native-module-rebuild"></a>
**Causa:** Após `npm install -g omniroute`, o binário nativo do `better-sqlite3` incluído no pacote pode ter sido compilado para uma arquitetura ou versão ABI do Node.js diferente da que está sendo usada localmente. Isso é comum no macOS (Apple Silicon e Intel) quando o binário pré-compilado não corresponde ao ambiente.
**Sintomas:**
- O servidor falha imediatamente ao iniciar com um erro `dlopen`
- A mensagem contém `slice is not valid mach-o file`
- Exemplo completo:
```
dlopen(/Users/<usuario>/.nvm/versions/node/v24.13.1/lib/node_modules/omniroute/app/node_modules/better-sqlite3/build/Release/better_sqlite3.node, 0x0001): tried: '...' (slice is not valid mach-o file)
```
**Solução — recompilar para o ambiente local (sem precisar fazer downgrade do Node.js):**
```bash
cd $(npm root -g)/omniroute/app
npm rebuild better-sqlite3
omniroute
```
> **Nota:** Isso recompila o binding nativo para a versão e arquitetura local do Node.js, resolvendo o erro de incompatibilidade de binário. O intervalo oficialmente suportado continua sendo **Node.js 18, 20 ou 22 LTS** (campo `engines` no `package.json`). Se você estiver no Node.js 24, o rebuild pode silenciar este erro específico de inicialização, mas outros problemas ainda podem ocorrer — fazer downgrade para o Node.js 22 LTS continua sendo o caminho recomendado.
---
+15
View File
@@ -4,6 +4,8 @@
---
Complete guide for configuring providers, creating combos, integrating CLI tools, and deploying OmniRoute.
---
@@ -223,6 +225,8 @@ Models: kr/claude-sonnet-4.5, kr/claude-haiku-4.5
## 🎨 Combos
You can reorder combo cards directly in **Dashboard → Combos** by dragging the handle on each card. The order is stored in SQLite and restored on reload.
### Example 1: Maximize Subscription → Cheap Backup
```
@@ -339,6 +343,17 @@ omniroute --port 3000
The CLI automatically loads `.env` from `~/.omniroute/.env` or `./.env`.
### Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| --- | --- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### VPS Deployment
```bash
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+15 -3
View File
@@ -6,7 +6,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
_Your universal API proxy — one endpoint, 100+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -259,7 +259,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 100+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer``system` for non-OpenAI providers; `system``user` for GLM/ERNIE
@@ -345,7 +345,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 100+ providers
</details>
@@ -490,6 +490,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router**`provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Manual Combo Ordering** — Drag combo cards by handle and persist the order in SQLite
- **Provider Toggle** — Enable/disable all connections for a provider with one click
- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
@@ -778,6 +779,17 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
### 2) Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
### Long-Running Streaming Timeouts
For most deployments, you only need:
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,7 +1,7 @@
openapi: 3.1.0
info:
title: OmniRoute API
version: 3.5.6
version: 3.6.2
description: |
OmniRoute is a local-first AI API proxy router. It provides an OpenAI-compatible
endpoint that routes requests to multiple AI providers with load balancing,
+21 -19
View File
@@ -61,26 +61,14 @@ let mainWindow = null;
let tray = null;
let nextServer = null;
let serverPort = 20128;
let isServerStopped = false;
const getServerUrl = () => `http://localhost:${serverPort}`;
function resolveNodeExecutable(env = process.env) {
const candidates = [
env.OMNIROUTE_NODE_PATH,
"/usr/local/bin/node",
"/opt/homebrew/bin/node",
"/opt/local/bin/node",
].filter(Boolean);
for (const candidate of candidates) {
try {
if (fs.existsSync(candidate)) return candidate;
} catch {
/* continue */
}
}
return "node";
// #1081: Ensure Next.js standalone runs using Electron's Node runtime
// instead of a randomly found system Node to prevent ABI architecture mismatches.
return process.execPath;
}
function resolveDataDir(overridePath, env = process.env) {
@@ -549,6 +537,8 @@ function startNextServer() {
DATA_DIR: dataDir,
PORT: String(serverPort),
NODE_ENV: "production",
ELECTRON_RUN_AS_NODE: "1",
NODE_PATH: path.join(process.resourcesPath, "app.asar.unpacked", "node_modules"),
},
stdio: "pipe",
});
@@ -703,9 +693,21 @@ app.on("window-all-closed", () => {
});
// Clean up before quit
app.on("before-quit", () => {
app.isQuitting = true;
stopNextServer();
app.on("before-quit", async (event) => {
if (nextServer && !isServerStopped) {
event.preventDefault(); // Stop immediate quit
app.isQuitting = true;
// Stop server and wait up to 5s for graceful WAL checkpoint
const serverToStop = nextServer;
stopNextServer();
await waitForServerExit(serverToStop, 5000);
isServerStopped = true;
app.quit(); // Resume quit safely
} else {
app.isQuitting = true;
}
});
// Global error handlers
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "omniroute-desktop",
"version": "3.5.7",
"version": "3.6.2",
"description": "OmniRoute Desktop Application",
"main": "main.js",
"author": {
@@ -22,6 +22,7 @@
"pack": "npm run prepare:bundle && electron-builder --dir"
},
"dependencies": {
"better-sqlite3": "^12.8.0",
"electron-updater": "^6.8.3"
},
"devDependencies": {
+2 -2
View File
@@ -8,7 +8,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
**Key value:** One endpoint (`http://localhost:20128/v1`), unlimited models, zero downtime, minimal cost.
**Current version:** 3.5.6
**Current version:** 3.6.0
## Tech Stack
@@ -279,7 +279,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
└── .env.example # Environment variable template
```
## Key Features (v3.5.6)
## Key Features (v3.6.0)
### Core Proxy
- **60+ AI providers** with automatic format translation
+450 -2
View File
@@ -102,6 +102,102 @@ const KIMI_CODING_SHARED = {
] as RegistryModel[],
} as const;
const buildModels = (ids: readonly string[]): RegistryModel[] =>
ids.map((id) => ({ id, name: id }));
const CHAT_OPENAI_COMPAT_MODELS: Record<string, RegistryModel[]> = {
deepinfra: buildModels([
"Qwen/Qwen3-Coder-480B-A35B-Instruct",
"deepseek-ai/DeepSeek-R1",
"meta-llama/Llama-3.3-70B-Instruct",
"anthropic/claude-4-sonnet",
]),
"vercel-ai-gateway": buildModels([
"openai/gpt-4.1",
"anthropic/claude-4-sonnet",
"google/gemini-2.5-pro",
"moonshotai/kimi-k2",
"vercel/v0-1.5-md",
]),
"lambda-ai": buildModels([
"deepseek-r1-671b",
"llama3.3-70b-instruct-fp8",
"qwen25-coder-32b-instruct",
]),
sambanova: buildModels([
"DeepSeek-V3.1",
"Llama-4-Maverick-17B-128E-Instruct",
"Qwen3-32B",
"gpt-oss-120b",
]),
nscale: buildModels([
"Qwen/QwQ-32B",
"deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
"meta-llama/Llama-3.3-70B-Instruct",
]),
ovhcloud: buildModels([
"Meta-Llama-3_3-70B-Instruct",
"Qwen2.5-Coder-32B-Instruct",
"Mistral-Small-3.2-24B-Instruct-2506",
]),
baseten: buildModels(["moonshotai/Kimi-K2.5", "zai-org/GLM-5", "deepseek-ai/DeepSeek-V3.1"]),
publicai: buildModels([
"swiss-ai/apertus-70b-instruct",
"aisingapore/Qwen-SEA-LION-v4-32B-IT",
"allenai/Olmo-3-32B-Think",
]),
moonshot: buildModels(["kimi-k2.5", "kimi-latest", "moonshot-v1-auto"]),
"meta-llama": buildModels([
"Llama-3.3-70B-Instruct",
"Llama-4-Maverick-17B-128E-Instruct-FP8",
"Llama-4-Scout-17B-16E-Instruct-FP8",
]),
"v0-vercel": buildModels(["v0-1.0-md", "v0-1.5-lg", "v0-1.5-md"]),
morph: buildModels(["morph-v3-fast", "morph-v3-large"]),
"featherless-ai": buildModels(["featherless-ai/Qwerky-72B", "featherless-ai/Qwerky-QwQ-32B"]),
friendliai: buildModels(["meta-llama-3.1-70b-instruct", "meta-llama-3.1-8b-instruct"]),
llamagate: buildModels(["qwen2.5-coder-7b", "deepseek-coder-6.7b", "qwen3-vl-8b"]),
heroku: buildModels(["claude-3-5-sonnet-latest", "claude-4-sonnet"]),
galadriel: buildModels(["galadriel-latest"]),
databricks: buildModels([
"databricks-gpt-5",
"databricks-meta-llama-3-3-70b-instruct",
"databricks-claude-sonnet-4",
"databricks-gemini-2-5-pro",
]),
snowflake: buildModels(["llama3.1-70b", "llama3.3-70b", "deepseek-r1", "claude-3-5-sonnet"]),
wandb: buildModels([
"openai/gpt-oss-120b",
"Qwen/Qwen3-Coder-480B-A35B-Instruct",
"deepseek-ai/DeepSeek-V3.1",
]),
volcengine: buildModels([
"deepseek-v3-2-251201",
"doubao-seed-2-0-code-preview-260215",
"kimi-k2-thinking-251104",
"glm-4-7-251222",
]),
ai21: buildModels(["jamba-large-1.7", "jamba-mini-1.7", "jamba-1.5-large"]),
gigachat: buildModels(["GigaChat-2-Max", "GigaChat-2-Pro", "GigaChat-2-Lite"]),
venice: buildModels(["venice-latest"]),
codestral: buildModels(["codestral-2405", "codestral-latest"]),
upstage: buildModels(["solar-pro", "solar-mini", "solar-docvision", "solar-embedding-1-large"]),
maritalk: buildModels(["sabia-3", "sabia-3-small"]),
"xiaomi-mimo": buildModels(["MiMo-7B-RL", "MiMo-7B-SFT"]),
"inference-net": buildModels([
"meta-llama/Llama-3.3-70B-Instruct",
"deepseek-ai/DeepSeek-R1",
"Qwen/Qwen2.5-72B-Instruct",
]),
nanogpt: buildModels(["chatgpt-4o-latest", "claude-3.5-sonnet", "gpt-4o-mini"]),
predibase: buildModels(["llama-3.3-70b"]),
bytez: buildModels([
"meta-llama/Llama-3.3-70B-Instruct",
"mistralai/Mistral-7B-Instruct-v0.3",
"Qwen/Qwen2.5-72B-Instruct",
]),
};
function mapStainlessOs() {
switch (platform()) {
case "darwin":
@@ -250,8 +346,8 @@ export const REGISTRY: Record<string, RegistryEntry> = {
tokenUrl: "https://auth.openai.com/oauth/token",
},
models: [
{ id: "gpt-5.4", name: "GPT 5.4" },
{ id: "gpt-5.4-mini", name: "GPT 5.4 Mini" },
{ id: "gpt-5.4", name: "GPT 5.4", targetFormat: "openai-responses" },
{ id: "gpt-5.4-mini", name: "GPT 5.4 Mini", targetFormat: "openai-responses" },
{ id: "gpt-5.3-codex", name: "GPT 5.3 Codex" },
{ id: "gpt-5.3-codex-xhigh", name: "GPT 5.3 Codex (xHigh)" },
{ id: "gpt-5.3-codex-high", name: "GPT 5.3 Codex (High)" },
@@ -1404,6 +1500,358 @@ export const REGISTRY: Record<string, RegistryEntry> = {
],
},
deepinfra: {
id: "deepinfra",
alias: "deepinfra",
format: "openai",
executor: "default",
baseUrl: "https://api.deepinfra.com/v1/openai/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.deepinfra,
},
"vercel-ai-gateway": {
id: "vercel-ai-gateway",
alias: "vag",
format: "openai",
executor: "default",
baseUrl: "https://ai-gateway.vercel.sh/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS["vercel-ai-gateway"],
},
"lambda-ai": {
id: "lambda-ai",
alias: "lambda",
format: "openai",
executor: "default",
baseUrl: "https://api.lambda.ai/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS["lambda-ai"],
},
sambanova: {
id: "sambanova",
alias: "samba",
format: "openai",
executor: "default",
baseUrl: "https://api.sambanova.ai/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.sambanova,
},
nscale: {
id: "nscale",
alias: "nscale",
format: "openai",
executor: "default",
baseUrl: "https://inference.api.nscale.com/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.nscale,
},
ovhcloud: {
id: "ovhcloud",
alias: "ovh",
format: "openai",
executor: "default",
baseUrl: "https://oai.endpoints.kepler.ai.cloud.ovh.net/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.ovhcloud,
},
baseten: {
id: "baseten",
alias: "baseten",
format: "openai",
executor: "default",
baseUrl: "https://inference.baseten.co/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.baseten,
},
publicai: {
id: "publicai",
alias: "publicai",
format: "openai",
executor: "default",
baseUrl: "https://api.publicai.co/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.publicai,
},
moonshot: {
id: "moonshot",
alias: "moonshot",
format: "openai",
executor: "default",
baseUrl: "https://api.moonshot.ai/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.moonshot,
},
"meta-llama": {
id: "meta-llama",
alias: "meta",
format: "openai",
executor: "default",
baseUrl: "https://api.llama.com/compat/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS["meta-llama"],
},
"v0-vercel": {
id: "v0-vercel",
alias: "v0",
format: "openai",
executor: "default",
baseUrl: "https://api.v0.dev/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS["v0-vercel"],
},
morph: {
id: "morph",
alias: "morph",
format: "openai",
executor: "default",
baseUrl: "https://api.morphllm.com/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.morph,
},
"featherless-ai": {
id: "featherless-ai",
alias: "featherless",
format: "openai",
executor: "default",
baseUrl: "https://api.featherless.ai/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS["featherless-ai"],
},
friendliai: {
id: "friendliai",
alias: "friendli",
format: "openai",
executor: "default",
baseUrl: "https://api.friendli.ai/dedicated/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.friendliai,
},
llamagate: {
id: "llamagate",
alias: "llamagate",
format: "openai",
executor: "default",
baseUrl: "https://llamagate.ai/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.llamagate,
},
heroku: {
id: "heroku",
alias: "heroku",
format: "openai",
executor: "default",
baseUrl: "https://us.inference.heroku.com/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.heroku,
},
galadriel: {
id: "galadriel",
alias: "galadriel",
format: "openai",
executor: "default",
baseUrl: "https://api.galadriel.ai/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.galadriel,
},
databricks: {
id: "databricks",
alias: "databricks",
format: "openai",
executor: "default",
baseUrl: "https://adb-0000000000000000.0.azuredatabricks.net/serving-endpoints",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.databricks,
},
snowflake: {
id: "snowflake",
alias: "snowflake",
format: "openai",
executor: "default",
baseUrl: "https://example-account.snowflakecomputing.com/api/v2",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.snowflake,
},
wandb: {
id: "wandb",
alias: "wandb",
format: "openai",
executor: "default",
baseUrl: "https://api.inference.wandb.ai/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.wandb,
},
volcengine: {
id: "volcengine",
alias: "volcengine",
format: "openai",
executor: "default",
baseUrl: "https://ark.cn-beijing.volces.com/api/v3/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.volcengine,
},
ai21: {
id: "ai21",
alias: "ai21",
format: "openai",
executor: "default",
baseUrl: "https://api.ai21.com/studio/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.ai21,
},
gigachat: {
id: "gigachat",
alias: "gigachat",
format: "openai",
executor: "default",
baseUrl: "https://gigachat.devices.sberbank.ru/api/v1",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.gigachat,
},
venice: {
id: "venice",
alias: "venice",
format: "openai",
executor: "default",
baseUrl: "https://api.venice.ai/api/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.venice,
},
codestral: {
id: "codestral",
alias: "codestral",
format: "openai",
executor: "default",
baseUrl: "https://codestral.mistral.ai/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.codestral,
},
upstage: {
id: "upstage",
alias: "upstage",
format: "openai",
executor: "default",
baseUrl: "https://api.upstage.ai/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.upstage,
},
maritalk: {
id: "maritalk",
alias: "maritalk",
format: "openai",
executor: "default",
baseUrl: "https://chat.maritaca.ai/api/chat/inference",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.maritalk,
},
"xiaomi-mimo": {
id: "xiaomi-mimo",
alias: "mimo",
format: "openai",
executor: "default",
baseUrl: "https://api.xiaomi.com/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS["xiaomi-mimo"],
},
"inference-net": {
id: "inference-net",
alias: "inet",
format: "openai",
executor: "default",
baseUrl: "https://api.inference.net/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS["inference-net"],
},
nanogpt: {
id: "nanogpt",
alias: "nanogpt",
format: "openai",
executor: "default",
baseUrl: "https://nano-gpt.com/api/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.nanogpt,
},
predibase: {
id: "predibase",
alias: "predibase",
format: "openai",
executor: "default",
baseUrl: "https://serving.app.predibase.com/v1/chat/completions",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.predibase,
},
bytez: {
id: "bytez",
alias: "bytez",
format: "openai",
executor: "default",
baseUrl: "https://api.bytez.com/models/v2",
authType: "apikey",
authHeader: "bearer",
models: CHAT_OPENAI_COMPAT_MODELS.bytez,
},
aimlapi: {
id: "aimlapi",
alias: "aiml",
+24 -6
View File
@@ -240,8 +240,8 @@ export class BaseExecutor {
return null;
}
needsRefresh(credentials: ProviderCredentials) {
if (!credentials.expiresAt) return false;
needsRefresh(credentials?: ProviderCredentials | null) {
if (!credentials?.expiresAt) return false;
const expiresAtMs = new Date(credentials.expiresAt).getTime();
return expiresAtMs - Date.now() < 5 * 60 * 1000;
}
@@ -263,13 +263,31 @@ export class BaseExecutor {
const fallbackCount = this.getFallbackCount();
let lastError: unknown = null;
let lastStatus = 0;
let activeCredentials = credentials;
// Track per-URL intra-retry attempts to avoid infinite loops
const retryAttemptsByUrl: Record<number, number> = {};
if (this.needsRefresh(credentials)) {
try {
const refreshed = await this.refreshCredentials(credentials, log || null);
if (refreshed) {
activeCredentials = {
...credentials,
...refreshed,
};
}
} catch (error) {
log?.warn?.(
"TOKEN",
`Credential refresh failed for ${this.provider}: ${error instanceof Error ? error.message : String(error)}`
);
}
}
for (let urlIndex = 0; urlIndex < fallbackCount; urlIndex++) {
const url = this.buildUrl(model, stream, urlIndex, credentials);
const headers = this.buildHeaders(credentials, stream);
applyConfiguredUserAgent(headers, credentials?.providerSpecificData);
const url = this.buildUrl(model, stream, urlIndex, activeCredentials);
const headers = this.buildHeaders(activeCredentials, stream);
applyConfiguredUserAgent(headers, activeCredentials?.providerSpecificData);
// Append 1M context beta header when [1m] suffix was used
// Only supported for specific Claude models per Anthropic docs
@@ -293,7 +311,7 @@ export class BaseExecutor {
}
}
const transformedBody = await this.transformRequest(model, body, stream, credentials);
const transformedBody = await this.transformRequest(model, body, stream, activeCredentials);
try {
// Apply timeout to all requests. Non-streaming requests need this to prevent
+87
View File
@@ -7,8 +7,43 @@ import {
CLAUDE_CODE_COMPATIBLE_DEFAULT_CHAT_PATH,
joinClaudeCodeCompatibleUrl,
} from "../services/claudeCodeCompatible.ts";
import { getGigachatAccessToken } from "../services/gigachatAuth.ts";
import { getOpenAICompatibleType, isClaudeCodeCompatible } from "../services/provider.ts";
function normalizeBaseUrl(baseUrl) {
return (baseUrl || "").trim().replace(/\/$/, "");
}
function normalizeBailianMessagesUrl(baseUrl) {
const normalized = normalizeBaseUrl(baseUrl).replace(/\?beta=true$/, "");
const messagesUrl = normalized.endsWith("/messages") ? normalized : `${normalized}/messages`;
return `${messagesUrl}?beta=true`;
}
function normalizeHerokuChatUrl(baseUrl) {
const normalized = normalizeBaseUrl(baseUrl);
if (normalized.endsWith("/v1/chat/completions")) return normalized;
return `${normalized}/v1/chat/completions`;
}
function normalizeDatabricksChatUrl(baseUrl) {
const normalized = normalizeBaseUrl(baseUrl);
if (normalized.endsWith("/chat/completions")) return normalized;
return `${normalized}/chat/completions`;
}
function normalizeSnowflakeChatUrl(baseUrl) {
const normalized = normalizeBaseUrl(baseUrl)
.replace(/\/cortex\/inference:complete$/, "")
.replace(/\/api\/v2$/, "");
return `${normalized}/api/v2/cortex/inference:complete`;
}
function normalizeGigachatChatUrl(baseUrl) {
const normalized = normalizeBaseUrl(baseUrl).replace(/\/chat\/completions$/, "");
return `${normalized}/chat/completions`;
}
export class DefaultExecutor extends BaseExecutor {
constructor(provider) {
super(provider, PROVIDERS[provider] || PROVIDERS.openai);
@@ -44,6 +79,26 @@ export class DefaultExecutor extends BaseExecutor {
return `${normalized}${customPath || "/messages"}`;
}
switch (this.provider) {
case "bailian-coding-plan": {
const baseUrl = credentials?.providerSpecificData?.baseUrl || this.config.baseUrl;
return normalizeBailianMessagesUrl(baseUrl);
}
case "heroku": {
const baseUrl = credentials?.providerSpecificData?.baseUrl || this.config.baseUrl;
return normalizeHerokuChatUrl(baseUrl);
}
case "databricks": {
const baseUrl = credentials?.providerSpecificData?.baseUrl || this.config.baseUrl;
return normalizeDatabricksChatUrl(baseUrl);
}
case "snowflake": {
const baseUrl = credentials?.providerSpecificData?.baseUrl || this.config.baseUrl;
return normalizeSnowflakeChatUrl(baseUrl);
}
case "gigachat": {
const baseUrl = credentials?.providerSpecificData?.baseUrl || this.config.baseUrl;
return normalizeGigachatChatUrl(baseUrl);
}
case "claude":
case "glm":
case "kimi-coding":
@@ -78,6 +133,19 @@ export class DefaultExecutor extends BaseExecutor {
? (headers["x-goog-api-key"] = effectiveKey)
: (headers["Authorization"] = `Bearer ${credentials.accessToken}`);
break;
case "snowflake": {
const rawToken = effectiveKey || credentials.accessToken || "";
const usesProgrammaticAccessToken = rawToken.startsWith("pat/");
headers["Authorization"] =
`Bearer ${usesProgrammaticAccessToken ? rawToken.slice(4) : rawToken}`;
headers["X-Snowflake-Authorization-Token-Type"] = usesProgrammaticAccessToken
? "PROGRAMMATIC_ACCESS_TOKEN"
: "KEYPAIR_JWT";
break;
}
case "gigachat":
headers["Authorization"] = `Bearer ${credentials.accessToken || effectiveKey}`;
break;
case "claude":
effectiveKey
? (headers["x-api-key"] = effectiveKey)
@@ -144,6 +212,17 @@ export class DefaultExecutor extends BaseExecutor {
* race-condition protection (deduplication via refreshPromiseCache).
*/
async refreshCredentials(credentials, log) {
if (this.provider === "gigachat") {
if (!credentials.apiKey) return null;
try {
return await getGigachatAccessToken({
credentials: credentials.apiKey,
});
} catch (error) {
log?.error?.("TOKEN", `gigachat refresh error: ${error.message}`);
return null;
}
}
if (!credentials.refreshToken) return null;
try {
return await getAccessToken(this.provider, credentials, log);
@@ -152,6 +231,14 @@ export class DefaultExecutor extends BaseExecutor {
return null;
}
}
needsRefresh(credentials) {
if (this.provider === "gigachat") {
if (credentials.apiKey && !credentials.accessToken) return true;
if (!credentials.expiresAt) return false;
}
return super.needsRefresh(credentials);
}
}
export default DefaultExecutor;
+24 -8
View File
@@ -51,12 +51,13 @@ import {
getModelPreserveOpenAIDeveloperRole,
getModelUpstreamExtraHeaders,
getUpstreamProxyConfig,
getCachedSettings,
} from "@/lib/localDb";
import { getExecutor } from "../executors/index.ts";
import { getCacheControlSettings } from "@/lib/cacheControlSettings";
import {
shouldPreserveCacheControl,
providerSupportsCaching,
type CacheControlMode,
} from "../utils/cacheControlPolicy.ts";
import { getCacheMetrics } from "@/lib/db/settings.ts";
@@ -810,9 +811,16 @@ export async function handleChatCore({
}
const stream = resolveStreamFlag(body?.stream, acceptHeader);
const runtimeSettings = await getCachedSettings().catch(() => ({}) as Record<string, unknown>);
const semanticCacheEnabled = runtimeSettings.semanticCacheEnabled !== false;
const cacheControlMode =
runtimeSettings.alwaysPreserveClientCache === "always" ||
runtimeSettings.alwaysPreserveClientCache === "never"
? (runtimeSettings.alwaysPreserveClientCache as CacheControlMode)
: "auto";
// ── Phase 9.1: Semantic cache check (non-streaming, temp=0 only) ──
if (isCacheable(body, clientRawRequest?.headers)) {
if (semanticCacheEnabled && isCacheable(body, clientRawRequest?.headers)) {
const signature = generateSignature(model, body.messages, body.temperature, body.top_p);
const cached = getCachedResponse(signature);
if (cached) {
@@ -948,8 +956,6 @@ export async function handleChatCore({
let ccSessionId: string | null = null;
// Determine if we should preserve client-side cache_control headers
// Fetch settings from DB to get user preference
const cacheControlMode = await getCacheControlSettings().catch(() => "auto" as const);
const preserveCacheControl = shouldPreserveCacheControl({
userAgent,
isCombo,
@@ -2017,21 +2023,31 @@ export async function handleChatCore({
try {
responseBody = rawBody ? JSON.parse(rawBody) : {};
} catch {
const isHtmlResponse =
rawBody && typeof rawBody === "string" && /^\s*(?:\s|<!|<[a-zA-Z]|<\?xml)/.test(rawBody);
appendRequestLog({
model,
provider,
connectionId,
status: `FAILED ${HTTP_STATUS.BAD_GATEWAY}`,
}).catch(() => {});
const invalidJsonMessage = "Invalid JSON response from provider";
const invalidJsonMessage = isHtmlResponse
? "Provider returned HTML error page instead of JSON - check credentials and endpoint"
: "Invalid JSON response from provider";
persistAttemptLogs({
status: HTTP_STATUS.BAD_GATEWAY,
error: invalidJsonMessage,
providerRequest: finalBody || translatedBody,
providerResponse: normalizedProviderPayload,
providerResponse: isHtmlResponse
? { _raw: rawBody?.slice(0, 500) }
: normalizedProviderPayload,
clientResponse: buildErrorBody(HTTP_STATUS.BAD_GATEWAY, invalidJsonMessage),
});
persistFailureUsage(HTTP_STATUS.BAD_GATEWAY, "invalid_json_payload");
persistFailureUsage(
HTTP_STATUS.BAD_GATEWAY,
isHtmlResponse ? "html_error_response" : "invalid_json_payload"
);
return createErrorResult(HTTP_STATUS.BAD_GATEWAY, invalidJsonMessage);
}
}
@@ -2259,7 +2275,7 @@ export async function handleChatCore({
}
// ── Phase 9.1: Cache store (non-streaming, temp=0) ──
if (isCacheable(body, clientRawRequest?.headers)) {
if (semanticCacheEnabled && isCacheable(body, clientRawRequest?.headers)) {
const signature = generateSignature(model, body.messages, body.temperature, body.top_p);
const tokensSaved = usage?.prompt_tokens + usage?.completion_tokens || 0;
setCachedResponse(signature, model, translatedResponse, tokensSaved);
+6 -1
View File
@@ -7,6 +7,7 @@ import { getCorsOrigin } from "../utils/cors.ts";
import { handleChatCore } from "./chatCore.ts";
import { convertResponsesApiFormat } from "../translator/helpers/responsesApiHelper.ts";
import { createResponsesApiTransformStream } from "../transformer/responsesTransformer.ts";
import { createSseHeartbeatTransform } from "../utils/sseHeartbeat.ts";
/**
* Handle /v1/responses request
@@ -19,6 +20,7 @@ import { createResponsesApiTransformStream } from "../transformer/responsesTrans
* @param {function} options.onRequestSuccess - Callback when request succeeds
* @param {function} options.onDisconnect - Callback when client disconnects
* @param {string} options.connectionId - Connection ID for usage tracking
* @param {AbortSignal} [options.signal] - Abort signal for request/disconnect cleanup
* @returns {Promise<{success: boolean, response?: Response, status?: number, error?: string}>}
*/
export async function handleResponsesCore({
@@ -30,6 +32,7 @@ export async function handleResponsesCore({
onRequestSuccess,
onDisconnect,
connectionId,
signal,
}) {
// Convert Responses API format to Chat Completions format
const convertedBody = convertResponsesApiFormat(body);
@@ -66,7 +69,9 @@ export async function handleResponsesCore({
// Transform SSE stream to Responses API format (no logging in worker)
const transformStream = createResponsesApiTransformStream(null);
const transformedBody = response.body.pipeThrough(transformStream);
const transformedBody = response.body
.pipeThrough(transformStream)
.pipeThrough(createSseHeartbeatTransform({ signal }));
return {
success: true,
+7
View File
@@ -884,8 +884,10 @@ export const cacheStatsOutput = z.object({
.object({
totalRequests: z.number(),
requestsWithCacheControl: z.number(),
totalInputTokens: z.number(),
totalCachedTokens: z.number(),
totalCacheCreationTokens: z.number(),
tokensSaved: z.number(),
estimatedCostSaved: z.number(),
})
.nullable(),
@@ -893,6 +895,11 @@ export const cacheStatsOutput = z.object({
activeKeys: z.number(),
windowMs: z.number(),
}),
config: z
.object({
semanticCacheEnabled: z.boolean(),
})
.optional(),
});
export const cacheStatsTool: McpToolDefinition<typeof cacheStatsInput, typeof cacheStatsOutput> = {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@omniroute/open-sse",
"version": "3.5.7",
"version": "3.6.2",
"description": "Express SSE sidecar for OmniRoute — handles streaming, protocol translation, and provider orchestration",
"type": "module",
"main": "index.js",
+113
View File
@@ -0,0 +1,113 @@
import { randomUUID } from "crypto";
type GigachatTokenResult = {
accessToken: string;
expiresAt: string;
};
type GigachatTokenOptions = {
credentials?: string | null;
scope?: string;
authUrl?: string;
signal?: AbortSignal;
};
const DEFAULT_GIGACHAT_AUTH_URL = "https://ngw.devices.sberbank.ru:9443/api/v2/oauth";
const DEFAULT_GIGACHAT_SCOPE = "GIGACHAT_API_PERS";
const CACHE_SKEW_MS = 60_000;
const tokenCache = new Map<string, GigachatTokenResult>();
const inflightRequests = new Map<string, Promise<GigachatTokenResult>>();
function getCacheKey(credentials: string, authUrl: string, scope: string) {
return `${authUrl}::${scope}::${credentials}`;
}
function isFreshToken(token: GigachatTokenResult | undefined) {
if (!token?.accessToken || !token?.expiresAt) return false;
const expiresAtMs = new Date(token.expiresAt).getTime();
return Number.isFinite(expiresAtMs) && expiresAtMs - Date.now() > CACHE_SKEW_MS;
}
function normalizeExpiry(rawExpiry: unknown) {
if (typeof rawExpiry === "number" && Number.isFinite(rawExpiry)) {
return new Date(rawExpiry).toISOString();
}
if (typeof rawExpiry === "string" && rawExpiry.trim().length > 0) {
const numericValue = Number(rawExpiry);
if (Number.isFinite(numericValue)) {
return new Date(numericValue).toISOString();
}
const dateMs = Date.parse(rawExpiry);
if (Number.isFinite(dateMs)) {
return new Date(dateMs).toISOString();
}
}
return new Date(Date.now() + 30 * 60 * 1000).toISOString();
}
export async function getGigachatAccessToken(
options: GigachatTokenOptions = {}
): Promise<GigachatTokenResult> {
const credentials = (options.credentials || "").trim();
if (!credentials) {
throw new Error("Missing GigaChat credentials");
}
const authUrl = (options.authUrl || DEFAULT_GIGACHAT_AUTH_URL).trim();
const scope = (options.scope || DEFAULT_GIGACHAT_SCOPE).trim();
const cacheKey = getCacheKey(credentials, authUrl, scope);
const cached = tokenCache.get(cacheKey);
if (isFreshToken(cached)) {
return cached;
}
const inflight = inflightRequests.get(cacheKey);
if (inflight) {
return inflight;
}
const requestPromise = (async () => {
const response = await fetch(authUrl, {
method: "POST",
headers: {
Authorization: `Basic ${credentials}`,
RqUID: randomUUID(),
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({ scope }).toString(),
signal: options.signal,
});
if (!response.ok) {
const bodyText = await response.text();
throw new Error(`GigaChat token request failed: ${response.status} ${bodyText}`.trim());
}
const data = (await response.json()) as Record<string, unknown>;
const accessToken =
typeof data.tok === "string"
? data.tok
: typeof data.access_token === "string"
? data.access_token
: "";
if (!accessToken) {
throw new Error("GigaChat token response missing access token");
}
const token = {
accessToken,
expiresAt: normalizeExpiry(data.exp ?? data.expires_at),
};
tokenCache.set(cacheKey, token);
return token;
})();
inflightRequests.set(cacheKey, requestPromise);
try {
return await requestPromise;
} finally {
inflightRequests.delete(cacheKey);
}
}
+10 -3
View File
@@ -100,11 +100,18 @@ export function convertOpenAIContentToParts(content) {
}
// 3. Handle raw data strings (e.g. {"type": "file", "data": "JVBER...", "mime_type": "..."})
if (typeof item.data === "string" && !item.data.startsWith("http")) {
const rawData = item.data.replace(/^data:[a-zA-Z0-9/+-]+;base64,/, "");
const rawDataStr = item.data || item.file?.data || item.document?.data;
const mimeTypeFallback =
item.mime_type ||
item.media_type ||
item.file?.mime_type ||
item.document?.mime_type ||
"application/octet-stream";
if (typeof rawDataStr === "string" && !rawDataStr.startsWith("http")) {
const rawData = rawDataStr.replace(/^data:[a-zA-Z0-9/+-]+;base64,/, "");
parts.push({
inlineData: {
mimeType: item.mime_type || item.media_type || "application/octet-stream",
mimeType: mimeTypeFallback,
data: rawData,
},
});
@@ -425,6 +425,31 @@ function flushEvents(state) {
return events;
}
function normalizeUpstreamFailure(data, fallbackType = "server_error") {
const response = data?.response && typeof data.response === "object" ? data.response : null;
const error =
response?.error && typeof response.error === "object"
? response.error
: data?.error && typeof data.error === "object"
? data.error
: null;
const code = typeof error?.code === "string" ? error.code : "";
const message =
typeof error?.message === "string"
? error.message
: typeof data?.message === "string"
? data.message
: "Upstream failure";
return {
status: code === "rate_limit_exceeded" ? 429 : 502,
type: code === "rate_limit_exceeded" ? "rate_limit_error" : fallbackType,
code: code || (fallbackType === "rate_limit_error" ? "rate_limit_exceeded" : "bad_gateway"),
message,
};
}
/**
* Translate OpenAI Responses API chunk to OpenAI Chat Completions format
* This is for when Codex returns data and we need to send it to an OpenAI-compatible client
@@ -456,6 +481,19 @@ export function openaiResponsesToOpenAIResponse(chunk, state) {
const eventType = chunk.type || chunk.event;
const data = chunk.data || chunk;
if (!state.model) {
const upstreamModel =
(data?.response && typeof data.response === "object" && data.response.model) ||
data?.model ||
data?.modelVersion ||
data?.model_version ||
null;
if (typeof upstreamModel === "string" && upstreamModel.trim().length > 0) {
state.model = upstreamModel.trim();
}
}
// Initialize state
if (!state.started) {
state.started = true;
@@ -716,6 +754,12 @@ export function openaiResponsesToOpenAIResponse(chunk, state) {
return null;
}
if (eventType === "response.failed" || eventType === "error") {
state.upstreamError = normalizeUpstreamFailure(data);
state.finishReasonSent = true;
return null;
}
// Reasoning events — emit as reasoning_content in Chat format
if (eventType === "response.reasoning_summary_text.delta") {
const reasoningDelta = data.delta || "";
+51
View File
@@ -0,0 +1,51 @@
const DEFAULT_INTERVAL_MS = 15_000;
type SseHeartbeatTransformOptions = {
intervalMs?: number;
signal?: AbortSignal;
};
export function createSseHeartbeatTransform({
intervalMs = DEFAULT_INTERVAL_MS,
signal,
}: SseHeartbeatTransformOptions = {}) {
let intervalId: ReturnType<typeof setInterval> | undefined;
const encoder = new TextEncoder();
const stop = () => {
if (!intervalId) return;
clearInterval(intervalId);
intervalId = undefined;
};
return new TransformStream<Uint8Array, Uint8Array>({
start(controller) {
intervalId = setInterval(() => {
if (signal?.aborted) {
stop();
return;
}
try {
controller.enqueue(encoder.encode(`: keepalive ${new Date().toISOString()}\n\n`));
} catch {
stop();
}
}, intervalMs);
if (intervalId && typeof intervalId === "object" && "unref" in intervalId) {
intervalId.unref?.();
}
signal?.addEventListener("abort", stop, { once: true });
},
transform(chunk, controller) {
controller.enqueue(chunk);
},
flush() {
stop();
},
});
}
+61 -2
View File
@@ -26,6 +26,7 @@ import {
sanitizeStreamingChunk,
extractThinkingFromContent,
} from "../handlers/responseSanitizer.ts";
import { buildErrorBody } from "./error.ts";
export { COLORS, formatSSE };
@@ -67,6 +68,12 @@ type TranslateState = ReturnType<typeof initState> & {
finishReason?: unknown;
/** Accumulated message content for call log response body */
accumulatedContent?: string;
upstreamError?: {
status: number;
type: string;
code: string;
message: string;
} | null;
};
type ToolCall = {
@@ -151,6 +158,7 @@ export function createSSEStream(options: StreamOptions = {}) {
/** Passthrough: accumulate tool_calls deltas for call log responseBody */
const passthroughToolCalls = new Map<string, ToolCall>();
let passthroughToolCallSeq = 0;
let skipPassthroughEvent = false;
// State for translate mode (accumulatedContent for call log response body)
const state: TranslateState | null =
@@ -233,6 +241,20 @@ export function createSSEStream(options: StreamOptions = {}) {
let injectedUsage = false;
let clientPayload: unknown = null;
if (skipPassthroughEvent) {
if (!trimmed) {
skipPassthroughEvent = false;
}
continue;
}
// Drop whole keepalive event blocks — strict OpenAI-compatible SDKs
// try to JSON.parse empty keepalive payloads and crash.
if (/^event:\s*keepalive\b/i.test(trimmed)) {
skipPassthroughEvent = true;
continue;
}
if (trimmed.startsWith("data:")) {
const providerPayload = parseSSELine(trimmed);
if (providerPayload) {
@@ -468,6 +490,10 @@ export function createSSEStream(options: StreamOptions = {}) {
// Translate mode
if (!trimmed) continue;
if (state?.upstreamError) {
continue;
}
const parsed = parseSSELine(trimmed);
if (!parsed) continue;
providerPayloadCollector.push(parsed);
@@ -661,12 +687,15 @@ export function createSSEStream(options: StreamOptions = {}) {
if (remaining) buffer += remaining;
if (mode === STREAM_MODE.PASSTHROUGH) {
if (buffer) {
const bufferedLine = buffer.trim();
if (skipPassthroughEvent || /^event:\s*keepalive\b/i.test(bufferedLine)) {
skipPassthroughEvent = false;
} else if (buffer) {
let output = buffer;
if (buffer.startsWith("data:") && !buffer.startsWith("data: ")) {
output = "data: " + buffer.slice(5);
}
const bufferedPayload = parseSSELine(buffer.trim());
const bufferedPayload = parseSSELine(bufferedLine);
if (bufferedPayload) {
providerPayloadCollector.push(bufferedPayload);
clientPayloadCollector.push(bufferedPayload);
@@ -795,6 +824,36 @@ export function createSSEStream(options: StreamOptions = {}) {
}
}
if (state?.upstreamError) {
const err = state.upstreamError;
trackPendingRequest(model, provider, connectionId, false);
const errorBody = buildErrorBody(err.status, err.message);
if (onComplete) {
try {
onComplete({
status: err.status,
usage: state?.usage,
responseBody: errorBody,
providerPayload: providerPayloadCollector.build(
buildStreamSummaryFromEvents(
providerPayloadCollector.getEvents(),
targetFormat,
model
),
{ includeEvents: false }
),
clientPayload: clientPayloadCollector.build(errorBody, {
includeEvents: false,
}),
});
} catch {}
}
controller.error(new Error(err.message || "Upstream failure"));
return;
}
// Flush remaining events (only once at stream end)
const flushed = translateResponse(targetFormat, sourceFormat, null, state);
+23 -44
View File
@@ -1,12 +1,12 @@
{
"name": "omniroute",
"version": "3.5.7",
"version": "3.6.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "omniroute",
"version": "3.5.7",
"version": "3.6.2",
"hasInstallScript": true,
"license": "MIT",
"workspaces": [
@@ -17,6 +17,7 @@
"@modelcontextprotocol/sdk": "^1.27.1",
"@monaco-editor/react": "^4.7.0",
"@swc/helpers": "0.5.21",
"axios": "^1.15.0",
"bcryptjs": "^3.0.3",
"better-sqlite3": "^12.6.2",
"bottleneck": "^2.19.5",
@@ -2851,9 +2852,6 @@
"cpu": [
"arm64"
],
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2870,9 +2868,6 @@
"cpu": [
"arm64"
],
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2889,9 +2884,6 @@
"cpu": [
"x64"
],
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2908,9 +2900,6 @@
"cpu": [
"x64"
],
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -7782,7 +7771,6 @@
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"dev": true,
"license": "MIT"
},
"node_modules/atomic-sleep": {
@@ -7831,10 +7819,9 @@
}
},
"node_modules/axios": {
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz",
"integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==",
"dev": true,
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz",
"integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.11",
@@ -8575,7 +8562,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dev": true,
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
@@ -9627,7 +9613,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.4.0"
@@ -9959,7 +9944,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -11134,7 +11118,6 @@
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
@@ -11151,7 +11134,6 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -11161,7 +11143,6 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
@@ -11605,7 +11586,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
@@ -12118,9 +12098,9 @@
}
},
"node_modules/icu-minify": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.9.0.tgz",
"integrity": "sha512-9ev7MqkN29jcIelUAqJRfNCxzGOEkBJPnr+scYATMp2bfpU4Bm1eIwYU0/o5xRy8BBnSWMUjK58WTB3132P0bg==",
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.9.1.tgz",
"integrity": "sha512-6NkfF9GHHFouqnz+wuiLjCWQiyxoEyJ5liUv4Jxxo/8wyhV7MY0L0iTEGDAVEa4aAD58WqTxFMa20S5nyMjwNw==",
"funding": [
{
"type": "individual",
@@ -15612,9 +15592,9 @@
}
},
"node_modules/next-intl": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.9.0.tgz",
"integrity": "sha512-MMNAjewHUw9Ke93E5/Yzhf8lqesesaXJTPlrK3FwECgn4EXG9m7Tuzy4rnDes0ogjDhQIa/Ksj/qmFnHJAOluw==",
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.9.1.tgz",
"integrity": "sha512-N7ga0CjtYcdxNvaKNIi6eJ2mmatlHK5hp8rt0YO2Omoc1m0gean242/Ukdj6+gJNiReBVcYIjK0HZeNx7CV1ug==",
"funding": [
{
"type": "individual",
@@ -15626,11 +15606,11 @@
"@formatjs/intl-localematcher": "^0.8.1",
"@parcel/watcher": "^2.4.1",
"@swc/core": "^1.15.2",
"icu-minify": "^4.9.0",
"icu-minify": "^4.9.1",
"negotiator": "^1.0.0",
"next-intl-swc-plugin-extractor": "^4.9.0",
"next-intl-swc-plugin-extractor": "^4.9.1",
"po-parser": "^2.1.1",
"use-intl": "^4.9.0"
"use-intl": "^4.9.1"
},
"peerDependencies": {
"next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
@@ -15643,9 +15623,9 @@
}
},
"node_modules/next-intl-swc-plugin-extractor": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.9.0.tgz",
"integrity": "sha512-CAu6Qy6XiCenKsvzyCPm2cZFkGfcvhJi8N93TCnOowmzD4Br3ked7QdROusRRp4MQ1iG9u+KCLgVcM9CLDUOIQ==",
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.9.1.tgz",
"integrity": "sha512-8whJJ6oxJz8JqkHarggmmuEDyXgC7nEnaPhZD91CJwEWW4xp0AST3Mw17YxvHyP2vAF3taWfFbs1maD+WWtz3w==",
"license": "MIT"
},
"node_modules/next/node_modules/@swc/helpers": {
@@ -16671,7 +16651,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -20023,9 +20002,9 @@
}
},
"node_modules/use-intl": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.9.0.tgz",
"integrity": "sha512-GehJvP7gu8SvmaDHNDNrRHt2TCNSZt4l1cGJMpUX77TGeZPAQKVQokAVvoYkeTT1UWPtv9RJ6N16UJNButzrgg==",
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.9.1.tgz",
"integrity": "sha512-iGVV/xFYlhe3btafRlL8RPLD2Jsuet4yqn9DR6LWWbMhULsJnXgLonDkzDmsAIBIwFtk02oJuX/Ox2vwHKF+UQ==",
"funding": [
{
"type": "individual",
@@ -20036,7 +20015,7 @@
"dependencies": {
"@formatjs/fast-memoize": "^3.1.0",
"@schummar/icu-type-parser": "1.21.5",
"icu-minify": "^4.9.0",
"icu-minify": "^4.9.1",
"intl-messageformat": "^11.1.0"
},
"peerDependencies": {
@@ -20989,7 +20968,7 @@
},
"open-sse": {
"name": "@omniroute/open-sse",
"version": "3.5.6"
"version": "3.6.2"
}
}
}
+5 -1
View File
@@ -1,6 +1,6 @@
{
"name": "omniroute",
"version": "3.5.7",
"version": "3.6.2",
"description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",
"type": "module",
"bin": {
@@ -16,6 +16,7 @@
"scripts/postinstall.mjs",
"scripts/sync-env.mjs",
"scripts/native-binary-compat.mjs",
"scripts/build-next-isolated.mjs",
"README.md",
"LICENSE"
],
@@ -85,6 +86,8 @@
"check": "npm run lint && npm run test",
"prepublishOnly": "npm run build:cli",
"postinstall": "node scripts/postinstall.mjs",
"uninstall": "node scripts/uninstall.mjs",
"uninstall:full": "node scripts/uninstall.mjs --full",
"prepare": "husky",
"system-info": "node scripts/system-info.mjs"
},
@@ -93,6 +96,7 @@
"@modelcontextprotocol/sdk": "^1.27.1",
"@monaco-editor/react": "^4.7.0",
"@swc/helpers": "0.5.21",
"axios": "^1.15.0",
"bcryptjs": "^3.0.3",
"better-sqlite3": "^12.6.2",
"bottleneck": "^2.19.5",
+30 -4
View File
@@ -3,6 +3,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { spawn } from "node:child_process";
import { pathToFileURL } from "node:url";
/**
* This repository contains a legacy `app/` snapshot (packaging/runtime artifacts)
@@ -24,6 +25,27 @@ async function exists(targetPath) {
}
}
export async function movePath(sourcePath, destinationPath, fsImpl = fs) {
try {
await fsImpl.rename(sourcePath, destinationPath);
} catch (error) {
if (error?.code !== "EXDEV") {
throw error;
}
console.warn(
`[build-next-isolated] EXDEV while moving ${sourcePath} -> ${destinationPath}; falling back to copy/remove`
);
await fsImpl.cp(sourcePath, destinationPath, {
recursive: true,
preserveTimestamps: true,
force: false,
errorOnExist: true,
});
await fsImpl.rm(sourcePath, { recursive: true, force: true });
}
}
function runNextBuild() {
return new Promise((resolve) => {
const nextBin = path.join(projectRoot, "node_modules", "next", "dist", "bin", "next");
@@ -52,12 +74,12 @@ function runNextBuild() {
});
}
async function main() {
export async function main() {
let moved = false;
try {
if (await exists(legacyAppDir)) {
await fs.rename(legacyAppDir, backupDir);
await movePath(legacyAppDir, backupDir);
moved = true;
}
@@ -86,7 +108,7 @@ async function main() {
} finally {
if (moved) {
try {
await fs.rename(backupDir, legacyAppDir);
await movePath(backupDir, legacyAppDir);
} catch (restoreError) {
console.error(
`[build-next-isolated] Failed to restore legacy app dir from ${backupDir}:`,
@@ -98,4 +120,8 @@ async function main() {
}
}
await main();
const entryScript = process.argv[1] ? pathToFileURL(process.argv[1]).href : null;
if (entryScript === import.meta.url) {
await main();
}

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