Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e4495b85b | |||
| b5e1c8e47b | |||
| 36a05831ab | |||
| 12b895f94a | |||
| e89015649e | |||
| 86fc7841b8 | |||
| 76e920fc1a | |||
| 99591a2b0f | |||
| 770b70a135 | |||
| 6845ef6bde | |||
| d4609762bb | |||
| ebf63a75d5 | |||
| 3effbe5f06 | |||
| c742433d34 | |||
| bd33b53805 | |||
| 1d6739b683 | |||
| e75baed4b6 | |||
| 55f73d34e1 | |||
| 557157c2d6 | |||
| 0bae35d387 | |||
| c7062bc560 | |||
| a344352365 | |||
| 33d86ad3b5 | |||
| 8bacde0262 | |||
| 87c82071c0 | |||
| 1f72810649 | |||
| 6711095dd6 | |||
| e39a42464e | |||
| 515674b6cf | |||
| 37cc63e493 | |||
| 4cd43f9c93 | |||
| 691d83e596 | |||
| 4bca25d783 | |||
| 74a5bcb3a9 | |||
| 9f55159bd5 | |||
| f118082f6b | |||
| 586e9f328f | |||
| fb9d52a19b | |||
| 815a7b6e1d | |||
| 336d889034 | |||
| bba7479688 |
@@ -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.
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 18–22 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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
+529
-389
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+424
-325
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+429
-330
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+425
-325
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+426
-327
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+427
-327
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+432
-331
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+433
-334
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
+433
-334
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+433
-334
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+431
-331
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+434
-335
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+428
-328
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+431
-330
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+434
-334
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+428
-328
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+431
-331
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+426
-326
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+419
-319
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+432
-333
File diff suppressed because it is too large
Load Diff
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
+429
-329
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+428
-328
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+429
-329
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+431
-332
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+425
-325
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+433
-334
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+434
-333
File diff suppressed because it is too large
Load Diff
@@ -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:
|
||||
|
||||
+424
-325
File diff suppressed because it is too large
Load Diff
+15
-3
@@ -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:
|
||||
|
||||
+427
-328
File diff suppressed because it is too large
Load Diff
@@ -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:
|
||||
|
||||
+436
-332
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -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
@@ -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
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 || "";
|
||||
|
||||
@@ -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();
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
Generated
+23
-44
@@ -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
@@ -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",
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user