Compare commits
450 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 028874fd05 | |||
| 6d366fe80f | |||
| 0924f767e9 | |||
| 173b5a1cd1 | |||
| 49e1d51be9 | |||
| 23e47a74ee | |||
| fce7f6ce47 | |||
| f3b47a16dd | |||
| aa7b754693 | |||
| 397b13e2d8 | |||
| b2c203e8c1 | |||
| 6afb314d26 | |||
| 28123355b4 | |||
| bcb87f5d55 | |||
| 67b9a3bc0e | |||
| ab4914ee6a | |||
| e7c73c76dd | |||
| 3591a3fe5c | |||
| fbdce049b2 | |||
| 9a8520a2de | |||
| a315ab29bc | |||
| 5437d691b5 | |||
| f99c90dc85 | |||
| d838388443 | |||
| 0b2c488a61 | |||
| e2eb4ef29d | |||
| 76e135077b | |||
| 6078cd2eab | |||
| 3482dade71 | |||
| ff73de5716 | |||
| 04d0c350db | |||
| b6a5c91045 | |||
| 7a37c79ebc | |||
| ba227c5ec3 | |||
| 7ab75dd15a | |||
| df23162e9d | |||
| 2c12f18b44 | |||
| eaeb28b4e1 | |||
| d5647eab33 | |||
| 89eb8885b1 | |||
| a5dc5687f8 | |||
| 6780485051 | |||
| d043e7a242 | |||
| c5d9b5f51d | |||
| 35e2892b98 | |||
| b492c5ac1a | |||
| df38b3c62a | |||
| 03a860dd6f | |||
| fec585e44b | |||
| 11dfdbb7a3 | |||
| ae1a0f411b | |||
| 007b5d7f50 | |||
| c6eadc504b | |||
| a864258cb8 | |||
| 8a9c15c874 | |||
| 7a666526b7 | |||
| 3fc1cac015 | |||
| 04a0b07bf6 | |||
| 59e48ca91a | |||
| 8ff562c5af | |||
| b502a93728 | |||
| b6afa6c2c7 | |||
| 5887da0229 | |||
| a7d833d96a | |||
| db3753d611 | |||
| f810b13bca | |||
| 5ad687c6d8 | |||
| 6ad0910790 | |||
| 4d8c0546cf | |||
| 35f96d4a40 | |||
| ae96fb6f63 | |||
| 67592d80aa | |||
| 94a5e43e5d | |||
| 26958f8f70 | |||
| a427d215e3 | |||
| 271cf37b8a | |||
| 179c03e79d | |||
| 0a1b68639b | |||
| d69e7ec850 | |||
| 76a6d8292c | |||
| 8f09c444b6 | |||
| 9032e6abb8 | |||
| 1c070d16a6 | |||
| 7837fcc657 | |||
| f9690d40d3 | |||
| 5de6cd77dc | |||
| aa5ab55b14 | |||
| 9195b18981 | |||
| b812d6efb8 | |||
| 231a02eb10 | |||
| 6736806361 | |||
| 8e17756bf8 | |||
| 0b133fe55e | |||
| d01266c642 | |||
| fe3f9c86d5 | |||
| 14bf3645d6 | |||
| 0f4a7b2405 | |||
| 681e49a4cc | |||
| 6e9c97fbff | |||
| 370070f489 | |||
| 7168f4014d | |||
| f0912feefb | |||
| e90c9c171a | |||
| d0c172830c | |||
| d5bf0d1199 | |||
| d3a24446b8 | |||
| aa93276e6e | |||
| cf36972969 | |||
| 40862f26e6 | |||
| 4083447c3f | |||
| 3cb34ad827 | |||
| 61d7566ca1 | |||
| af338d447b | |||
| 6fad06f659 | |||
| 1d51d8ff27 | |||
| 82dd4aa403 | |||
| 8af9bd1ac3 | |||
| 9fc3845d92 | |||
| 93bbe8e7a8 | |||
| 46acd16999 | |||
| 5ad2c6abf6 | |||
| d5781d60bd | |||
| e464a95c5a | |||
| a50ea4bb9e | |||
| aa11bb6d93 | |||
| 319018f055 | |||
| 394b986ccb | |||
| 26f7b36ce4 | |||
| f0daad10ce | |||
| 0bc557fb8b | |||
| 3571421a0e | |||
| aed80f3e4f | |||
| b84e79362e | |||
| dc077bc309 | |||
| 0fd634ef43 | |||
| d352b6b509 | |||
| fcc48cc738 | |||
| ec06a345cc | |||
| 7690b364e7 | |||
| b94c0c7d04 | |||
| 500bfdf588 | |||
| d23b19c466 | |||
| 3a5450039d | |||
| b582ddf090 | |||
| ef8b470e8b | |||
| 5a0841a994 | |||
| bd462c4e0b | |||
| f11ec4e142 | |||
| a5393a3ec4 | |||
| bf76da3222 | |||
| f171b7de96 | |||
| c0cbf00199 | |||
| 0cd6e59fb9 | |||
| 11a8adc71c | |||
| b9c7fd879f | |||
| 2fc4c7ea33 | |||
| c5003665c3 | |||
| 538028c150 | |||
| fb8d187f8d | |||
| 1a11301e1a | |||
| 4c6cdd5c23 | |||
| 30a64b0dd3 | |||
| 04de492019 | |||
| 07890df6cb | |||
| 2f23cfdf1c | |||
| 1832946d41 | |||
| 6ec8745d2e | |||
| b6bbfe063b | |||
| 48182edbd5 | |||
| 94a00cb6d6 | |||
| fc24361aa6 | |||
| cec833afc6 | |||
| f1cddba938 | |||
| a0acdfdcb9 | |||
| 6637f294df | |||
| ad8a444105 | |||
| 877cfa0071 | |||
| e6f0a780b7 | |||
| dd9de2efa9 | |||
| f6b0811f78 | |||
| eba9d854a9 | |||
| 437cf9bab0 | |||
| fdaeccf1e5 | |||
| 7723e46c26 | |||
| dce355cce6 | |||
| 213e7b7093 | |||
| fe7d8f93a1 | |||
| 9e2f4216f9 | |||
| a48f7b2222 | |||
| 0b85d8a9bc | |||
| 58d6938065 | |||
| a536a2b822 | |||
| 9ffad1005e | |||
| 65edddd62e | |||
| a7cdcd8b3a | |||
| 3d6b85ed20 | |||
| 7abea2020c | |||
| e16c34f0e3 | |||
| 4bfda6a145 | |||
| 98470e8551 | |||
| df558ab8d6 | |||
| c07372b58c | |||
| 00f59b95ae | |||
| 8915a7c2cd | |||
| 8595964ab8 | |||
| 922dae8546 | |||
| 69b3e23400 | |||
| 55325773dc | |||
| b84c915b23 | |||
| cfb390936a | |||
| c5f344f333 | |||
| ba4b496306 | |||
| c48554589c | |||
| da0851e21d | |||
| d2d05abac0 | |||
| de3e0423cc | |||
| 8d742d7938 | |||
| 682fd550fa | |||
| abcf836a0c | |||
| b123fb2cc7 | |||
| 0da3621a68 | |||
| 8ed452d9ea | |||
| f380d44697 | |||
| 86d377a2f0 | |||
| 508a6d99f5 | |||
| 63e42047e3 | |||
| 769be46bf9 | |||
| 13829de0d9 | |||
| ad7f570be5 | |||
| 9ba4f966db | |||
| ae8d2ac2e1 | |||
| 93beb068a3 | |||
| e88d260acd | |||
| 8121238872 | |||
| 161e377ec1 | |||
| ad4bd800aa | |||
| 2fba6f65f4 | |||
| a754ab4f10 | |||
| 86cfc468bd | |||
| 7df0c1607e | |||
| 6acd36e374 | |||
| af51eecbac | |||
| 3a23dc8b04 | |||
| ba13e44720 | |||
| e80420f6db | |||
| 21ddcfc866 | |||
| 20f82cb22c | |||
| 7ef75bab23 | |||
| 7224e03590 | |||
| cf4f2991a5 | |||
| 9eb3c23494 | |||
| c80d8898cc | |||
| bc74dd88e0 | |||
| da87c461ef | |||
| bf2e694f2c | |||
| e5150487c4 | |||
| 9ff6353b88 | |||
| 926fd8abf4 | |||
| 211a7a4cfe | |||
| c1835cd9cc | |||
| 5700044393 | |||
| 36fbd3d018 | |||
| d1178390a9 | |||
| 8182825e92 | |||
| 2392006246 | |||
| a6e78cd5dc | |||
| 8752790352 | |||
| 3976c79e12 | |||
| 5c1cf7f4ac | |||
| 7e90b8b7be | |||
| 912321a030 | |||
| ab0a905499 | |||
| 3c6b3c02df | |||
| bcb2e91d97 | |||
| 766ef94605 | |||
| e3f016e262 | |||
| 65833f1ae0 | |||
| 2602cd9ab2 | |||
| 8333f3d9de | |||
| dee1d9ba74 | |||
| ed2e0c5080 | |||
| 7db810d7d0 | |||
| 8dae4e5038 | |||
| b9b28edefe | |||
| 58120f435f | |||
| 027b8e52da | |||
| aad510a9d5 | |||
| 9852a805a1 | |||
| b2cabf0122 | |||
| 521ce15f86 | |||
| fb97c11140 | |||
| 1c5c62e311 | |||
| 77148f7f97 | |||
| a329d2f2bc | |||
| 39e9e4446b | |||
| b32de54944 | |||
| 071b874e1b | |||
| 9ba65d3323 | |||
| 890a851bbf | |||
| 5f6ca23da4 | |||
| 58df1c06ee | |||
| 95f8599dc2 | |||
| 8a11242d7f | |||
| 948513ef5f | |||
| c497a35d21 | |||
| e0a539bc64 | |||
| 44b8395ead | |||
| 1bc8878490 | |||
| ded2ac493d | |||
| 57b3319ac0 | |||
| eba7ba25b8 | |||
| df774892c8 | |||
| f3b4ce6b67 | |||
| bb8545b3e1 | |||
| 600149fc2b | |||
| f4de3c8748 | |||
| 6e7e04839f | |||
| f62dcc12a0 | |||
| bef591c2e6 | |||
| 5907296d36 | |||
| aa2a7d12be | |||
| 33fee5dcc5 | |||
| e9ae50be0c | |||
| 5886c0fd5e | |||
| ed146fcf07 | |||
| 35538e6f77 | |||
| ea924f3bbf | |||
| 7bc15a2fc9 | |||
| 2bf7db92ee | |||
| 95260f56ba | |||
| c5ace0376a | |||
| 7ee09388fa | |||
| a15b0ef060 | |||
| 57cfd9a315 | |||
| 5fb4149c32 | |||
| 03d97ba617 | |||
| 5205f5f4b4 | |||
| 6eda0f4d00 | |||
| 9e640cac6b | |||
| 061521f87f | |||
| b15eb278e1 | |||
| 142ac8eb96 | |||
| 88705bb6e9 | |||
| 60d4fcfe7e | |||
| 038d19ec98 | |||
| e1b98768c7 | |||
| b82af2b849 | |||
| 703591d76a | |||
| 7142688a77 | |||
| a12622b3d8 | |||
| 9248ab4dfd | |||
| 5a8c6440f0 | |||
| 74b694a4dd | |||
| 896b52d5fb | |||
| 1429fea27a | |||
| 3218563f32 | |||
| d412edbbe1 | |||
| 968159a85d | |||
| 18a3741fc2 | |||
| f1be3e6bb0 | |||
| b717a02394 | |||
| d68143e63d | |||
| 0d306b8b1c | |||
| a655863855 | |||
| 58264c80dd | |||
| 6f9f1aec65 | |||
| 97b1ee5b02 | |||
| fe033cd0b3 | |||
| afbd07c62a | |||
| 9b15996545 | |||
| 1dbbd7241d | |||
| 6c0ef48d45 | |||
| 8b57f88ca3 | |||
| 3e9fdc777e | |||
| a8ca88797a | |||
| 71540b5dc0 | |||
| b5a145d7b3 | |||
| 21d6a0a2dd | |||
| 80cc7340ac | |||
| 45b272ee2f | |||
| f765664580 | |||
| 10b44f036d | |||
| 1bf4ee3a3c | |||
| 5d82ffa503 | |||
| 5dc3fd2ec0 | |||
| 4562fdda92 | |||
| 18258b9b0d | |||
| 92e0f242c7 | |||
| 428fa9404c | |||
| 3cccc480fb | |||
| acb94216c8 | |||
| 5fa97841b2 | |||
| 4ad66bf7b9 | |||
| 64860ed5e5 | |||
| b17faf6e1e | |||
| 0ea73bd527 | |||
| b2f0820560 | |||
| 7ad5d42982 | |||
| 3912734498 | |||
| 0fa3f9a057 | |||
| 0fbabdcf25 | |||
| 67b7ae98a6 | |||
| 0f703c95dd | |||
| c34b3f41bd | |||
| e003b17280 | |||
| e003d58c60 | |||
| 0546d06c0a | |||
| 5337111990 | |||
| bb06f8eb0c | |||
| 23e3a1c269 | |||
| e47740e02e | |||
| d9ff0035f5 | |||
| 7a7f3be0d2 | |||
| 91e45fbe95 | |||
| 7d7e9da28c | |||
| 24a9739604 | |||
| 4fb9687782 | |||
| 95ffc21b60 | |||
| f3c5e55b26 | |||
| 40183c6a5c | |||
| 457c59e38a | |||
| aa93a3f2e2 | |||
| 8b9abcb6cc | |||
| 1ecc1908c7 | |||
| 6a2c7b467d | |||
| 0acef57865 | |||
| 43046ee649 | |||
| a15fda0c08 | |||
| e5988764ce | |||
| 9c9d9b5a8d | |||
| 44dc564d85 | |||
| 83e367afab | |||
| 8b7e7c2669 | |||
| 53474021b7 | |||
| da1ed1b5b2 | |||
| e08d661600 | |||
| 1aa1bc7a26 | |||
| 47634e942e | |||
| 15466cbf1a | |||
| 2a749db427 | |||
| ecccce86e4 | |||
| bf3f64bea4 | |||
| 2f2d6b8535 | |||
| d68c884649 | |||
| 8b556de03b | |||
| 7229af53c3 | |||
| 81b3034c2f | |||
| f0419396b5 | |||
| 6b9c2754e8 | |||
| 8edb131f8b |
@@ -0,0 +1,39 @@
|
||||
---
|
||||
description: Deploy the latest OmniRoute code to the Akamai VPS (69.164.221.35)
|
||||
---
|
||||
|
||||
# Deploy to Akamai VPS Workflow
|
||||
|
||||
Deploy OmniRoute to the Akamai VPS using `npm pack + scp` + PM2.
|
||||
|
||||
**Akamai VPS:** `69.164.221.35`
|
||||
**Process manager:** PM2 (`omniroute`)
|
||||
**Port:** `20128`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Build + pack locally
|
||||
|
||||
// turbo
|
||||
|
||||
```bash
|
||||
cd /home/diegosouzapw/dev/proxys/9router && npm run build:cli && npm pack --ignore-scripts
|
||||
```
|
||||
|
||||
### 2. Copy to Akamai VPS and install
|
||||
|
||||
// turbo-all
|
||||
|
||||
```bash
|
||||
scp omniroute-*.tgz root@69.164.221.35:/tmp/
|
||||
```
|
||||
|
||||
```bash
|
||||
ssh root@69.164.221.35 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 && pm2 delete omniroute 2>/dev/null; pm2 start /root/.omniroute/ecosystem.config.cjs --update-env && pm2 save && echo '✅ Akamai done'"
|
||||
```
|
||||
|
||||
### 3. Verify the deployment
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -w 'AKAMAI HTTP %{http_code}\n' http://69.164.221.35:20128/
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
description: Deploy the latest OmniRoute code to BOTH the Akamai VPS and the Local VPS
|
||||
---
|
||||
|
||||
# Deploy to VPS (Both) Workflow
|
||||
|
||||
Deploy OmniRoute to the production VPSs using `npm pack + scp` + PM2.
|
||||
|
||||
**Akamai VPS:** `69.164.221.35`
|
||||
**Local VPS:** `192.168.0.15`
|
||||
**Process manager:** PM2 (`omniroute`)
|
||||
**Port:** `20128`
|
||||
**PM2 entry:** `/usr/lib/node_modules/omniroute/app/server.js`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The npm registry rejects packages > 100MB, so deployment uses **npm pack + scp**.
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Build + pack locally
|
||||
|
||||
// turbo
|
||||
|
||||
```bash
|
||||
cd /home/diegosouzapw/dev/proxys/9router && npm run build:cli && npm pack --ignore-scripts
|
||||
```
|
||||
|
||||
### 2. Copy to both VPS and install
|
||||
|
||||
// turbo-all
|
||||
|
||||
```bash
|
||||
scp omniroute-*.tgz root@69.164.221.35:/tmp/ && scp omniroute-*.tgz root@192.168.0.15:/tmp/
|
||||
```
|
||||
|
||||
```bash
|
||||
ssh root@69.164.221.35 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 && pm2 delete omniroute 2>/dev/null; pm2 start /root/.omniroute/ecosystem.config.cjs --update-env && pm2 save && echo '✅ Akamai done'"
|
||||
```
|
||||
|
||||
```bash
|
||||
ssh root@192.168.0.15 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 && pm2 delete omniroute 2>/dev/null; pm2 start /root/.omniroute/ecosystem.config.cjs --update-env && pm2 save && echo '✅ Local done'"
|
||||
```
|
||||
|
||||
### 3. Verify the deployment
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -w 'AKAMAI HTTP %{http_code}\n' http://69.164.221.35:20128/
|
||||
curl -s -o /dev/null -w 'LOCAL HTTP %{http_code}\n' http://192.168.0.15:20128/
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
description: Deploy the latest OmniRoute code to the Local VPS (192.168.0.15)
|
||||
---
|
||||
|
||||
# Deploy to Local VPS Workflow
|
||||
|
||||
Deploy OmniRoute to the Local VPS using `npm pack + scp` + PM2.
|
||||
|
||||
**Local VPS:** `192.168.0.15`
|
||||
**Process manager:** PM2 (`omniroute`)
|
||||
**Port:** `20128`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Build + pack locally
|
||||
|
||||
// turbo
|
||||
|
||||
```bash
|
||||
cd /home/diegosouzapw/dev/proxys/9router && npm run build:cli && npm pack --ignore-scripts
|
||||
```
|
||||
|
||||
### 2. Copy to Local VPS and install
|
||||
|
||||
// turbo-all
|
||||
|
||||
```bash
|
||||
scp omniroute-*.tgz root@192.168.0.15:/tmp/
|
||||
```
|
||||
|
||||
```bash
|
||||
ssh root@192.168.0.15 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 && pm2 delete omniroute 2>/dev/null; pm2 start /root/.omniroute/ecosystem.config.cjs --update-env && pm2 save && echo '✅ Local done'"
|
||||
```
|
||||
|
||||
### 3. Verify the deployment
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -w 'LOCAL HTTP %{http_code}\n' http://192.168.0.15:20128/
|
||||
```
|
||||
@@ -1,102 +0,0 @@
|
||||
---
|
||||
description: Deploy the latest OmniRoute code to the Akamai VPS (69.164.221.35) via npm
|
||||
---
|
||||
|
||||
# Deploy to VPS Workflow
|
||||
|
||||
Deploy OmniRoute to the production VPS using `npm pack + scp` + PM2.
|
||||
|
||||
**VPS:** `69.164.221.35` (Akamai, Ubuntu 24.04, 1GB RAM + 2.5GB swap)
|
||||
**Local VPS:** `192.168.0.15` (same setup)
|
||||
**Process manager:** PM2 (`omniroute`)
|
||||
**Port:** `20128`
|
||||
**PM2 entry:** `/usr/lib/node_modules/omniroute/app/server.js`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> PM2 runs from the global npm package at `/usr/lib/node_modules/omniroute`.
|
||||
> The Next.js standalone build is at `app/server.js` inside that directory.
|
||||
> The npm registry rejects packages > 100MB, so deployment uses **npm pack + scp**.
|
||||
|
||||
> [!CAUTION]
|
||||
> **NEVER** use `pm2 restart omniroute` after `npm install -g`. This drops env vars.
|
||||
> Always use `pm2 delete omniroute && pm2 start <ecosystem.config.cjs> --update-env`.
|
||||
> After `npm install -g`, always rebuild better-sqlite3: `cd .../app && npm rebuild better-sqlite3`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Build + pack locally
|
||||
|
||||
Run the full build (includes hash-strip patch) and create the .tgz:
|
||||
|
||||
// turbo
|
||||
|
||||
```bash
|
||||
cd /home/diegosouzapw/dev/proxys/9router && npm run build:cli && npm pack --ignore-scripts
|
||||
```
|
||||
|
||||
### 2. Copy to both VPS and install
|
||||
|
||||
// turbo-all
|
||||
|
||||
```bash
|
||||
scp omniroute-*.tgz root@69.164.221.35:/tmp/ && scp omniroute-*.tgz root@192.168.0.15:/tmp/
|
||||
```
|
||||
|
||||
```bash
|
||||
ssh root@69.164.221.35 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 && pm2 delete omniroute 2>/dev/null; pm2 start /root/.omniroute/ecosystem.config.cjs --update-env && pm2 save && echo '✅ Akamai done'"
|
||||
```
|
||||
|
||||
```bash
|
||||
ssh root@192.168.0.15 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 && pm2 delete omniroute 2>/dev/null; pm2 start /root/.omniroute/ecosystem.config.cjs --update-env && pm2 save && echo '✅ Local done'"
|
||||
```
|
||||
|
||||
### 3. Verify the deployment
|
||||
|
||||
```bash
|
||||
ssh root@69.164.221.35 "pm2 list && cat \$(npm root -g)/omniroute/app/package.json | grep version | head -1 && curl -s -o /dev/null -w 'HTTP %{http_code}' http://localhost:20128/"
|
||||
```
|
||||
|
||||
```bash
|
||||
ssh root@192.168.0.15 "pm2 list && cat \$(npm root -g)/omniroute/app/package.json | grep version | head -1 && curl -s -X POST http://localhost:20128/api/auth/login -H 'Content-Type: application/json' -d '{\"password\":\"123456\"}'"
|
||||
```
|
||||
|
||||
Expected: PM2 shows `online`, version matches, login returns `{"success":true}`.
|
||||
|
||||
## How it works
|
||||
|
||||
1. `npm run build:cli` builds Next.js standalone → `app/` and strips Turbopack hashed require() calls from chunks
|
||||
2. `npm pack --ignore-scripts` packages without re-running the build
|
||||
3. `scp` transfers the .tgz to each VPS (~286MB)
|
||||
4. `npm install -g /tmp/omniroute-*.tgz --ignore-scripts` installs pre-built package
|
||||
5. `npm rebuild better-sqlite3` recompiles native bindings for the VPS Node.js version
|
||||
6. `pm2 delete` + `pm2 start ecosystem.config.cjs --update-env` restarts with env vars
|
||||
7. `pm2 save` persists the process list for reboot survival
|
||||
|
||||
## Ecosystem Config
|
||||
|
||||
Both VPSs have `ecosystem.config.cjs` at `/root/.omniroute/ecosystem.config.cjs`.
|
||||
This file defines env vars (PORT, DATA_DIR, INITIAL_PASSWORD, OAuth secrets, etc.)
|
||||
that `pm2 restart` does NOT inject — only `pm2 start --update-env` does.
|
||||
|
||||
## PM2 Setup (one-time — if reconfiguring from scratch)
|
||||
|
||||
```bash
|
||||
ssh root@<VPS> "
|
||||
pm2 delete omniroute 2>/dev/null;
|
||||
cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 &&
|
||||
pm2 start /root/.omniroute/ecosystem.config.cjs --update-env &&
|
||||
pm2 save && pm2 startup
|
||||
"
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Ensure `/root/.omniroute/ecosystem.config.cjs` exists with all required env vars.
|
||||
> For fresh installs, copy from the existing VPS or create from the template in `.env`.
|
||||
|
||||
## Notes
|
||||
|
||||
- Env vars are in `/root/.omniroute/ecosystem.config.cjs` (NOT `.env` in app dir)
|
||||
- PM2 is configured with `pm2 startup` to auto-restart on reboot
|
||||
- Nginx proxies `omniroute.online` → `localhost:20128`
|
||||
- The VPS has only 1GB RAM — builds happen locally, never on the VPS
|
||||
- After `npm install -g`, `better-sqlite3` MUST be rebuilt in the `app/` subdir
|
||||
@@ -96,7 +96,18 @@ Keep an empty `## [Unreleased]` section above it.
|
||||
// turbo
|
||||
|
||||
```bash
|
||||
VERSION=$(node -p "require('./package.json').version") && sed -i "s/ version: .*/ version: $VERSION/" docs/openapi.yaml && echo "✓ openapi.yaml → $VERSION"
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
sed -i "s/ version: .*/ version: $VERSION/" docs/openapi.yaml
|
||||
echo "✓ openapi.yaml → $VERSION"
|
||||
|
||||
for dir in electron open-sse; do
|
||||
if [ -d "$dir" ] && [ -f "$dir/package.json" ]; then
|
||||
(cd "$dir" && npm version "$VERSION" --no-git-tag-version --allow-same-version > /dev/null)
|
||||
echo "✓ $dir/package.json → $VERSION"
|
||||
fi
|
||||
done
|
||||
# Re-run install to assert the workspace lockfile is updated
|
||||
npm install
|
||||
```
|
||||
|
||||
### 6. Update README.md and i18n docs
|
||||
|
||||
@@ -18,11 +18,24 @@ Fetches open feature request issues, analyzes each against the current codebase,
|
||||
|
||||
### 2. Fetch Open Feature Request Issues
|
||||
|
||||
// turbo
|
||||
// turbo-all
|
||||
|
||||
- Run: `gh issue list --repo <owner>/<repo> --state open --limit 50 --json number,title,labels,body,comments,createdAt,author`
|
||||
- Filter for issues that are feature requests (label `enhancement`/`feature`, or body describes new functionality, or previously classified as feature request)
|
||||
- Sort by oldest first
|
||||
**⚠️ CRITICAL**: The JSON output of `gh issue list` can be truncated by the tool, silently hiding issues and their comments. You MUST use the two-step approach below to guarantee **all** feature requests and their full conversations are fetched.
|
||||
|
||||
**Step 2a — Get Issue numbers only** (small output, never truncated):
|
||||
|
||||
- Run: `gh issue list --repo <owner>/<repo> --state open --labels "enhancement" --limit 500 --json number --jq '.[].number'`
|
||||
- (Also run the same for `--labels "feature"` if they are separated, or filter all open issues if labels are not strictly used).
|
||||
- This outputs one issue number per line. Count them and confirm total.
|
||||
|
||||
**Step 2b — Fetch full metadata & conversations for each Issue** (one call per issue):
|
||||
|
||||
- For each issue number from step 2a, run:
|
||||
`gh issue view <NUMBER> --repo <owner>/<repo> --json number,title,labels,body,comments,createdAt,author`
|
||||
- Read not just the body, but **ALL comments (`comments` array)** completely to understand the full context, agreements, and restrictions discussed by the community.
|
||||
- You may batch these into parallel calls (up to 4 at a time).
|
||||
- Filter for issues that are feature requests (if not already filtered by label).
|
||||
- Sort by oldest first.
|
||||
|
||||
### 3. Analyze Each Feature Request
|
||||
|
||||
|
||||
@@ -19,11 +19,21 @@ This workflow fetches all open issues from the project's GitHub repository, clas
|
||||
|
||||
### 2. Fetch All Open Issues
|
||||
|
||||
// turbo
|
||||
// turbo-all
|
||||
|
||||
- Run: `gh issue list --repo <owner>/<repo> --state open --limit 500 --json number,title,labels,body,comments,createdAt,author`
|
||||
- Parse the JSON output to get a list of **all** open issues
|
||||
- Sort by oldest first (FIFO)
|
||||
**⚠️ CRITICAL**: The JSON output of `gh issue list` can be truncated by the tool, silently hiding issues. You MUST use the two-step approach below to guarantee **all** issues are fetched.
|
||||
|
||||
**Step 2a — Get Issue numbers only** (small output, never truncated):
|
||||
|
||||
- Run: `gh issue list --repo <owner>/<repo> --state open --limit 500 --json number --jq '.[].number'`
|
||||
- This outputs one issue number per line. Count them and confirm total.
|
||||
|
||||
**Step 2b — Fetch full metadata for each Issue** (one call per issue):
|
||||
|
||||
- For each issue number from step 2a, run:
|
||||
`gh issue view <NUMBER> --repo <owner>/<repo> --json number,title,labels,body,comments,createdAt,author`
|
||||
- You may batch these into parallel calls (up to 4 at a time).
|
||||
- Sort by oldest first (FIFO).
|
||||
|
||||
### 3. Classify Each Issue
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
---
|
||||
description: Read all open GitHub Discussions, summarize them, respond to pending ones, and create issues from actionable feature requests
|
||||
---
|
||||
|
||||
# /review-discussions — GitHub Discussions Review & Response Workflow
|
||||
|
||||
## Overview
|
||||
|
||||
This workflow reads all open GitHub Discussions, generates a categorized summary, identifies which ones need a response, drafts and posts replies, and optionally creates issues from actionable feature requests. It follows the same flow used for Issues but adapted for the Discussions forum.
|
||||
|
||||
// turbo-all
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Identify the GitHub Repository
|
||||
|
||||
- Run: `git -C <project_root> remote get-url origin` to extract the owner/repo
|
||||
- Parse the owner and repo name from the URL
|
||||
|
||||
### 2. Fetch All Open Discussions
|
||||
|
||||
- Use `read_url_content` to fetch `https://github.com/<owner>/<repo>/discussions`
|
||||
- Parse the discussion list to get all discussion titles, IDs, authors, categories, and dates
|
||||
- For each discussion, fetch the individual page to read the full content and all comments/replies
|
||||
|
||||
### 3. Summarize All Discussions
|
||||
|
||||
For each discussion, extract:
|
||||
|
||||
- **Title** and **#Number**
|
||||
- **Author** (GitHub username)
|
||||
- **Category** (Announcements, General, Ideas, Q&A, Show and tell)
|
||||
- **Date** created
|
||||
- **Summary** of the original post (1-2 sentences)
|
||||
- **Comments count** and key participants
|
||||
- **Your previous response** (if any)
|
||||
- **Pending action** — whether a response or follow-up is needed
|
||||
|
||||
### 4. Present Summary Report to User
|
||||
|
||||
Present the full summary to the user organized by category, using a table:
|
||||
|
||||
| # | Category | Title | Author | Date | Status |
|
||||
| --- | -------- | ----- | ------ | ------ | ----------------- |
|
||||
| #N | Ideas | Title | @user | Mar 23 | ⚠️ Needs response |
|
||||
| #N | Q&A | Title | @user | Mar 9 | ✅ Answered |
|
||||
| #N | General | Title | @user | Mar 19 | ⚠️ Needs response |
|
||||
|
||||
Highlight:
|
||||
|
||||
- **⚠️ Needs response** — No reply from maintainer, or a follow-up comment was left unanswered
|
||||
- **✅ Answered** — Maintainer already responded
|
||||
- **🐛 Bug reported** — A bug was mentioned that needs tracking
|
||||
- **💡 Actionable** — Contains a concrete feature request that could become an issue
|
||||
|
||||
### 5. Draft & Post Responses
|
||||
|
||||
For each discussion that needs a response, draft a reply following these guidelines:
|
||||
|
||||
#### Response Style
|
||||
|
||||
- **Friendly and professional** — Start with "Hey @username!"
|
||||
- **Acknowledge the contribution** — Thank the user for their input
|
||||
- **Be specific** — Reference existing features, settings, or dashboard pages if the feature already exists
|
||||
- **Provide workarounds** — If the request isn't implemented yet, suggest current alternatives
|
||||
- **Commit to action** — If the request is valid, state that you'll open an issue or add it to the roadmap
|
||||
- **Keep it concise** — 3-5 paragraphs max
|
||||
|
||||
#### Posting via Browser
|
||||
|
||||
- Use `browser_subagent` to navigate to each discussion and post the comment
|
||||
- **IMPORTANT**: When typing text in GitHub comment boxes via the browser, use only plain ASCII characters:
|
||||
- Use regular hyphens `-` instead of em-dashes
|
||||
- Use `->` instead of arrow symbols
|
||||
- Do NOT use emoji Unicode characters (the browser keyboard may fail on them)
|
||||
- Use `**bold**` and `\`code\`` markdown formatting
|
||||
- Click the green "Comment" button (or "Reply" for threaded replies) after typing
|
||||
- Verify the comment was posted by checking the page shows the new comment
|
||||
|
||||
### 6. Create Issues from Actionable Feature Requests
|
||||
|
||||
For discussions that contain concrete, actionable feature requests:
|
||||
|
||||
1. Ask the user which ones should become issues
|
||||
2. For each approved request, create a GitHub issue via `browser_subagent`:
|
||||
- Navigate to `https://github.com/<owner>/<repo>/issues/new`
|
||||
- **Title**: `<Feature Name> - <Short description>`
|
||||
- **Body** should include:
|
||||
- `## Feature Request` header
|
||||
- `**Source:** Discussion #N by @author`
|
||||
- `## Problem` — What limitation the user hit
|
||||
- `## Proposed Solution` — How it could work
|
||||
- `### Implementation Ideas` — Technical approach
|
||||
- `### Current Workarounds` — What users can do today
|
||||
- `## Additional Context` — Links to related issues/discussions
|
||||
- Add `enhancement` label
|
||||
- Click "Submit new issue" / "Create"
|
||||
3. After creation, go back to the original discussion and post a comment linking to the new issue:
|
||||
- "I've opened Issue #N to track this feature request. Follow along there for updates!"
|
||||
|
||||
### 7. Final Report
|
||||
|
||||
Present a final summary to the user:
|
||||
|
||||
| Discussion | Action Taken |
|
||||
| ---------- | ---------------------------------- |
|
||||
| #N — Title | Responded with workarounds |
|
||||
| #N — Title | Responded + created Issue #N |
|
||||
| #N — Title | Already answered, no action needed |
|
||||
| #N — Title | Responded to follow-up comment |
|
||||
|
||||
## Notes
|
||||
|
||||
- This workflow is **interactive** — always present the summary and wait for user approval before posting responses or creating issues
|
||||
- If the user says "pode responder" (or similar approval), proceed with posting all drafted responses
|
||||
- For discussions in non-English languages, respond in the same language as the original post
|
||||
- Always reference specific dashboard paths, config options, or code files when explaining existing features
|
||||
- When a discussion reveals a bug, note it separately from feature requests
|
||||
@@ -18,17 +18,35 @@ This workflow fetches all open PRs from the project's GitHub repository, perform
|
||||
|
||||
### 2. Fetch Open Pull Requests
|
||||
|
||||
// turbo
|
||||
// turbo-all
|
||||
|
||||
**⚠️ CRITICAL**: The JSON output of `gh pr list` can be truncated by the tool, silently hiding PRs. You MUST use the two-step approach below to guarantee **all** PRs are fetched.
|
||||
|
||||
**Step 2a — Get PR numbers only** (small output, never truncated):
|
||||
|
||||
- Run: `gh pr list --repo <owner>/<repo> --state open --limit 500 --json number --jq '.[].number'`
|
||||
- This outputs one PR number per line. Count them and confirm total.
|
||||
|
||||
**Step 2b — Fetch full metadata for each PR** (one call per PR):
|
||||
|
||||
- For each PR number from step 2a, run:
|
||||
`gh pr view <NUMBER> --repo <owner>/<repo> --json number,title,author,headRefName,body,createdAt,additions,deletions,files`
|
||||
- You may batch these into parallel calls (up to 4 at a time).
|
||||
|
||||
**Step 2c — Fetch diffs for each PR** (one call per PR, saved to /tmp):
|
||||
|
||||
- For each PR number, run:
|
||||
`gh pr diff <NUMBER> --repo <owner>/<repo> > /tmp/pr<NUMBER>.diff`
|
||||
- Then read each diff file with `view_file`.
|
||||
|
||||
- Run: `gh pr list --repo <owner>/<repo> --state open --limit 500 --json number,title,author,headRefName,body,createdAt,additions,deletions,files`
|
||||
- This fetches **all** open PRs without restriction. Get the diff for each with:
|
||||
`gh pr diff <NUMBER> --repo <owner>/<repo>`
|
||||
- For each open PR, collect:
|
||||
- PR number, title, author, branch, number of commits, date
|
||||
- PR description/body
|
||||
- Files changed (diff)
|
||||
- Existing review comments (from bots or humans)
|
||||
|
||||
**Verification**: Confirm the count of PRs analyzed matches the count from step 2a before proceeding.
|
||||
|
||||
### 3. Analyze Each PR — For each open PR, perform the following analysis:
|
||||
|
||||
#### 3a. Feature Assessment
|
||||
|
||||
+4
-3
@@ -40,6 +40,7 @@ MACHINE_ID_SALT=endpoint-proxy-salt
|
||||
ENABLE_REQUEST_LOGS=false
|
||||
AUTH_COOKIE_SECURE=false
|
||||
REQUIRE_API_KEY=false
|
||||
ALLOW_API_KEY_REVEAL=false
|
||||
|
||||
# Input Sanitizer (FASE-01 — prompt injection & PII protection)
|
||||
# INPUT_SANITIZER_ENABLED=true
|
||||
@@ -127,8 +128,8 @@ GEMINI_CLI_OAUTH_CLIENT_SECRET=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
|
||||
# CODEX_OAUTH_CLIENT_ID=
|
||||
# CODEX_OAUTH_CLIENT_SECRET=
|
||||
# QWEN_OAUTH_CLIENT_ID=
|
||||
# IFLOW_OAUTH_CLIENT_ID=
|
||||
IFLOW_OAUTH_CLIENT_SECRET=4Z3YjXycVsQvyGF1etiNlIBB4RsqSDtW
|
||||
# QODER_OAUTH_CLIENT_ID=
|
||||
QODER_OAUTH_CLIENT_SECRET=4Z3YjXycVsQvyGF1etiNlIBB4RsqSDtW
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Provider User-Agent Overrides (optional — customize per-provider UA headers)
|
||||
@@ -141,7 +142,7 @@ CODEX_USER_AGENT=codex-cli/0.92.0 (Windows 10.0.26100; x64)
|
||||
GITHUB_USER_AGENT=GitHubCopilotChat/0.26.7
|
||||
ANTIGRAVITY_USER_AGENT=antigravity/1.104.0 darwin/arm64
|
||||
KIRO_USER_AGENT=AWS-SDK-JS/3.0.0 kiro-ide/1.0.0
|
||||
IFLOW_USER_AGENT=iFlow-Cli
|
||||
QODER_USER_AGENT=Qoder-Cli
|
||||
QWEN_USER_AGENT=QwenCode/0.12.3 (linux; x64)
|
||||
CURSOR_USER_AGENT=connect-es/1.6.1
|
||||
GEMINI_CLI_USER_AGENT=google-api-nodejs-client/9.15.1
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
name: Bug Report
|
||||
description: Report a bug or unexpected behavior in OmniRoute
|
||||
title: "[BUG] "
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report a bug. Please fill out the sections below so we can reproduce and fix the issue.
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: OmniRoute Version
|
||||
description: "Run `omniroute --version` or check the left sidebar in the dashboard."
|
||||
placeholder: "e.g. 3.0.9"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: install-method
|
||||
attributes:
|
||||
label: Installation Method
|
||||
options:
|
||||
- npm (global)
|
||||
- Docker / Docker Compose
|
||||
- Electron desktop app
|
||||
- Built from source
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating System
|
||||
options:
|
||||
- Windows
|
||||
- macOS
|
||||
- Linux
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: os-version
|
||||
attributes:
|
||||
label: OS Version
|
||||
placeholder: "e.g. Windows 11 23H2, macOS 15.3, Ubuntu 24.04"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: node-version
|
||||
attributes:
|
||||
label: Node.js Version
|
||||
description: "Run `node --version`. Skip if using Docker."
|
||||
placeholder: "e.g. 22.12.0"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: provider
|
||||
attributes:
|
||||
label: Provider(s) Involved
|
||||
description: "Which AI provider(s) does this affect?"
|
||||
placeholder: "e.g. Antigravity, OpenRouter, Ollama, Qwen"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: model
|
||||
attributes:
|
||||
label: Model(s) Involved
|
||||
placeholder: "e.g. claude-sonnet-4-20250514, gpt-4o, gemini-2.5-pro"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: client-tool
|
||||
attributes:
|
||||
label: Client Tool
|
||||
description: "Which tool are you using OmniRoute with?"
|
||||
placeholder: "e.g. Claude Code, Cursor, Roo Code, OpenClaw, Gemini CLI, cURL"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: "A clear description of what the bug is."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: "Step-by-step instructions to reproduce the behavior."
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: "What did you expect to happen?"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: "What actually happened?"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Error Logs / Output
|
||||
description: "Paste any relevant error messages, logs, or terminal output. This will be automatically formatted as code."
|
||||
render: shell
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: "If applicable, add screenshots to help explain the problem. Please also include the text of any error messages above — screenshots alone are not searchable."
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: "Any other context about the problem (e.g. proxy config, number of accounts, network setup)."
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Question / Help
|
||||
url: https://github.com/diegosouzapw/OmniRoute/discussions
|
||||
about: For questions or help with setup, please use GitHub Discussions instead of opening an issue.
|
||||
@@ -0,0 +1,70 @@
|
||||
name: Feature Request
|
||||
description: Suggest a new feature or improvement for OmniRoute
|
||||
title: "[Feature] "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for suggesting a feature! Please describe the problem you're trying to solve and how you'd like it to work.
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem / Use Case
|
||||
description: "What problem does this feature solve? Why do you need it?"
|
||||
placeholder: "I'm trying to ... but currently ..."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: "How would you like this to work?"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
description: "Have you considered any workarounds or alternative approaches?"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
id: area
|
||||
attributes:
|
||||
label: Area
|
||||
description: "Which part of OmniRoute does this relate to?"
|
||||
multiple: true
|
||||
options:
|
||||
- Dashboard / UI
|
||||
- Proxy / Routing
|
||||
- Provider Support
|
||||
- CLI Tools Integration
|
||||
- OAuth / Authentication
|
||||
- Analytics / Usage Tracking
|
||||
- Docker / Deployment
|
||||
- Documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: provider
|
||||
attributes:
|
||||
label: Related Provider(s)
|
||||
description: "If this relates to specific providers, list them."
|
||||
placeholder: "e.g. Antigravity, OpenRouter, Ollama"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: "Any other context, mockups, or references."
|
||||
validations:
|
||||
required: false
|
||||
+16
-16
@@ -18,8 +18,8 @@ jobs:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
@@ -36,8 +36,8 @@ jobs:
|
||||
name: Security Audit
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
@@ -55,8 +55,8 @@ jobs:
|
||||
matrix:
|
||||
node-version: [20, 22]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: npm
|
||||
@@ -74,8 +74,8 @@ jobs:
|
||||
JWT_SECRET: ci-test-secret-with-sufficient-length-for-validation
|
||||
API_KEY_SECRET: ci-test-api-key-secret-long
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: npm
|
||||
@@ -90,8 +90,8 @@ jobs:
|
||||
JWT_SECRET: ci-test-secret-with-sufficient-length-for-validation
|
||||
API_KEY_SECRET: ci-test-api-key-secret-long
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
@@ -109,8 +109,8 @@ jobs:
|
||||
JWT_SECRET: ci-test-secret-with-sufficient-length-for-validation
|
||||
API_KEY_SECRET: ci-test-api-key-secret-long
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
@@ -129,8 +129,8 @@ jobs:
|
||||
INITIAL_PASSWORD: ci-test-password-for-integration
|
||||
DATA_DIR: /tmp/omniroute-ci
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
@@ -145,8 +145,8 @@ jobs:
|
||||
JWT_SECRET: ci-test-secret-with-sufficient-length-for-validation
|
||||
API_KEY_SECRET: ci-test-api-key-secret-long
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
name: Publish to Docker Hub
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
@@ -12,6 +15,7 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
@@ -21,22 +25,29 @@ jobs:
|
||||
IMAGE_NAME: diegosouzapw/omniroute
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/v{0}', inputs.version) || '' }}
|
||||
|
||||
- name: Set up QEMU (for multi-arch builds)
|
||||
uses: docker/setup-qemu-action@v4
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v4
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract version from release tag or input
|
||||
id: version
|
||||
run: |
|
||||
@@ -50,7 +61,7 @@ jobs:
|
||||
echo "Publishing Docker image: $IMAGE_NAME:$VERSION"
|
||||
|
||||
- name: Build and push multi-arch image
|
||||
uses: docker/build-push-action@v7
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
target: runner-base
|
||||
@@ -59,6 +70,8 @@ jobs:
|
||||
tags: |
|
||||
${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}
|
||||
${{ env.IMAGE_NAME }}:latest
|
||||
ghcr.io/diegosouzapw/omniroute:${{ steps.version.outputs.version }}
|
||||
ghcr.io/diegosouzapw/omniroute:latest
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
no-cache: false
|
||||
@@ -70,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@v5
|
||||
uses: peter-evans/dockerhub-description@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
@@ -13,6 +13,8 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
@@ -22,7 +24,7 @@ jobs:
|
||||
version: ${{ steps.validate.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -70,16 +72,16 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v5
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
|
||||
@@ -146,7 +148,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: electron-${{ matrix.platform }}
|
||||
path: release-assets/
|
||||
@@ -157,12 +159,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: release-assets
|
||||
merge-multiple: true
|
||||
@@ -201,3 +203,13 @@ jobs:
|
||||
release-assets/*.source.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
publish-npm:
|
||||
name: Publish to npm
|
||||
needs: [validate, release]
|
||||
uses: ./.github/workflows/npm-publish.yml
|
||||
with:
|
||||
version: ${{ needs.validate.outputs.version }}
|
||||
tag: latest
|
||||
secrets:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
@@ -6,13 +6,36 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Version tag to publish (e.g. 2.6.0)"
|
||||
description: "Version to publish (e.g. 2.9.5 or 3.0.0-rc.15)"
|
||||
required: true
|
||||
type: string
|
||||
tag:
|
||||
description: "npm dist-tag (latest / next)"
|
||||
required: false
|
||||
default: "latest"
|
||||
type: choice
|
||||
options:
|
||||
- latest
|
||||
- next
|
||||
workflow_call:
|
||||
inputs:
|
||||
version:
|
||||
description: "Version to publish (without v prefix)"
|
||||
required: true
|
||||
type: string
|
||||
tag:
|
||||
description: "npm dist-tag (latest / next)"
|
||||
required: false
|
||||
default: "latest"
|
||||
type: string
|
||||
secrets:
|
||||
NPM_TOKEN:
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
@@ -20,10 +43,10 @@ jobs:
|
||||
environment: NPM_TOKEN
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
registry-url: https://registry.npmjs.org
|
||||
@@ -31,16 +54,36 @@ jobs:
|
||||
- name: Install dependencies (skip scripts to avoid heavy build)
|
||||
run: npm install --ignore-scripts --no-audit --no-fund
|
||||
|
||||
- name: Sync version from release tag or input
|
||||
- name: Resolve version and dist-tag
|
||||
id: resolve
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
VERSION="${{ inputs.version }}"
|
||||
else
|
||||
VERSION="${GITHUB_REF_NAME}"
|
||||
VERSION="${VERSION#v}"
|
||||
VERSION="${{ inputs.version }}"
|
||||
TAG="${{ inputs.tag }}"
|
||||
|
||||
if [ -z "$VERSION" ]; then
|
||||
if [ "${{ github.event_name }}" = "release" ]; then
|
||||
VERSION="${GITHUB_REF_NAME}"
|
||||
fi
|
||||
fi
|
||||
npm version "$VERSION" --no-git-tag-version --allow-same-version
|
||||
echo "Publishing version: $VERSION"
|
||||
|
||||
# Strip v prefix if present
|
||||
VERSION="${VERSION#v}"
|
||||
|
||||
# Default dist-tag logic
|
||||
if [ -z "$TAG" ]; then
|
||||
if [[ "$VERSION" == *-* ]]; then
|
||||
TAG="next"
|
||||
else
|
||||
TAG="latest"
|
||||
fi
|
||||
fi
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||
echo "📦 Publishing omniroute@$VERSION with tag=$TAG"
|
||||
|
||||
- name: Sync package.json version
|
||||
run: |
|
||||
npm version "${{ steps.resolve.outputs.version }}" --no-git-tag-version --allow-same-version
|
||||
|
||||
- name: Build CLI bundle (standalone app)
|
||||
env:
|
||||
@@ -49,12 +92,36 @@ jobs:
|
||||
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
VERSION="${{ steps.resolve.outputs.version }}"
|
||||
TAG="${{ steps.resolve.outputs.tag }}"
|
||||
# Check if this version is already published — skip instead of failing with E403
|
||||
if npm view "omniroute@${VERSION}" version --silent 2>/dev/null | grep -q "^${VERSION}$"; then
|
||||
echo "️⚠️ Version ${VERSION} is already published on npm — skipping."
|
||||
echo "⚠️ Version ${VERSION} is already published on npm — skipping."
|
||||
exit 0
|
||||
fi
|
||||
npm publish --access public
|
||||
if [ "$TAG" = "latest" ]; then
|
||||
npm publish --access public
|
||||
else
|
||||
npm publish --access public --tag "$TAG"
|
||||
fi
|
||||
echo "✅ Published omniroute@$VERSION (tag: $TAG)"
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Publish to GitHub Packages
|
||||
run: |
|
||||
VERSION="${{ steps.resolve.outputs.version }}"
|
||||
TAG="${{ steps.resolve.outputs.tag }}"
|
||||
|
||||
echo "Configuring for GitHub Packages..."
|
||||
echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" > .npmrc
|
||||
npm pkg set name="@diegosouzapw/omniroute"
|
||||
|
||||
if [ "$TAG" = "latest" ]; then
|
||||
npm publish --registry=https://npm.pkg.github.com || echo "⚠️ Version ${VERSION} might already be published on GitHub."
|
||||
else
|
||||
npm publish --registry=https://npm.pkg.github.com --tag "$TAG" || echo "⚠️ Version ${VERSION} might already be published on GitHub."
|
||||
fi
|
||||
echo "✅ Action finished for GitHub Packages"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
name: Sync Upstream
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run every 6 hours
|
||||
- cron: '0 */6 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: Sync with upstream
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Fetch upstream
|
||||
run: |
|
||||
git remote add upstream https://github.com/diegosouzapw/OmniRoute.git || true
|
||||
git fetch upstream
|
||||
git fetch origin
|
||||
|
||||
- name: Sync main branch
|
||||
run: |
|
||||
git checkout main
|
||||
git merge upstream/main --no-edit || {
|
||||
echo "Merge conflict detected. Manual intervention required."
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: Push changes
|
||||
run: git push https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/tombii/OmniRoute.git main
|
||||
@@ -89,6 +89,7 @@ docs/*
|
||||
!docs/MCP-SERVER.md
|
||||
!docs/CLI-TOOLS.md
|
||||
|
||||
|
||||
# open-sse tests
|
||||
open-sse/test/*
|
||||
|
||||
@@ -111,6 +112,7 @@ app.log
|
||||
|
||||
# Backup directories
|
||||
app.__qa_backup/
|
||||
.app-build-backup-*/
|
||||
|
||||
# Production standalone build (created by scripts/prepublish.mjs)
|
||||
# Conflicts with Next.js App Router detection in dev (root app/ shadows src/app/)
|
||||
@@ -130,3 +132,6 @@ vscode-extension/
|
||||
*.sqlite-shm
|
||||
*.sqlite-wal
|
||||
*.sqlite-journal
|
||||
|
||||
# Compiled npm-package build artifact (not source, should not be in git)
|
||||
/app
|
||||
|
||||
@@ -47,3 +47,12 @@ AGENTS.md
|
||||
# Build artifacts (pre-built goes inside app/)
|
||||
.next/
|
||||
node_modules/
|
||||
|
||||
# Ignore large binary files and other build directories
|
||||
*.tgz
|
||||
*.AppImage
|
||||
*.deb
|
||||
*.rpm
|
||||
electron/
|
||||
app/electron/
|
||||
app/vscode-extension/
|
||||
|
||||
@@ -49,19 +49,22 @@ but the real logic lives in `src/lib/db/`.
|
||||
|
||||
Translation between provider formats: `open-sse/translator/`
|
||||
|
||||
**Upstream model extra headers** (`compatByProtocol` / custom models): merged in executors after default auth; **same header name replaces** the executor value (e.g. custom `Authorization` overrides Bearer). In `open-sse/handlers/chatCore.ts`, the primary request merges headers for **both** the client model id and `resolveModelAlias(clientModel)` (resolved id wins on key conflicts). **T5 intra-family fallback** recomputes headers using only the fallback model id and `resolveModelAlias(fallback)` so sibling models do not inherit another model’s headers. Forbidden header names live in `src/shared/constants/upstreamHeaders.ts` — keep sanitize (`models.ts`), Zod (`schemas.ts`), and unit tests aligned when editing that list.
|
||||
|
||||
### MCP Server (`open-sse/mcp-server/`)
|
||||
|
||||
16 tools for AI agent control via **3 transport modes**:
|
||||
|
||||
- **stdio** — Local IDE integration (Claude Desktop, Cursor, VS Code)
|
||||
- **SSE** — Remote Server-Sent Events at `/api/mcp/sse`
|
||||
- **Streamable HTTP** — Modern bidirectional HTTP at `/api/mcp/stream`
|
||||
|
||||
HTTP transports run in-process via `httpTransport.ts` singleton using `WebStandardStreamableHTTPServerTransport`.
|
||||
|
||||
| Category | Tools |
|
||||
| ---------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Essential | `get_health`, `list_combos`, `get_combo_metrics`, `switch_combo`, `check_quota`, `route_request`, `cost_report`, `list_models_catalog` |
|
||||
| Advanced | `simulate_route`, `set_budget_guard`, `set_resilience_profile`, `test_combo`, `get_provider_metrics`, `best_combo_for_task`, `explain_route`, `get_session_snapshot` |
|
||||
| Category | Tools |
|
||||
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Essential | `get_health`, `list_combos`, `get_combo_metrics`, `switch_combo`, `check_quota`, `route_request`, `cost_report`, `list_models_catalog` |
|
||||
| Advanced | `simulate_route`, `set_budget_guard`, `set_resilience_profile`, `test_combo`, `get_provider_metrics`, `best_combo_for_task`, `explain_route`, `get_session_snapshot` |
|
||||
|
||||
- Scoped authorization (9 scopes), audit logging, Zod schemas
|
||||
- IDE configs for Claude Desktop, Cursor, VS Code Copilot
|
||||
@@ -79,25 +82,26 @@ Agent-to-Agent v0.3 protocol:
|
||||
### Auto-Combo Engine (`open-sse/services/autoCombo/`)
|
||||
|
||||
Self-healing routing optimization:
|
||||
|
||||
- 6-factor scoring, 4 mode packs, bandit exploration
|
||||
- Progressive cooldown, probe-based re-admission
|
||||
|
||||
### Dashboard (`src/app/(dashboard)/`)
|
||||
|
||||
| Page | Description |
|
||||
| ---------------------------- | -------------------------------------------------------------- |
|
||||
| `/dashboard` | Home with quick start, provider overview |
|
||||
| `/dashboard/endpoint` | **Endpoints** (tabbed): Endpoint Proxy, MCP, A2A, API Endpoints |
|
||||
| `/dashboard/providers` | Provider management and connections |
|
||||
| `/dashboard/combos` | Combo configurations with routing strategies |
|
||||
| `/dashboard/logs` | Request, Proxy, Audit, Console logs (tabbed) |
|
||||
| `/dashboard/analytics` | Usage analytics and evaluations |
|
||||
| `/dashboard/costs` | Cost tracking and breakdown |
|
||||
| `/dashboard/health` | Uptime, circuit breakers, latency |
|
||||
| `/dashboard/cli-tools` | CLI tool integrations (Claude, Codex, Antigravity, etc.) |
|
||||
| `/dashboard/media` | Image, Video, Music generation playground |
|
||||
| `/dashboard/settings` | System settings with multiple tabs |
|
||||
| `/dashboard/api-manager` | API key management with model permissions |
|
||||
| Page | Description |
|
||||
| ------------------------ | --------------------------------------------------------------- |
|
||||
| `/dashboard` | Home with quick start, provider overview |
|
||||
| `/dashboard/endpoint` | **Endpoints** (tabbed): Endpoint Proxy, MCP, A2A, API Endpoints |
|
||||
| `/dashboard/providers` | Provider management and connections |
|
||||
| `/dashboard/combos` | Combo configurations with routing strategies |
|
||||
| `/dashboard/logs` | Request, Proxy, Audit, Console logs (tabbed) |
|
||||
| `/dashboard/analytics` | Usage analytics and evaluations |
|
||||
| `/dashboard/costs` | Cost tracking and breakdown |
|
||||
| `/dashboard/health` | Uptime, circuit breakers, latency |
|
||||
| `/dashboard/cli-tools` | CLI tool integrations (Claude, Codex, Antigravity, etc.) |
|
||||
| `/dashboard/media` | Image, Video, Music generation playground |
|
||||
| `/dashboard/settings` | System settings with multiple tabs |
|
||||
| `/dashboard/api-manager` | API key management with model permissions |
|
||||
|
||||
### OAuth & Tokens (`src/lib/oauth/`)
|
||||
|
||||
|
||||
+1340
-7
File diff suppressed because it is too large
Load Diff
+8
-1
@@ -114,6 +114,7 @@ npm run test:fixes # Fix verification tests
|
||||
|
||||
# With coverage
|
||||
npm run test:coverage
|
||||
npm run coverage:report
|
||||
|
||||
# E2E tests (requires Playwright)
|
||||
npm run test:e2e
|
||||
@@ -123,7 +124,13 @@ npm run lint
|
||||
npm run check
|
||||
```
|
||||
|
||||
Current test status: **368+ unit tests** covering:
|
||||
Coverage notes:
|
||||
|
||||
- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
|
||||
- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
|
||||
- `npm run test:coverage:legacy` preserves the older metric for historical comparison
|
||||
|
||||
Current test status: **968+ unit tests** covering:
|
||||
|
||||
- Provider translators and format conversion
|
||||
- Rate limiting, circuit breaker, and resilience
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
# Test Coverage Plan
|
||||
|
||||
Last updated: 2026-03-28
|
||||
|
||||
## Baseline
|
||||
|
||||
There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
|
||||
|
||||
| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
|
||||
| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
|
||||
| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
|
||||
| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
|
||||
| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
|
||||
|
||||
The recommended baseline is the number to optimize against.
|
||||
|
||||
## Rules
|
||||
|
||||
- Coverage targets apply to source files, not to `tests/**`.
|
||||
- `open-sse/**` is part of the product and must remain in scope.
|
||||
- New code should not reduce coverage in touched areas.
|
||||
- Prefer testing behavior and branch outcomes over implementation details.
|
||||
- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
|
||||
|
||||
## Current command set
|
||||
|
||||
- `npm run test:coverage`
|
||||
- Main source coverage gate for the unit test suite
|
||||
- Generates `text-summary`, `html`, `json-summary`, and `lcov`
|
||||
- `npm run coverage:report`
|
||||
- Detailed file-by-file report from the latest run
|
||||
- `npm run test:coverage:legacy`
|
||||
- Historical comparison only
|
||||
|
||||
## Milestones
|
||||
|
||||
| Phase | Target | Focus |
|
||||
| ------- | ---------------------: | ------------------------------------------------- |
|
||||
| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
|
||||
| Phase 2 | 65% statements / lines | DB and route foundations |
|
||||
| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
|
||||
| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
|
||||
| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
|
||||
| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
|
||||
| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
|
||||
|
||||
Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
|
||||
|
||||
## Priority hotspots
|
||||
|
||||
These files or areas offer the best return for the next phases:
|
||||
|
||||
1. `open-sse/handlers`
|
||||
- `chatCore.ts` at 7.57%
|
||||
- Overall directory at 29.07%
|
||||
2. `open-sse/translator/request`
|
||||
- Overall directory at 36.39%
|
||||
- Many translators are still near single-digit coverage
|
||||
3. `open-sse/translator/response`
|
||||
- Overall directory at 8.07%
|
||||
4. `open-sse/executors`
|
||||
- Overall directory at 36.62%
|
||||
5. `src/lib/db`
|
||||
- `models.ts` at 20.66%
|
||||
- `registeredKeys.ts` at 34.46%
|
||||
- `modelComboMappings.ts` at 36.25%
|
||||
- `settings.ts` at 46.40%
|
||||
- `webhooks.ts` at 33.33%
|
||||
6. `src/lib/usage`
|
||||
- `usageHistory.ts` at 21.12%
|
||||
- `usageStats.ts` at 9.56%
|
||||
- `costCalculator.ts` at 30.00%
|
||||
7. `src/lib/providers`
|
||||
- `validation.ts` at 41.16%
|
||||
8. Low-risk utility and API files for early gains
|
||||
- `src/shared/utils/upstreamError.ts`
|
||||
- `src/shared/utils/apiAuth.ts`
|
||||
- `src/lib/api/errorResponse.ts`
|
||||
- `src/app/api/settings/require-login/route.ts`
|
||||
- `src/app/api/providers/[id]/models/route.ts`
|
||||
|
||||
## Execution checklist
|
||||
|
||||
### Phase 1: 56.95% -> 60%
|
||||
|
||||
- [x] Fix coverage metric so it reflects source code instead of test files
|
||||
- [x] Keep a legacy coverage script for comparison
|
||||
- [x] Record the baseline and hotspots in-repo
|
||||
- [ ] Add focused tests for low-risk utilities:
|
||||
- `src/shared/utils/upstreamError.ts`
|
||||
- `src/shared/utils/fetchTimeout.ts`
|
||||
- `src/lib/api/errorResponse.ts`
|
||||
- `src/shared/utils/apiAuth.ts`
|
||||
- `src/lib/display/names.ts`
|
||||
- [ ] Add route tests for:
|
||||
- `src/app/api/settings/require-login/route.ts`
|
||||
- `src/app/api/providers/[id]/models/route.ts`
|
||||
|
||||
### Phase 2: 60% -> 65%
|
||||
|
||||
- [ ] Add DB-backed tests for:
|
||||
- `src/lib/db/modelComboMappings.ts`
|
||||
- `src/lib/db/settings.ts`
|
||||
- `src/lib/db/registeredKeys.ts`
|
||||
- [ ] Cover branch behavior in:
|
||||
- `src/lib/providers/validation.ts`
|
||||
- `src/app/api/v1/embeddings/route.ts`
|
||||
- `src/app/api/v1/moderations/route.ts`
|
||||
|
||||
### Phase 3: 65% -> 70%
|
||||
|
||||
- [ ] Add usage analytics tests for:
|
||||
- `src/lib/usage/usageHistory.ts`
|
||||
- `src/lib/usage/usageStats.ts`
|
||||
- `src/lib/usage/costCalculator.ts`
|
||||
- [ ] Expand route coverage for proxy management and settings branches
|
||||
|
||||
### Phase 4: 70% -> 75%
|
||||
|
||||
- [ ] Cover translator helpers and central translation paths:
|
||||
- `open-sse/translator/index.ts`
|
||||
- `open-sse/translator/helpers/*`
|
||||
- `open-sse/translator/request/*`
|
||||
- `open-sse/translator/response/*`
|
||||
|
||||
### Phase 5: 75% -> 80%
|
||||
|
||||
- [ ] Add handler-level tests for:
|
||||
- `open-sse/handlers/chatCore.ts`
|
||||
- `open-sse/handlers/responsesHandler.js`
|
||||
- `open-sse/handlers/imageGeneration.js`
|
||||
- `open-sse/handlers/embeddings.js`
|
||||
- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
|
||||
|
||||
### Phase 6: 80% -> 85%
|
||||
|
||||
- [ ] Merge more edge-case suites into the main coverage path
|
||||
- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
|
||||
- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
|
||||
|
||||
### Phase 7: 85% -> 90%
|
||||
|
||||
- [ ] Treat the remaining low-coverage files as blockers
|
||||
- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
|
||||
- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
|
||||
|
||||
## Ratchet policy
|
||||
|
||||
Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
|
||||
|
||||
Recommended ratchet sequence:
|
||||
|
||||
1. 55/60/55
|
||||
2. 60/62/58
|
||||
3. 65/64/62
|
||||
4. 70/66/66
|
||||
5. 75/70/72
|
||||
6. 80/75/78
|
||||
7. 85/80/84
|
||||
8. 90/85/88
|
||||
|
||||
Order is `statements-lines / branches / functions`.
|
||||
|
||||
## Known gap
|
||||
|
||||
The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
|
||||
+9
-2
@@ -1,13 +1,17 @@
|
||||
FROM node:22-bookworm-slim AS builder
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends libsecret-1-0 ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY package*.json ./
|
||||
COPY scripts/postinstall.mjs ./scripts/postinstall.mjs
|
||||
COPY scripts/native-binary-compat.mjs ./scripts/native-binary-compat.mjs
|
||||
RUN if [ -f package-lock.json ]; then npm ci --no-audit --no-fund; else npm install --no-audit --no-fund; fi
|
||||
|
||||
COPY . ./
|
||||
RUN mkdir -p /app/data && npm run build
|
||||
RUN mkdir -p /app/data && npm run build -- --webpack
|
||||
|
||||
FROM node:22-bookworm-slim AS runner-base
|
||||
WORKDIR /app
|
||||
@@ -25,6 +29,9 @@ ENV NODE_OPTIONS="--max-old-space-size=256"
|
||||
|
||||
# Data directory inside Docker — must match the volume mount in docker-compose.yml
|
||||
ENV DATA_DIR=/app/data
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends libsecret-1-0 ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
RUN mkdir -p /app/data
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
@@ -53,7 +60,7 @@ FROM runner-base AS runner-cli
|
||||
|
||||
# Install system dependencies required by openclaw (git+ssh references).
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends git ca-certificates \
|
||||
&& apt-get install -y --no-install-recommends git ca-certificates docker.io docker-compose \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& git config --system url."https://github.com/".insteadOf "ssh://git@github.com/"
|
||||
|
||||
|
||||
+2076
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2084
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+1965
File diff suppressed because it is too large
Load Diff
+2076
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
|
||||
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
|
||||
|
||||
_Your universal API proxy — one endpoint, 44+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
|
||||
_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
|
||||
|
||||
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
|
||||
|
||||
@@ -11,7 +11,9 @@ _Your universal API proxy — one endpoint, 44+ providers, zero downtime. Now wi
|
||||
<div align="center">
|
||||
|
||||
[](https://www.npmjs.com/package/omniroute)
|
||||
[](https://www.npmjs.com/package/omniroute)
|
||||
[](https://hub.docker.com/r/diegosouzapw/omniroute)
|
||||
[](https://hub.docker.com/r/diegosouzapw/omniroute)
|
||||
[](https://github.com/diegosouzapw/OmniRoute/blob/main/LICENSE)
|
||||
[](https://omniroute.online)
|
||||
[](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
|
||||
@@ -24,6 +26,28 @@ _Your universal API proxy — one endpoint, 44+ providers, zero downtime. Now wi
|
||||
|
||||
---
|
||||
|
||||
## 🆕 What's New in v3.0.0
|
||||
|
||||
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
|
||||
|
||||
| Area | Change |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 🔒 **CodeQL Security** | Fixed 10+ CodeQL alerts: polynomial-redos, insecure-randomness, shell-injection remediation |
|
||||
| ✅ **Route Validation** | All 176 API routes now validated with Zod schemas + `validateBody()` — CI `check:route-validation:t06` passes |
|
||||
| 🐛 **omniModel Tag Leak** | Internal `<omniModel>` tags no longer leak to clients in SSE streaming responses (#585) |
|
||||
| 🔑 **Registered Keys API** | Auto-provision API keys via `POST /api/v1/registered-keys` with per-provider/account quota enforcement, idempotency, SHA-256 storage, and optional GitHub issue reporting |
|
||||
| 🎨 **Provider Icons** | 130+ provider logos via `@lobehub/icons` (SVG) with PNG → generic fallback chain |
|
||||
| 🔄 **Model Auto-Sync** | 24h scheduler and manual UI toggle to sync model lists for built-in and custom OpenAI-compatible providers |
|
||||
| 🌐 **OpenCode Zen/Go** | Two new providers from @kang-heewon via PR #530: free tier + subscription tier via `OpencodeExecutor` |
|
||||
| 🐛 **Gemini CLI OAuth** | Actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker (was cryptic Google error) |
|
||||
| 🐛 **OpenCode config** | `saveOpenCodeConfig()` now correctly writes TOML to `XDG_CONFIG_HOME` |
|
||||
| 🐛 **Pinned model override** | `body.model` correctly set to `pinnedModel` on context-cache protection |
|
||||
| 🐛 **Codex/Claude loop** | `tool_result` blocks now converted to text to stop infinite loops |
|
||||
| 🐛 **Login redirect** | Login no longer freezes after skipping password setup |
|
||||
| 🐛 **Windows paths** | MSYS2/Git-Bash paths (`/c/...`) normalized to `C:\...` automatically |
|
||||
|
||||
---
|
||||
|
||||
## 🖼️ Main Dashboard
|
||||
|
||||
<div align="center">
|
||||
@@ -175,7 +199,7 @@ When opening an issue, please run the system-info command and attach the generat
|
||||
npm run system-info
|
||||
```
|
||||
|
||||
This generates a `system-info.txt` with your Node.js version, OmniRoute version, OS details, installed CLI tools (iflow, gemini, claude, codex, antigravity, droid, etc.), Docker/PM2 status, and system packages — everything we need to reproduce your issue quickly. Attach the file directly to your GitHub issue.
|
||||
This generates a `system-info.txt` with your Node.js version, OmniRoute version, OS details, installed CLI tools (qoder, gemini, claude, codex, antigravity, droid, etc.), Docker/PM2 status, and system packages — everything we need to reproduce your issue quickly. Attach the file directly to your GitHub issue.
|
||||
|
||||
---
|
||||
|
||||
@@ -201,7 +225,7 @@ This generates a `system-info.txt` with your Node.js version, OmniRoute version,
|
||||
│ ↓ budget limit
|
||||
├─→ [Tier 3: CHEAP] GLM ($0.6/1M), MiniMax ($0.2/1M)
|
||||
│ ↓ budget limit
|
||||
└─→ [Tier 4: FREE] iFlow, Qwen, Kiro (unlimited)
|
||||
└─→ [Tier 4: FREE] Qoder, Qwen, Kiro (unlimited)
|
||||
|
||||
Result: Never stop coding, minimal cost
|
||||
```
|
||||
@@ -234,7 +258,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 44+ providers
|
||||
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ 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
|
||||
@@ -268,7 +292,7 @@ Not everyone can pay $20–200/month for AI subscriptions. Students, devs from e
|
||||
|
||||
**How OmniRoute solves it:**
|
||||
|
||||
- **Free Tier Providers Built-in** — Native support for 100% free providers: iFlow (5 unlimited models via OAuth: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2), Qwen (4 unlimited models: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model), Kiro (Claude + AWS Builder ID for free), Gemini CLI (180K tokens/month free)
|
||||
- **Free Tier Providers Built-in** — Native support for 100% free providers: Qoder (5 unlimited models via OAuth: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2), Qwen (4 unlimited models: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model), Kiro (Claude + AWS Builder ID for free), Gemini CLI (180K tokens/month free)
|
||||
- **Ollama Cloud** — Cloud-hosted Ollama models at `api.ollama.com` with free "Light usage" tier; use `ollamacloud/<model>` prefix
|
||||
- **Free-Only Combos** — Chain `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = $0/month with zero downtime
|
||||
- **NVIDIA NIM Free Access** — ~40 RPM dev-forever free access to 70+ models at build.nvidia.com (transitioning from credits to pure rate limits)
|
||||
@@ -320,7 +344,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 44+ providers
|
||||
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
|
||||
|
||||
</details>
|
||||
|
||||
@@ -332,7 +356,7 @@ Claude Code, Codex, Gemini CLI, Copilot — all use OAuth 2.0 with expiring toke
|
||||
**How OmniRoute solves it:**
|
||||
|
||||
- **Auto Token Refresh** — OAuth tokens refresh in background before expiration
|
||||
- **OAuth 2.0 (PKCE) Built-in** — Automatic flow for Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
|
||||
- **OAuth 2.0 (PKCE) Built-in** — Automatic flow for Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, Qoder
|
||||
- **Multi-Account OAuth** — Multiple accounts per provider via JWT/ID token extraction
|
||||
- **OAuth LAN/Remote Fix** — Private IP detection for `redirect_uri` + manual URL mode for remote servers
|
||||
- **OAuth Behind Nginx** — Uses `window.location.origin` for reverse proxy compatibility
|
||||
@@ -709,14 +733,14 @@ Outcome: deep fallback depth for deadline-critical workloads
|
||||
| Step | Action | Providers Unlocked |
|
||||
| ---- | -------------------------------------------------- | ------------------------------------------------------------------ |
|
||||
| 1 | Connect **Kiro** (AWS Builder ID OAuth) | Claude Sonnet 4.5, Haiku 4.5 — **unlimited** |
|
||||
| 2 | Connect **iFlow** (Google OAuth) | kimi-k2-thinking, qwen3-coder-plus, deepseek-r1... — **unlimited** |
|
||||
| 2 | Connect **Qoder** (Google OAuth) | kimi-k2-thinking, qwen3-coder-plus, deepseek-r1... — **unlimited** |
|
||||
| 3 | Connect **Qwen** (Device Code) | qwen3-coder-plus, qwen3-coder-flash... — **unlimited** |
|
||||
| 4 | Connect **Gemini CLI** (Google OAuth) | gemini-3-flash, gemini-2.5-pro — **180K/mo free** |
|
||||
| 5 | `/dashboard/combos` → **Free Stack ($0)** template | Round-robin all free providers automatically |
|
||||
|
||||
**Point any IDE/CLI to:** `http://localhost:20128/v1` · API Key: `any-string` · Done.
|
||||
|
||||
> **Optional extra coverage (also free):** Groq API key (30 RPM free), NVIDIA NIM (40 RPM free, 70+ models), Cerebras (1M tok/day).
|
||||
> **Optional extra coverage (also free):** Groq API key (30 RPM free), NVIDIA NIM (40 RPM free, 70+ models), Cerebras (1M tok/day), LongCat API key (50M tokens/day!), Cloudflare Workers AI (10K Neurons/day, 50+ models).
|
||||
|
||||
## ⚡ Quick Start
|
||||
|
||||
@@ -852,6 +876,44 @@ docker compose --profile base up -d
|
||||
docker compose --profile cli up -d
|
||||
```
|
||||
|
||||
Dashboard support for Docker deployments now includes a one-click **Cloudflare Quick Tunnel** on `Dashboard → Endpoints`. The first enable downloads `cloudflared` only when needed, starts a temporary tunnel to your current `/v1` endpoint, and shows the generated `https://*.trycloudflare.com/v1` URL directly below your normal public URL.
|
||||
|
||||
Notes:
|
||||
|
||||
- Quick Tunnel URLs are temporary and change after every restart.
|
||||
- Managed install currently supports Linux, macOS, and Windows on `x64` / `arm64`.
|
||||
- Docker images bundle system CA roots and pass them to managed `cloudflared`, which avoids TLS trust failures when the tunnel bootstraps inside the container.
|
||||
- Set `CLOUDFLARED_BIN=/absolute/path/to/cloudflared` if you want OmniRoute to use an existing binary instead of downloading one.
|
||||
|
||||
**Using Docker Compose with Caddy (HTTPS Auto-TLS):**
|
||||
|
||||
OmniRoute can be securely exposed using Caddy's automatic SSL provisioning. Ensure your domain's DNS A record points to your server's IP.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
omniroute:
|
||||
image: diegosouzapw/omniroute:latest
|
||||
container_name: omniroute
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- omniroute-data:/app/data
|
||||
environment:
|
||||
- PORT=20128
|
||||
- NEXT_PUBLIC_BASE_URL=https://your-domain.com
|
||||
|
||||
caddy:
|
||||
image: caddy:latest
|
||||
container_name: caddy
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
command: caddy reverse-proxy --from https://your-domain.com --to http://omniroute:20128
|
||||
|
||||
volumes:
|
||||
omniroute-data:
|
||||
```
|
||||
|
||||
| Image | Tag | Size | Description |
|
||||
| ------------------------ | -------- | ------ | --------------------- |
|
||||
| `diegosouzapw/omniroute` | `latest` | ~250MB | Latest stable release |
|
||||
@@ -918,21 +980,31 @@ When minimized, OmniRoute lives in your system tray with quick actions:
|
||||
| | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option |
|
||||
| | Kimi K2.5 (Moonshot API) 🆕 | Pay-per-use | None | Direct Moonshot API access |
|
||||
| | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost |
|
||||
| **🆓 FREE** | iFlow | **$0** | Unlimited | 5 models unlimited |
|
||||
| **🆓 FREE** | Qoder | **$0** | Unlimited | 5 models unlimited |
|
||||
| | Qwen | **$0** | Unlimited | 4 models unlimited |
|
||||
| | Kiro | **$0** | Unlimited | Claude Sonnet/Haiku (AWS Builder) |
|
||||
| | LongCat Flash-Lite 🆕 | **$0** (50M tok/day 🔥) | 1 RPS | Largest free quota on Earth |
|
||||
| | Pollinations AI 🆕 | **$0** (no key needed) | 1 req/15s | GPT-5, Claude, DeepSeek, Llama 4 |
|
||||
| | Cloudflare Workers AI 🆕 | **$0** (10K Neurons/day) | ~150 resp/day | 50+ models, global edge |
|
||||
| | Scaleway AI 🆕 | **$0** (1M tokens total) | Rate limited | EU/GDPR, Qwen3 235B, Llama 70B |
|
||||
|
||||
> 🆕 **New models added (Mar 2026):** Grok-4 Fast family at $0.20/$0.50/M (benchmarked at 1143ms — 30% faster than Gemini 2.5 Flash), GLM-5 via Z.AI with 128K output, MiniMax M2.5 reasoning, DeepSeek V3.2 updated pricing, Kimi K2.5 via Moonshot direct API.
|
||||
|
||||
**💡 $0 Combo Stack — The Complete Free Setup:**
|
||||
|
||||
```
|
||||
Gemini CLI (180K/mo free)
|
||||
→ iFlow (unlimited: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1)
|
||||
→ Kiro (Claude Sonnet 4.5 + Haiku — unlimited, via AWS Builder ID)
|
||||
→ Qwen (4 models — unlimited)
|
||||
→ Groq (14.4K req/day — ultra-fast)
|
||||
→ NVIDIA NIM (70+ models — 40 RPM forever)
|
||||
# 🆓 Ultimate Free Stack 2026 — 11 Providers, $0 Forever
|
||||
Kiro (kr/) → Claude Sonnet/Haiku UNLIMITED
|
||||
Qoder (if/) → kimi-k2-thinking, qwen3-coder-plus, deepseek-r1 UNLIMITED
|
||||
LongCat Lite (lc/) → LongCat-Flash-Lite — 50M tokens/day 🔥
|
||||
Pollinations (pol/) → GPT-5, Claude, DeepSeek, Llama 4 — no key needed
|
||||
Qwen (qw/) → qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next UNLIMITED
|
||||
Gemini (gemini/) → Gemini 2.5 Flash — 1,500 req/day free API key
|
||||
Cloudflare AI (cf/) → Llama 70B, Gemma 3, Mistral — 10K Neurons/day
|
||||
Scaleway (scw/) → Qwen3 235B, Llama 70B — 1M free tokens (EU)
|
||||
Groq (groq/) → Llama/Gemma ultra-fast — 14.4K req/day
|
||||
NVIDIA NIM (nvidia/) → 70+ open models — 40 RPM forever
|
||||
Cerebras (cerebras/) → Llama/Qwen world-fastest — 1M tok/day
|
||||
```
|
||||
|
||||
**Zero cost. Never stops coding.** Configure this as one OmniRoute combo and all fallbacks happen automatically — no manual switching ever.
|
||||
@@ -953,7 +1025,7 @@ Gemini CLI (180K/mo free)
|
||||
| `claude-haiku-4.5` | `kr/` | **Unlimited** | No reported daily cap |
|
||||
| `claude-opus-4.6` | `kr/` | **Unlimited** | Latest Opus via Kiro |
|
||||
|
||||
### 🟢 IFLOW MODELS (Free OAuth — No Credit Card)
|
||||
### 🟢 QODER MODELS (Free OAuth — No Credit Card)
|
||||
|
||||
| Model | Prefix | Limit | Rate Limit |
|
||||
| ------------------ | ------ | ------------- | --------------- |
|
||||
@@ -1003,19 +1075,66 @@ Available free: `llama-3.3-70b`, `llama-3.1-8b`, `deepseek-r1-distill-llama-70b`
|
||||
|
||||
Available free: `llama-3.3-70b-versatile`, `gemma2-9b-it`, `mixtral-8x7b`, `whisper-large-v3`
|
||||
|
||||
> **💡 The Ultimate Free Stack:**
|
||||
### 🔴 LONGCAT AI (Free API Key — longcat.chat) 🆕
|
||||
|
||||
| Model | Prefix | Daily Free Quota | Notes |
|
||||
| ----------------------------- | ------ | ----------------- | ----------------------- |
|
||||
| `LongCat-Flash-Lite` | `lc/` | **50M tokens** 💥 | Largest free quota ever |
|
||||
| `LongCat-Flash-Chat` | `lc/` | 500K tokens | Multi-turn chat |
|
||||
| `LongCat-Flash-Thinking` | `lc/` | 500K tokens | Reasoning / CoT |
|
||||
| `LongCat-Flash-Thinking-2601` | `lc/` | 500K tokens | Jan 2026 version |
|
||||
| `LongCat-Flash-Omni-2603` | `lc/` | 500K tokens | Multimodal |
|
||||
|
||||
> 100% free while in public beta. Sign up at [longcat.chat](https://longcat.chat) with email or phone. Resets daily 00:00 UTC.
|
||||
|
||||
### 🟢 POLLINATIONS AI (No API Key Required) 🆕
|
||||
|
||||
| Model | Prefix | Rate Limit | Provider Behind |
|
||||
| ---------- | ------ | ---------- | ------------------ |
|
||||
| `openai` | `pol/` | 1 req/15s | GPT-5 |
|
||||
| `claude` | `pol/` | 1 req/15s | Anthropic Claude |
|
||||
| `gemini` | `pol/` | 1 req/15s | Google Gemini |
|
||||
| `deepseek` | `pol/` | 1 req/15s | DeepSeek V3 |
|
||||
| `llama` | `pol/` | 1 req/15s | Meta Llama 4 Scout |
|
||||
| `mistral` | `pol/` | 1 req/15s | Mistral AI |
|
||||
|
||||
> ✨ **Zero friction:** No signup, no API key. Add the Pollinations provider with an empty key field and it works immediately.
|
||||
|
||||
### 🟠 CLOUDFLARE WORKERS AI (Free API Key — cloudflare.com) 🆕
|
||||
|
||||
| Tier | Daily Neurons | Equivalent Usage | Notes |
|
||||
| ---- | ------------- | --------------------------------------- | ----------------------- |
|
||||
| Free | **10,000** | ~150 LLM resp / 500s audio / 15K embeds | Global edge, 50+ models |
|
||||
|
||||
Popular free models: `@cf/meta/llama-3.3-70b-instruct`, `@cf/google/gemma-3-12b-it`, `@cf/openai/whisper-large-v3-turbo` (free audio!), `@cf/qwen/qwen2.5-coder-15b-instruct`
|
||||
|
||||
> Requires API Token + Account ID from [dash.cloudflare.com](https://dash.cloudflare.com). Store Account ID in provider settings.
|
||||
|
||||
### 🟣 SCALEWAY AI (1M Free Tokens — scaleway.com) 🆕
|
||||
|
||||
| Tier | Free Quota | Location | Notes |
|
||||
| ---- | ------------- | ------------ | ----------------------------------- |
|
||||
| Free | **1M tokens** | 🇫🇷 Paris, EU | No credit card needed within limits |
|
||||
|
||||
Available free: `qwen3-235b-a22b-instruct-2507` (Qwen3 235B!), `llama-3.1-70b-instruct`, `mistral-small-3.2-24b-instruct-2506`, `deepseek-v3-0324`
|
||||
|
||||
> EU/GDPR compliant. Get API key at [console.scaleway.com](https://console.scaleway.com).
|
||||
|
||||
> **💡 The Ultimate Free Stack (11 Providers, $0 Forever):**
|
||||
>
|
||||
> ```
|
||||
> Kiro (Claude, unlimited)
|
||||
> → iFlow (5 models, unlimited)
|
||||
> → Qwen (4 models, unlimited)
|
||||
> → Gemini CLI (180K/mo)
|
||||
> → Cerebras (1M tok/day)
|
||||
> → Groq (14.4K req/day)
|
||||
> → NVIDIA NIM (40 RPM, 70+ models)
|
||||
> Kiro (kr/) → Claude Sonnet/Haiku UNLIMITED
|
||||
> Qoder (if/) → kimi-k2-thinking, qwen3-coder-plus, deepseek-r1 UNLIMITED
|
||||
> LongCat Lite (lc/) → LongCat-Flash-Lite — 50M tokens/day 🔥
|
||||
> Pollinations (pol/) → GPT-5, Claude, DeepSeek, Llama 4 — no key needed
|
||||
> Qwen (qw/) → qwen3-coder models UNLIMITED
|
||||
> Gemini (gemini/) → Gemini 2.5 Flash — 1,500 req/day free
|
||||
> Cloudflare AI (cf/) → 50+ models — 10K Neurons/day
|
||||
> Scaleway (scw/) → Qwen3 235B, Llama 70B — 1M free tokens (EU)
|
||||
> Groq (groq/) → Llama/Gemma — 14.4K req/day ultra-fast
|
||||
> NVIDIA NIM (nvidia/) → 70+ open models — 40 RPM forever
|
||||
> Cerebras (cerebras/) → Llama/Qwen world-fastest — 1M tok/day
|
||||
> ```
|
||||
>
|
||||
> Configure this as an OmniRoute combo and you'll never pay for AI again.
|
||||
|
||||
## 🎙️ Free Transcription Combo
|
||||
|
||||
@@ -1100,6 +1219,9 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
|
||||
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
|
||||
| ⚡ **Background Degradation** | Route low-priority background tasks to cheaper models |
|
||||
| 🧪 **Task-Aware Smart Routing** | Auto-select model by content type (coding/vision/analysis/summarization) |
|
||||
| 🔄 **A2A Agent Workflows** | Deterministic FSM orchestrator for stateful multi-step agent executions |
|
||||
| 🔀 **Adaptive Routing** | Dynamic strategy override based on token volume and prompt complexity |
|
||||
| 🎲 **Provider Diversity** | Shannon entropy scoring balancing auto-combo traffic distribution |
|
||||
| 💬 **System Prompt Injection** | Global behavior controls applied consistently |
|
||||
| 📄 **Responses API Compatibility** | Full `/v1/responses` support for Codex and advanced agentic workflows |
|
||||
|
||||
@@ -1130,34 +1252,46 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
|
||||
| 🔏 **CLI Fingerprint Matching** | Matches native CLI request signatures — **reduces ban risk while preserving proxy IP** |
|
||||
| 🌐 **IP Filtering** | Allowlist/blocklist control for exposed deployments |
|
||||
| 📊 **Editable Rate Limits** | Configurable global/provider-level limits with persistence |
|
||||
| 📉 **Graceful Degradation** | Multi-layer capability fallbacks protecting core gateway operations |
|
||||
| 📜 **Config Audit Trail** | Diff-based change tracking preventing operational drift with simple rollbacks |
|
||||
| ⏳ **Provider Health Sync** | Proactive token expiration monitoring triggering alerts before authorization failures |
|
||||
| 🚪 **Auto-Disable Banned Accounts** | Operational circuit breaker sealing permanently blocked token accounts automatically |
|
||||
| 🔑 **API Key Management + Scoping** | Secure key issuance/rotation and model/provider controls |
|
||||
| 👁️ **Scoped API Key Reveal** 🆕 | Opt-in recovery of API keys via `ALLOW_API_KEY_REVEAL` |
|
||||
| 🛡️ **Protected `/models`** | Optional auth gating and provider hiding for model catalog |
|
||||
|
||||
### 📊 Observability & Analytics
|
||||
|
||||
| Feature | What It Does |
|
||||
| ------------------------------- | ----------------------------------------------------- |
|
||||
| 📝 **Request + Proxy Logging** | Full request/response and proxy logging |
|
||||
| 📋 **Unified Logs Dashboard** | Request, proxy, audit, and console views in one page |
|
||||
| 🔍 **Request Telemetry** | p50/p95/p99 latency and request tracing |
|
||||
| 🏥 **Health Dashboard** | Uptime, breaker states, lockouts, cache stats |
|
||||
| 💰 **Cost Tracking** | Budget controls and per-model pricing visibility |
|
||||
| 📈 **Analytics Visualizations** | Model/provider usage insights and trend views |
|
||||
| 🧪 **Evaluation Framework** | Golden set testing with configurable match strategies |
|
||||
| Feature | What It Does |
|
||||
| -------------------------------- | ----------------------------------------------------- |
|
||||
| 📝 **Request + Proxy Logging** | Full request/response and proxy logging |
|
||||
| 📉 **Streamed Detailed Logs** 🆕 | Reconstructs SSE payload streams cleanly into the UI |
|
||||
| 📋 **Unified Logs Dashboard** | Request, proxy, audit, and console views in one page |
|
||||
| 🔍 **Request Telemetry** | p50/p95/p99 latency and request tracing |
|
||||
| 🏥 **Health Dashboard** | Uptime, breaker states, lockouts, cache stats |
|
||||
| 💰 **Cost Tracking** | Budget controls and per-model pricing visibility |
|
||||
| 📈 **Analytics Visualizations** | Model/provider usage insights and trend views |
|
||||
| 🧪 **Evaluation Framework** | Golden set testing with configurable match strategies |
|
||||
| 📡 **Live Diagnostics** 🆕 | Semantic cache bypass for accurate combo live testing |
|
||||
|
||||
### ☁️ Deployment & Platform
|
||||
|
||||
| Feature | What It Does |
|
||||
| ----------------------------- | -------------------------------------------------------- |
|
||||
| 🌐 **Deploy Anywhere** | Localhost, VPS, Docker, Cloud environments |
|
||||
| 💾 **Cloud Sync** | Configuration sync via cloud worker |
|
||||
| 🔄 **Backup/Restore** | Export/import and disaster recovery flows |
|
||||
| 🧙 **Onboarding Wizard** | First-run guided setup |
|
||||
| 🔧 **CLI Tools Dashboard** | One-click setup for popular coding tools |
|
||||
| 🎮 **Model Playground** | Test any provider/model/endpoint from the dashboard |
|
||||
| 🔏 **CLI Fingerprint Toggle** | Per-provider fingerprint matching in Settings > Security |
|
||||
| 🌐 **i18n (30 languages)** | Full dashboard + docs language support with RTL coverage |
|
||||
| 📂 **Custom Data Directory** | `DATA_DIR` override for storage location |
|
||||
| Feature | What It Does |
|
||||
| ----------------------------- | --------------------------------------------------------- |
|
||||
| 🌐 **Deploy Anywhere** | Localhost, VPS, Docker, Cloud environments |
|
||||
| 🚇 **Cloudflare Tunnel** 🆕 | One-click Quick Tunnel integration from the dashboard |
|
||||
| 🔑 **API Key Model Filtering** | Native /v1/models response filtered via assigned Bearer context roles |
|
||||
| ⚡ **Smart Cache Bypass** | Configurable TTL heuristics and forced refetch controls |
|
||||
| 🔄 **Backup/Restore** | Export/import and disaster recovery flows |
|
||||
| 🧙 **Onboarding Wizard** | First-run guided setup |
|
||||
| 🔧 **CLI Tools Dashboard** | One-click setup for popular coding tools |
|
||||
| 🎮 **Model Playground** | Test any provider/model/endpoint from the dashboard |
|
||||
| 🔏 **CLI Fingerprint Toggle** | Per-provider fingerprint matching in Settings > Security |
|
||||
| 🌐 **i18n (30 languages)** | Full dashboard + docs language support with RTL coverage |
|
||||
| 🧹 **Clear All Models** | One-click model list clearing in provider details |
|
||||
| 👁️ **Sidebar Controls** 🆕 | Hide components and integrations from Appearance Settings |
|
||||
| 📋 **Issue Templates** | Standardized GitHub templates for bugs and features |
|
||||
| 📂 **Custom Data Directory** | `DATA_DIR` override for storage location |
|
||||
|
||||
### Feature Deep Dive
|
||||
|
||||
@@ -1409,6 +1543,8 @@ Models:
|
||||
|
||||
**Models:** Access 100+ models from all major providers through a single API key.
|
||||
|
||||
**Dashboard behavior:** OpenRouter models are managed from **Available Models**. Manual add, import, and auto-sync all update the same list.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@@ -1451,11 +1587,11 @@ Models:
|
||||
<details>
|
||||
<summary><b>🆓 FREE Providers (Emergency Backup)</b></summary>
|
||||
|
||||
### iFlow (5 FREE models via OAuth)
|
||||
### Qoder (5 FREE models via OAuth)
|
||||
|
||||
```bash
|
||||
Dashboard → Connect iFlow
|
||||
→ iFlow OAuth login
|
||||
Dashboard → Connect Qoder
|
||||
→ Qoder OAuth login
|
||||
→ Unlimited usage
|
||||
|
||||
Models:
|
||||
@@ -1653,7 +1789,7 @@ opencode
|
||||
|
||||
- Check usage stats in Dashboard → Costs
|
||||
- Switch primary model to GLM/MiniMax
|
||||
- Use free tier (Gemini CLI, iFlow) for non-critical tasks
|
||||
- Use free tier (Gemini CLI, Qoder) for non-critical tasks
|
||||
|
||||
**Dashboard/API ports are wrong**
|
||||
|
||||
|
||||
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2083
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
+2082
File diff suppressed because it is too large
Load Diff
+2077
File diff suppressed because it is too large
Load Diff
@@ -1,374 +0,0 @@
|
||||
# ZWS_README_V4 — 启动性能优化:HMR 泄漏修复与 Turbopack 迁移
|
||||
|
||||
## 一、如何发现问题
|
||||
|
||||
### 现象
|
||||
|
||||
- `npm run dev` 后,首次打开浏览器白屏等待 **5-22 秒**不等。
|
||||
- 运行一段时间后 Node 进程内存飙升至 **2.4 GB**,触发 Next.js 内存阈值保护强制重启。
|
||||
- 重启后 `Ready in 82.6s`(正常冷启动仅 3.4s),之后每个页面首次编译需 **7-28 秒**。
|
||||
- 日志中大量重复输出,单次会话内:
|
||||
- `[DB] SQLite database ready` 出现 **485 次**
|
||||
- `[HealthCheck] Starting proactive token health-check` 出现 **586 次**
|
||||
- `[CREDENTIALS] No external credentials file found` 出现 **432 次**
|
||||
|
||||
### 排查过程
|
||||
|
||||
1. **Terminal 日志分析**:统计关键日志出现次数,发现 DB 连接和 HealthCheck 定时器被反复创建。
|
||||
2. **代码审计**:追踪到所有受影响模块使用 `let initialized = false` 作为单例守卫——这在 Next.js dev 模式的 Webpack HMR 下会被重置。
|
||||
3. **对比**:`apiBridgeServer.ts` 使用了 `globalThis.__omnirouteApiBridgeStarted`,在日志中无重复初始化,验证了 `globalThis` 方案的有效性。
|
||||
4. **内存快照**:通过 `Get-Process node` 观察到两个 node 进程分别占用 1.7GB 和 1.0GB。
|
||||
5. **编译时间分析**:日志中 `compile:` 字段显示 Webpack 编译每个路由需 2-26 秒,对比 Turbopack 应在 0.5-3 秒。
|
||||
|
||||
---
|
||||
|
||||
## 二、根因分析
|
||||
|
||||
### 根因 1(P0):模块级单例在 HMR 中丢失
|
||||
|
||||
Next.js dev 模式下,Webpack HMR 会重新执行被修改(或依赖链变化)的模块。模块级 `let` 变量在每次重新执行时被重置为初始值。
|
||||
|
||||
```typescript
|
||||
// 修复前 — 每次 HMR 重新执行时 _db 重置为 null
|
||||
let _db: SqliteDatabase | null = null;
|
||||
|
||||
export function getDbInstance() {
|
||||
if (_db) return _db; // HMR 后这里永远 false
|
||||
// ... 重新打开一个新的 DB 连接(旧连接泄漏)
|
||||
}
|
||||
```
|
||||
|
||||
**受影响的模块与泄漏类型:**
|
||||
|
||||
| 模块 | 泄漏资源 | 累计次数 | 后果 |
|
||||
| ----------------------- | ---------------------- | -------- | ----------------------- |
|
||||
| `db/core.ts` | SQLite 连接 | 485 | 文件句柄泄漏 + 内存占用 |
|
||||
| `tokenHealthCheck.ts` | `setInterval` 定时器 | 586 | CPU 空转 + DB 查询风暴 |
|
||||
| `localHealthCheck.ts` | `setTimeout` 定时器链 | ~400 | 重复 HTTP 请求 + CPU |
|
||||
| `consoleInterceptor.ts` | console 方法包装 | ~400 | 日志 double-write |
|
||||
| `gracefulShutdown.ts` | SIGTERM/SIGINT handler | ~400 | 信号处理器堆叠 |
|
||||
|
||||
**级联效应**:泄漏的资源持续消耗内存和 CPU → 触发 Next.js 内存阈值保护 → 进程重启 → Webpack 从零重建模块图 → **Ready in 82.6s**。
|
||||
|
||||
### 根因 2(P0):强制使用 Webpack 而非 Turbopack
|
||||
|
||||
`scripts/run-next.mjs` 中硬编码了 `--webpack` 标志:
|
||||
|
||||
```javascript
|
||||
if (mode === "dev") {
|
||||
args.splice(2, 0, "--webpack");
|
||||
}
|
||||
```
|
||||
|
||||
Next.js 16 默认使用 Turbopack(Rust 编写的增量打包器),dev 编译速度是 Webpack 的 5-10 倍。强制回退到 Webpack 导致:
|
||||
|
||||
| 指标 | Webpack | Turbopack(预期) |
|
||||
| ----------------------- | ------- | ----------------- |
|
||||
| 首页编译 | 3.7s | ~0.5s |
|
||||
| Provider 详情页首次编译 | 22s | ~2-3s |
|
||||
| API route 首次编译 | 2-7s | ~0.3-1s |
|
||||
| 内存重启后 Ready | 82.6s | 不会触发 |
|
||||
|
||||
### 根因 3(P1):`node:crypto` 被拉入客户端 bundle
|
||||
|
||||
`src/lib/db/proxies.ts` 使用了 `import { randomUUID } from "node:crypto"`。通过 `localDb.ts` 的 re-export 链,这个 Node.js 原生模块被间接拉入客户端组件的 bundle,导致 Webpack 报错:
|
||||
|
||||
```
|
||||
UnhandledSchemeError: Reading from "node:crypto" is not handled by plugins
|
||||
Import trace: node:crypto → ./src/lib/db/proxies.ts → ./src/lib/localDb.ts → page.tsx
|
||||
```
|
||||
|
||||
Webpack 无法处理 `node:` URI scheme 前缀。`crypto`(不带 `node:` 前缀)已在 `next.config.mjs` 的 `serverExternalPackages` 中声明为服务端外部包。
|
||||
|
||||
### 根因 4(P1):Edge Runtime 编译警告刷屏
|
||||
|
||||
Next.js 16 会同时为 **Node.js** 和 **Edge** 两种运行时编译 `instrumentation.ts`。虽然 `register()` 函数内有 `process.env.NEXT_RUNTIME === "nodejs"` 的运行时守卫,但 Turbopack 在打包 Edge 版本时仍会**静态追踪**所有动态 `import()` 的依赖链:
|
||||
|
||||
```
|
||||
instrumentation.ts
|
||||
→ import("@/lib/db/secrets")
|
||||
→ @/lib/db/core.ts → fs, path, better-sqlite3
|
||||
→ @/lib/dataPaths.ts → path, os
|
||||
→ @/lib/db/migrationRunner.ts → fs, path, url
|
||||
```
|
||||
|
||||
对每个 Node.js 原生模块,Turbopack 都输出一条 "not supported in Edge Runtime" 警告。每次有新请求触发热编译时,这组 **10+ 条警告重复刷一遍**,严重污染终端输出,干扰开发调试。
|
||||
|
||||
### 根因 5(P2):启动 import 完全串行
|
||||
|
||||
`instrumentation.ts` 中 9 个 `await import()` 完全串行执行,每个都可能触发 Webpack 编译其依赖树:
|
||||
|
||||
```typescript
|
||||
await ensureSecrets(); // 串行 1
|
||||
const { initConsoleInterceptor } = await import(...); // 串行 2
|
||||
const { initGracefulShutdown } = await import(...); // 串行 3
|
||||
const { initApiBridgeServer } = await import(...); // 串行 4
|
||||
const { startBackgroundRefresh } = await import(...); // 串行 5
|
||||
const { getSettings } = await import(...); // 串行 6
|
||||
const { setCustomAliases } = await import(...); // 串行 7
|
||||
const { setDefaultFastServiceTierEnabled } = await import(...); // 串行 8
|
||||
const { initAuditLog, cleanupExpiredLogs } = await import(...); // 串行 9
|
||||
```
|
||||
|
||||
其中 4-6 互不依赖,7-8 互不依赖,完全可以并行。
|
||||
|
||||
---
|
||||
|
||||
## 三、修复方案
|
||||
|
||||
### 修复 1:globalThis 单例守卫(core.ts, tokenHealthCheck.ts, localHealthCheck.ts, consoleInterceptor.ts, gracefulShutdown.ts)
|
||||
|
||||
**原理**:`globalThis` 对象在 Node.js 进程生命周期内全局唯一,不受 Webpack 模块重新执行的影响。
|
||||
|
||||
```typescript
|
||||
// 修复后 — globalThis 在 HMR 后依然保留
|
||||
declare global {
|
||||
var __omnirouteDb: import("better-sqlite3").Database | undefined;
|
||||
}
|
||||
|
||||
function getDb() {
|
||||
return globalThis.__omnirouteDb ?? null;
|
||||
}
|
||||
function setDb(db) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
export function getDbInstance() {
|
||||
const existing = getDb();
|
||||
if (existing) return existing; // HMR 后命中缓存
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**每个模块的具体改动:**
|
||||
|
||||
| 模块 | globalThis key | 守卫内容 |
|
||||
| ----------------------- | ----------------------------------- | ----------------------------------------------------------- |
|
||||
| `db/core.ts` | `__omnirouteDb` | SQLite 连接实例 |
|
||||
| `tokenHealthCheck.ts` | `__omnirouteTokenHC` | `{ initialized, interval }` |
|
||||
| `localHealthCheck.ts` | `__omnirouteLocalHC` | `{ initialized, sweepTimer, healthCache, sweepInProgress }` |
|
||||
| `consoleInterceptor.ts` | `__omnirouteConsoleInterceptorInit` | `boolean` |
|
||||
| `gracefulShutdown.ts` | `__omnirouteShutdownInit` | `boolean` |
|
||||
|
||||
**优点**:
|
||||
|
||||
- 零依赖,无需额外库。
|
||||
- 与 `apiBridgeServer.ts` 已有模式一致。
|
||||
- 对生产环境零影响(非 HMR 场景下行为完全相同)。
|
||||
|
||||
**缺点/注意**:
|
||||
|
||||
- `globalThis` 键名需全局唯一,使用 `__omniroute` 前缀避免冲突。
|
||||
- 需要 `declare global` 类型声明以保持 TypeScript 类型安全。
|
||||
- 生产构建中 `globalThis` 存储略冗余(但仅是一个对象引用,几乎零开销)。
|
||||
|
||||
### 修复 2:支持通过环境变量切换 Turbopack(run-next.mjs)
|
||||
|
||||
```javascript
|
||||
// 修复后 — 默认仍用 webpack(保持原有行为),设置环境变量可启用 Turbopack
|
||||
if (mode === "dev" && process.env.OMNIROUTE_USE_TURBOPACK !== "1") {
|
||||
args.splice(2, 0, "--webpack");
|
||||
}
|
||||
```
|
||||
|
||||
**默认行为不变**:dev 模式仍使用 Webpack,与修复前完全一致。设置 `OMNIROUTE_USE_TURBOPACK=1` 可切换到 Turbopack 以获得更快的 dev 编译速度。
|
||||
|
||||
**优点**:
|
||||
|
||||
- 零风险:不改变任何人的现有体验。
|
||||
- 需要时设置 `OMNIROUTE_USE_TURBOPACK=1` 即可获得 5-10 倍编译加速。
|
||||
- `next.config.mjs` 中已有 `turbopack.resolveAlias` 配置,说明项目已在准备 Turbopack 迁移。
|
||||
|
||||
**缺点/注意**:
|
||||
|
||||
- Turbopack 对某些 Webpack 特定配置(如自定义 externals 函数)的支持方式不同,启用前需测试兼容性。
|
||||
- 默认走 Webpack 意味着不主动启用 Turbopack 的用户无法享受编译加速。
|
||||
|
||||
### 修复 3:`node:crypto` → `crypto`(proxies.ts, errorResponse.ts)
|
||||
|
||||
```typescript
|
||||
// 修复前
|
||||
import { randomUUID } from "node:crypto";
|
||||
|
||||
// 修复后
|
||||
import { randomUUID } from "crypto";
|
||||
```
|
||||
|
||||
**优点**:
|
||||
|
||||
- `crypto`(无 `node:` 前缀)已在 `next.config.mjs` 的 `serverExternalPackages` 列表中,Webpack/Turbopack 会正确将其标记为外部包。
|
||||
- 消除 `UnhandledSchemeError` 构建失败。
|
||||
- Node.js 中 `crypto` 和 `node:crypto` 解析到同一模块。
|
||||
|
||||
**缺点**:
|
||||
|
||||
- 无。`crypto` 是 Node.js 内建模块,两种写法功能完全等价。
|
||||
|
||||
### 修复 4:分离 Edge/Node.js Instrumentation(instrumentation.ts → instrumentation-node.ts)
|
||||
|
||||
**问题**:`instrumentation.ts` 中所有 Node.js 逻辑(`ensureSecrets`、DB 初始化、审计日志等)虽然只在 `NEXT_RUNTIME === "nodejs"` 时执行,但 Turbopack 编译 Edge 版本时仍静态追踪其 import 链,对每个 `fs`/`path`/`os`/`better-sqlite3` 等原生模块输出警告。
|
||||
|
||||
**方案**:将所有 Node.js 专属逻辑提取到 `src/instrumentation-node.ts`,主文件通过**计算的 import 路径**引入,阻止 Turbopack 静态解析:
|
||||
|
||||
```typescript
|
||||
// src/instrumentation.ts — 精简后仅 ~20 行
|
||||
export async function register() {
|
||||
if (process.env.NEXT_RUNTIME === "nodejs") {
|
||||
// 拼接路径阻止 Turbopack 在 Edge 编译时静态解析模块依赖
|
||||
const nodeMod = "./instrumentation-" + "node";
|
||||
const { registerNodejs } = await import(nodeMod);
|
||||
await registerNodejs();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
// src/instrumentation-node.ts — 包含全部 Node.js 启动逻辑
|
||||
export async function registerNodejs(): Promise<void> {
|
||||
await ensureSecrets();
|
||||
// initConsoleInterceptor, initGracefulShutdown, initApiBridgeServer, ...
|
||||
// (原 instrumentation.ts 的完整 Node.js 逻辑)
|
||||
}
|
||||
```
|
||||
|
||||
**关键技术**:`"./instrumentation-" + "node"` 是运行时拼接的字符串,Turbopack 无法在编译期确定其值,因此**不会追踪**该 import 的依赖树。Node.js 运行时则正常解析该路径并执行。
|
||||
|
||||
**优点**:
|
||||
|
||||
- Edge 编译时完全跳过 Node.js 模块追踪,**10+ 条重复警告全部消除**。
|
||||
- Node.js 运行时行为与修复前完全一致。
|
||||
- 启动时间从 **13.9s → 1.25s**(Turbopack 不再在 Edge 编译中处理 Node.js 模块图)。
|
||||
|
||||
**缺点/注意**:
|
||||
|
||||
- 新增一个文件 `instrumentation-node.ts`,需同步维护。
|
||||
- 计算 import 路径是有意为之的 bundler 逃逸技巧,需加注释说明原因防止后续重构时被"优化"回静态字符串。
|
||||
|
||||
### 修复 5:并行化 instrumentation.ts 中的启动 import
|
||||
|
||||
```typescript
|
||||
// 修复后 — 4 个独立模块并行导入
|
||||
const [
|
||||
{ initGracefulShutdown },
|
||||
{ initApiBridgeServer },
|
||||
{ startBackgroundRefresh },
|
||||
{ getSettings },
|
||||
] = await Promise.all([
|
||||
import("@/lib/gracefulShutdown"),
|
||||
import("@/lib/apiBridgeServer"),
|
||||
import("@/domain/quotaCache"),
|
||||
import("@/lib/db/settings"),
|
||||
]);
|
||||
|
||||
// 2 个 open-sse 模块也并行导入
|
||||
const [{ setCustomAliases }, { setDefaultFastServiceTierEnabled }] = await Promise.all([
|
||||
import("@omniroute/open-sse/services/modelDeprecation.ts"),
|
||||
import("@omniroute/open-sse/executors/codex.ts"),
|
||||
]);
|
||||
```
|
||||
|
||||
**优点**:
|
||||
|
||||
- `consoleInterceptor` 仍保持第一个(必须在任何日志前初始化)。
|
||||
- 后续 4 个无依赖模块并行加载,节省 3 次串行等待。
|
||||
- open-sse 的 2 个模块也并行加载。
|
||||
|
||||
**缺点**:
|
||||
|
||||
- 并行 import 的错误堆栈略复杂(Promise.all 中某一个失败会 reject 整个组)。
|
||||
- 这里的 compliance 模块仍保持独立 try/catch 串行,因为它有自己的错误处理逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 四、预期效果
|
||||
|
||||
| 指标 | 修复前 | 修复后(预期) |
|
||||
| ----------------------------- | ------------------------- | ------------------------ |
|
||||
| DB 连接创建次数 | 485 次/会话 | 1 次 |
|
||||
| HealthCheck 定时器 | 586 个泄漏 | 1 个 |
|
||||
| 信号处理器注册 | ~400 次重复 | 1 次 |
|
||||
| Console 拦截层数 | ~400 层嵌套 | 1 层 |
|
||||
| 内存使用峰值 | 2.4 GB → OOM 重启 | 预期 < 500 MB |
|
||||
| 冷启动 Ready | 3.4s | ~3s(略快) |
|
||||
| 内存重启 Ready | 82.6s | 不再触发内存重启 |
|
||||
| Login 页首次编译 | 3.7s | ~0.5s (需启用 Turbopack) |
|
||||
| Provider 详情页首次编译 | 22s | ~2-3s (需启用 Turbopack) |
|
||||
| `node:crypto` 构建错误 | 反复出现 | 消除 |
|
||||
| Edge Runtime 编译警告 | 每次热编译刷出 10+ 条 | **0 条** |
|
||||
| instrumentation 启动耗时 | 13.9s(含 Edge 模块追踪) | **1.25s** |
|
||||
| instrumentation import 并行度 | 9 次串行 import | 3 批并行 import |
|
||||
|
||||
---
|
||||
|
||||
## 五、涉及文件清单
|
||||
|
||||
| 区域 | 文件 | 改动类型 |
|
||||
| ------------------- | ------------------------------- | ------------------------------------------------------------------ |
|
||||
| DB 单例 | `src/lib/db/core.ts` | `let _db` → `globalThis.__omnirouteDb` |
|
||||
| Token 健康检查 | `src/lib/tokenHealthCheck.ts` | `let initialized` → `globalThis.__omnirouteTokenHC` |
|
||||
| 本地节点健康检查 | `src/lib/localHealthCheck.ts` | `let initialized` → `globalThis.__omnirouteLocalHC` |
|
||||
| Console 拦截 | `src/lib/consoleInterceptor.ts` | `let initialized` → `globalThis.__omnirouteConsoleInterceptorInit` |
|
||||
| 优雅关停 | `src/lib/gracefulShutdown.ts` | 新增 `globalThis.__omnirouteShutdownInit` 守卫 |
|
||||
| Dev 启动脚本 | `scripts/run-next.mjs` | 新增 `OMNIROUTE_USE_TURBOPACK=1` 开关 |
|
||||
| Proxy 注册表 | `src/lib/db/proxies.ts` | `node:crypto` → `crypto` |
|
||||
| API 错误响应 | `src/lib/api/errorResponse.ts` | `node:crypto` → `crypto` |
|
||||
| 启动钩子(主入口) | `src/instrumentation.ts` | 精简为 ~20 行,计算 import 路径阻止 Edge 追踪 |
|
||||
| 启动钩子(Node.js) | `src/instrumentation-node.ts` | 新文件,承载全部 Node.js 启动逻辑 + `Promise.all` 并行 |
|
||||
|
||||
---
|
||||
|
||||
## 六、回退方案
|
||||
|
||||
- **启用 Turbopack**:设置 `OMNIROUTE_USE_TURBOPACK=1` 环境变量;不设置则默认使用 Webpack(原有行为不变)。
|
||||
- **globalThis 方案异常**:所有 globalThis key 都以 `__omniroute` 为前缀,可通过 `delete globalThis.__omnirouteDb` 等方式手动重置。
|
||||
- **Edge 警告回退**:若 `instrumentation-node.ts` 拆分导致问题,可将其内容合并回 `instrumentation.ts`,恢复为直接 `import()` 调用(警告会重新出现但不影响功能)。
|
||||
- **生产环境**:以上修复对生产构建无负面影响——生产环境不存在 HMR,globalThis 单例仅在首次调用时初始化一次。计算 import 路径在 `next build` 时由 Node.js 正常解析,不影响打包产物。
|
||||
|
||||
---
|
||||
|
||||
## 七、单元测试与备份恢复(pre-commit 验证通过)
|
||||
|
||||
为保证提交前必须通过验证(不再使用 `--no-verify`),对以下失败用例与生产逻辑做了修复与加固。
|
||||
|
||||
### 问题与根因
|
||||
|
||||
| 失败项 | 根因 |
|
||||
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| bootstrap-env 4 个用例 | Windows 上 DATA_DIR 解析用 `APPDATA`/`homedir()`,测试只设了 `HOME`,脚本读不到测试用的 `.env`。 |
|
||||
| domain-persistence costRules 2 个用例 | `core` 在首次 import 时缓存 `DATA_DIR`;测试每测一个 tmpDir 并在 afterEach 删目录,导致后续 describe 使用的 DB 路径已被删,读写得到 0。 |
|
||||
| fixes-p1 restoreDbBackup | 测试在 DB 仍打开时写 stale 侧文件;`restoreDbBackup` 内 pre-restore 备份未 await 就关库,Windows 上句柄未及时释放,unlink 报 EBUSY。 |
|
||||
| fixes-p1 resetStorage 及后续用例 | 上一测留下 DB 打开,下一测 `resetStorage()` 删目录时文件仍被占用,EBUSY。 |
|
||||
|
||||
### 修复 6:bootstrap-env 测试(tests/unit/bootstrap-env.test.mjs)
|
||||
|
||||
在每个用例的 `withTempEnv` 回调开头增加 `process.env.DATA_DIR = dataDir`,使脚本在任意平台(含 Windows)都使用测试临时目录,而不是依赖 `HOME`/`APPDATA`。
|
||||
|
||||
### 修复 7:domain-persistence 测试(tests/unit/domain-persistence.test.mjs)
|
||||
|
||||
- **单例 tmpDir**:全文件共用一个 `fileTmpDir`,在模块加载时创建并设置 `process.env.DATA_DIR`,与 `core` 首次加载时缓存的路径一致。
|
||||
- **每测清 DB 不清目录**:`beforeEach` 中 `resetDbInstance()` 后删除 `storage.sqlite` 及其 `-wal`/`-shm`/`-journal`,保证每测干净 DB,不在 afterEach 删目录,避免路径失效。
|
||||
- **收尾**:`after()` 中恢复 `DATA_DIR` 并删除 `fileTmpDir`。
|
||||
- **costRules 断言**:改为小容差精确校验(`assertAlmostEqual`),继续验证 `4.5` / `4.0` 这类业务关键值,避免把真实累计错误放过去。
|
||||
|
||||
### 修复 8:fixes-p1 测试(tests/unit/fixes-p1.test.mjs)
|
||||
|
||||
- **restoreDbBackup 用例**:在写入 stale 侧文件前调用 `core.resetDbInstance()`,避免 DB 仍打开时写 `-wal`/`-shm` 触发 Windows 锁错误。
|
||||
- **Windows 跳过**:该用例在 Windows 上仍使用 `test(..., { skip: isWindows })`。原因不是业务逻辑不支持 Windows,而是 better-sqlite3 关闭后底层句柄释放存在时序抖动,这条真实 sidecar 集成测试容易退化成不稳定的文件锁测试;Linux/macOS 上照常运行。
|
||||
- **核心兜底测试**:新增平台无关的 `unlinkFileWithRetry` 单测,直接模拟 `EBUSY` / `EPERM` 后重试并最终成功,确保 Windows 相关的重试删除逻辑被稳定覆盖,而不是完全依赖 flaky 的真实文件锁时序。
|
||||
- **resetStorage**:改为 async,对 `rmSync(TEST_DATA_DIR)` 做最多 10 次、间隔 100ms 的 EBUSY/EPERM 重试,避免下一测因上一测句柄未释放而失败。
|
||||
|
||||
### 修复 9:备份恢复逻辑(src/lib/db/backup.ts)
|
||||
|
||||
- **pre-restore 备份改为同步等待**:在 `restoreDbBackup` 内用内联逻辑做 pre-restore 备份并 `await` 完成,再调用 `resetDbInstance()`,避免异步 backup 未结束就关库导致后续 unlink 失败。
|
||||
- **节流语义保持一致**:pre-restore 备份成功后补回 `_lastBackupAt = Date.now()`,避免恢复后紧接着又触发一轮额外自动备份。
|
||||
- **关库后短延迟**:`resetDbInstance()` 后 `await new Promise(r => setTimeout(r, 500))`,再执行 unlink,给 Windows 等平台释放句柄留时间。
|
||||
- **unlink 重试**:将主库及 `-wal`/`-shm`/`-journal` 的删除提取为 `unlinkFileWithRetry`,统一做最多 10 次、间隔 100ms 的 EBUSY/EPERM 重试,提高恢复流程在锁释放较慢环境下的成功率,也便于单测直接覆盖重试逻辑。
|
||||
|
||||
### 涉及文件(本节)
|
||||
|
||||
| 区域 | 文件 | 改动类型 |
|
||||
| -------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
||||
| 单元测试 | `tests/unit/bootstrap-env.test.mjs` | 各用例内设置 `process.env.DATA_DIR = dataDir` |
|
||||
| 单元测试 | `tests/unit/domain-persistence.test.mjs` | 单例 tmpDir、beforeEach 清 DB 文件、after 删目录;costRules 改为小容差精确断言 |
|
||||
| 单元测试 | `tests/unit/fixes-p1.test.mjs` | restoreDbBackup 前 resetDbInstance、Windows skip 说明、resetStorage 重试、`unlinkFileWithRetry` 核心单测 |
|
||||
| 备份恢复 | `src/lib/db/backup.ts` | pre-restore 内联并 await、恢复 `_lastBackupAt` 节流语义、关库后 500ms 延迟、抽取 `unlinkFileWithRetry` 重试删除 |
|
||||
@@ -1,332 +0,0 @@
|
||||
# ZWS_README_V5 — 按协议配置模型兼容性 + 前端性能优化
|
||||
|
||||
V4 内容(HMR 泄漏修复、Edge 警告消除、测试稳定性)已完成;V5 在 V4 基础上实现**按协议维度配置模型兼容性**,新增前端查找性能优化与类型安全改进。
|
||||
|
||||
---
|
||||
|
||||
## 一、如何发现问题
|
||||
|
||||
### 现象
|
||||
|
||||
- 同一模型被 **OpenAI Chat Completions**、**OpenAI Responses API**、**Anthropic Messages** 三种客户端请求形态调用时,V2 的兼容性开关(工具 ID 9 位、不保留 developer 角色)是**全局生效**的——无法为不同协议设置不同的兼容策略。
|
||||
- 例如:用户希望 OpenAI Responses API 请求时不保留 developer 角色(MiniMax 422 修复),但 OpenAI Chat Completions 请求时保留。V2 下只能二选一。
|
||||
- 前端兼容性弹层未标明当前配置对应哪种协议,容易误导。
|
||||
- 前端组件中 `Array.find()` 在每次渲染时对 customModels 和 modelCompatOverrides 做 O(n) 线性扫描,模型数量多时存在不必要的性能开销。
|
||||
- `ModelCompatPatch` 类型定义与运行时逻辑不一致:`preserveOpenAIDeveloperRole` 字段需要支持 `null`(表示取消设置/恢复默认),但类型仅允许 `boolean`。
|
||||
|
||||
### 排查过程
|
||||
|
||||
1. **需求分析**:梳理 `detectFormat(body)` 返回的三种协议键(`openai`、`openai-responses`、`claude`),确认每种协议对 developer 角色和 tool call ID 的需求不同。
|
||||
2. **数据模型设计**:在现有 `normalizeToolCallId` / `preserveOpenAIDeveloperRole` 顶层字段基础上,设计 `compatByProtocol` 嵌套结构,按协议键细分。
|
||||
3. **构建问题**:客户端 `"use client"` 组件直接从 `@/lib/localDb` 引入常量时,间接拉入了 `node:crypto`(经由 `db/proxies.ts`),触发 Webpack `UnhandledSchemeError`。需将常量拆到 `shared/` 层。
|
||||
4. **前端性能**:通过 React DevTools 和代码审计发现 `effectiveNormalizeForProtocol` 等函数每次调用都对数组做 `find()`,在渲染列表时存在 O(n²) 的隐患。
|
||||
|
||||
---
|
||||
|
||||
## 二、根因分析
|
||||
|
||||
### 根因 1(P0):兼容选项无协议维度
|
||||
|
||||
V2 的 `normalizeToolCallId` / `preserveOpenAIDeveloperRole` 存储在模型级别的顶层字段,无法区分请求来源协议。`chatCore.ts` 中的 getter 函数只接收 `(providerId, modelId)` 两个参数,不感知当前请求的 `sourceFormat`。
|
||||
|
||||
**影响**:跨协议场景下用户只能设置一个全局值,无法精确控制。
|
||||
|
||||
### 根因 2(P1):客户端构建拉入 Node.js 模块
|
||||
|
||||
`page.tsx`("use client")→ `@/lib/localDb` → `db/proxies.ts` → `import { randomUUID } from "node:crypto"`
|
||||
|
||||
Webpack 无法处理 `node:` URI scheme,报 `UnhandledSchemeError`。虽然 V4 已将 `node:crypto` → `crypto` 修复了 `proxies.ts`,但 `localDb.ts` 的 barrel export 链仍然存在风险——客户端组件不应引入任何可能传递到 Node.js 模块的路径。
|
||||
|
||||
### 根因 3(P2):前端查找性能
|
||||
|
||||
`effectiveNormalizeForProtocol`、`effectivePreserveForProtocol`、`anyNormalizeCompatBadge`、`anyNoPreserveCompatBadge` 四个函数每次调用都使用 `Array.find()` 在 `customModels` 和 `modelCompatOverrides` 数组中查找目标模型。在模型列表渲染时,每个模型行会调用多次这些函数,导致 O(n × m) 的查找开销(n = 模型数,m = 每行调用次数)。
|
||||
|
||||
### 根因 4(P2):类型定义与运行时不一致
|
||||
|
||||
```typescript
|
||||
// V3 暂存区版本(有问题)
|
||||
export type ModelCompatPatch = Partial<
|
||||
Pick<
|
||||
ModelCompatOverride,
|
||||
"normalizeToolCallId" | "preserveOpenAIDeveloperRole" | "compatByProtocol"
|
||||
>
|
||||
>;
|
||||
```
|
||||
|
||||
`ModelCompatOverride.preserveOpenAIDeveloperRole` 类型为 `boolean | undefined`,但 `mergeModelCompatOverride()` 内部有 `=== null` 判断(用于取消设置/恢复默认),类型层面无法覆盖。
|
||||
|
||||
---
|
||||
|
||||
## 三、修复方案
|
||||
|
||||
### 修复 1:`compatByProtocol` 存储与读取(models.ts)
|
||||
|
||||
**新增数据结构**:
|
||||
|
||||
```typescript
|
||||
type CompatByProtocolMap = Partial<Record<ModelCompatProtocolKey, ModelCompatPerProtocol>>;
|
||||
|
||||
export type ModelCompatOverride = {
|
||||
id: string;
|
||||
normalizeToolCallId?: boolean;
|
||||
preserveOpenAIDeveloperRole?: boolean;
|
||||
compatByProtocol?: CompatByProtocolMap; // 新增
|
||||
};
|
||||
```
|
||||
|
||||
**读取优先级链**(适用于 `getModelNormalizeToolCallId` 和 `getModelPreserveOpenAIDeveloperRole`):
|
||||
|
||||
```
|
||||
compatByProtocol[sourceFormat].field → 顶层 field → 默认值
|
||||
```
|
||||
|
||||
1. 若 `sourceFormat` 属于已知协议键(`openai` / `openai-responses` / `claude`),且 `compatByProtocol[sourceFormat]` 中存在目标字段,使用该值。
|
||||
2. 否则回退到顶层字段。
|
||||
3. 顶层字段也不存在时使用默认值(normalizeToolCallId=false,preserveOpenAIDeveloperRole=undefined)。
|
||||
|
||||
**深度合并逻辑** `deepMergeCompatByProtocol()`:
|
||||
|
||||
- 对每个协议键,逐字段合并而非覆盖。
|
||||
- `normalizeToolCallId=false` 时删除该字段(不存储 false,减少冗余)。
|
||||
- 合并后若整个协议条目为空对象,删除该协议条目。
|
||||
- 协议键通过 `isCompatProtocolKey()` 白名单校验,拒绝未知键。
|
||||
|
||||
**Getter 签名扩展**(向后兼容,第三参数可选):
|
||||
|
||||
```typescript
|
||||
export function getModelNormalizeToolCallId(
|
||||
providerId: string,
|
||||
modelId: string,
|
||||
sourceFormat?: string | null
|
||||
): boolean;
|
||||
|
||||
export function getModelPreserveOpenAIDeveloperRole(
|
||||
providerId: string,
|
||||
modelId: string,
|
||||
sourceFormat?: string | null
|
||||
): boolean | undefined;
|
||||
```
|
||||
|
||||
**优点**:
|
||||
|
||||
- 完全向后兼容:无 `sourceFormat` 参数时行为与 V2 完全一致。
|
||||
- 协议键白名单校验防止存储污染。
|
||||
- 深度合并保留未变更协议的配置。
|
||||
|
||||
**缺点/注意**:
|
||||
|
||||
- JSON 存储体积略增(每个模型最多增加 3 个协议条目)。
|
||||
- 新增 ~80 行 TypeScript 代码。
|
||||
|
||||
### 修复 2:请求管线传入 sourceFormat(chatCore.ts)
|
||||
|
||||
```typescript
|
||||
const normalizeToolCallId = getModelNormalizeToolCallId(
|
||||
provider || "",
|
||||
model || "",
|
||||
sourceFormat // 新增第三参
|
||||
);
|
||||
const preserveDeveloperRole = getModelPreserveOpenAIDeveloperRole(
|
||||
provider || "",
|
||||
model || "",
|
||||
sourceFormat // 新增第三参
|
||||
);
|
||||
```
|
||||
|
||||
`sourceFormat` 由已有的 `detectFormat(body)` 返回,无需新增检测逻辑。
|
||||
|
||||
**优点**:
|
||||
|
||||
- 改动仅 2 行,精准传参。
|
||||
- 不影响其他 handler(embeddings、imageGeneration 等不涉及 developer 角色和 tool call ID)。
|
||||
|
||||
### 修复 3:API 路由支持 compatByProtocol(route.ts)
|
||||
|
||||
**PUT 请求体扩展**:
|
||||
|
||||
- 解构 `compatByProtocol` 并传入 `updateCustomModel()`。
|
||||
- `compatOnly` 判断扩展:仅含 `provider` + `modelId` + 兼容字段时,走 `mergeModelCompatOverride()` 路径。
|
||||
- 使用 `ModelCompatPatch` 类型替代行内类型定义,统一类型来源。
|
||||
|
||||
**Zod 校验 schema**:
|
||||
|
||||
```typescript
|
||||
const modelCompatPerProtocolSchema = z.object({
|
||||
normalizeToolCallId: z.boolean().optional(),
|
||||
preserveOpenAIDeveloperRole: z.boolean().optional(),
|
||||
}).strict(); // strict: 拒绝额外字段
|
||||
|
||||
compatByProtocol: z
|
||||
.record(z.enum(["openai", "openai-responses", "claude"]), modelCompatPerProtocolSchema)
|
||||
.optional(),
|
||||
```
|
||||
|
||||
**优点**:
|
||||
|
||||
- `.strict()` 防止客户端注入额外字段。
|
||||
- `z.enum()` 限定协议键,与后端白名单一致。
|
||||
- 仅传 `compatByProtocol` 即可更新,前端无需拼装完整模型对象。
|
||||
|
||||
### 修复 4:客户端安全常量拆分(modelCompat.ts)
|
||||
|
||||
**新增** `src/shared/constants/modelCompat.ts`:
|
||||
|
||||
```typescript
|
||||
export const MODEL_COMPAT_PROTOCOL_KEYS = ["openai", "openai-responses", "claude"] as const;
|
||||
export type ModelCompatProtocolKey = (typeof MODEL_COMPAT_PROTOCOL_KEYS)[number];
|
||||
```
|
||||
|
||||
- 不依赖 Node.js / DB 代码,客户端组件可安全引入。
|
||||
- `models.ts` 从此模块引入并再导出。
|
||||
- `localDb.ts` 新增 `ModelCompatPatch` 类型导出(供 route.ts 使用),不导出协议常量。
|
||||
- `page.tsx` 改为从 `@/shared/constants/modelCompat` 引入。
|
||||
|
||||
**优点**:
|
||||
|
||||
- 彻底切断客户端 → localDb → db → proxies → node:crypto 的依赖链。
|
||||
- 协议键定义单一来源(Single Source of Truth)。
|
||||
|
||||
### 修复 5:前端协议选择器与按协议解析(page.tsx)
|
||||
|
||||
**ModelCompatPopover 重构**:
|
||||
|
||||
- 新增协议下拉选择器(`<select>`),可选 OpenAI Chat / OpenAI Responses / Anthropic Messages。
|
||||
- 两个开关(工具 ID 9 位、不保留 developer)**针对选中协议**生效。
|
||||
- 选择 Claude 协议时隐藏 developer 角色开关(developer 仅对 OpenAI 系有意义)。
|
||||
- 保存时以 `{ compatByProtocol: { [protocol]: payload } }` 形式提交,后端按协议合并。
|
||||
- 深色模式适配:下拉框使用 `bg-white dark:bg-zinc-800`、`text-zinc-900 dark:text-zinc-100`。
|
||||
|
||||
**Props 接口重构**:
|
||||
|
||||
旧接口(4 个独立值/回调):
|
||||
|
||||
```typescript
|
||||
(normalizeToolCallId, preserveDeveloperRole, onNormalizeChange, onPreserveChange);
|
||||
```
|
||||
|
||||
新接口(3 个函数式 props):
|
||||
|
||||
```typescript
|
||||
effectiveModelNormalize: (protocol: string) => boolean
|
||||
effectiveModelPreserveDeveloper: (protocol: string) => boolean
|
||||
onCompatPatch: (protocol: string, payload: {...}) => void
|
||||
```
|
||||
|
||||
所有消费方(`ModelRow`、`PassthroughModelRow`、`CustomModelsSection`、`CompatibleModelsSection`)已同步更新。
|
||||
|
||||
**角标显示逻辑**:
|
||||
|
||||
- `anyNormalizeCompatBadge()`:任意协议或顶层存在 `normalizeToolCallId=true` 即显示「ID×9」角标。
|
||||
- `anyNoPreserveCompatBadge()`:任意协议或顶层存在 `preserveOpenAIDeveloperRole=false` 即显示「不保留」角标。
|
||||
|
||||
**CustomModelsSection 增强**:
|
||||
|
||||
- 新增 `modelCompatOverrides` 状态,从 API 响应中获取。
|
||||
- 新增 `saveCustomCompat()` 函数,支持仅传 `compatByProtocol` 的独立保存。
|
||||
|
||||
### 修复 6:前端 Map 查找性能优化(page.tsx)
|
||||
|
||||
**问题**:`effectiveNormalizeForProtocol` 等函数对 `customModels` 和 `modelCompatOverrides` 用 `Array.find()` 做 O(n) 查找,在列表渲染时每个模型行多次调用。
|
||||
|
||||
**方案**:使用 `useMemo` + `Map` 将数组预建为 O(1) 查找表。
|
||||
|
||||
```typescript
|
||||
type CompatModelMap = Map<string, CompatModelRow>;
|
||||
|
||||
function buildCompatMap(rows: CompatModelRow[]): CompatModelMap {
|
||||
const m = new Map<string, CompatModelRow>();
|
||||
for (const r of rows) if (r.id) m.set(r.id, r);
|
||||
return m;
|
||||
}
|
||||
|
||||
// 在组件内
|
||||
const customMap = useMemo(() => buildCompatMap(modelMeta.customModels), [modelMeta.customModels]);
|
||||
const overrideMap = useMemo(
|
||||
() => buildCompatMap(modelMeta.modelCompatOverrides),
|
||||
[modelMeta.modelCompatOverrides]
|
||||
);
|
||||
```
|
||||
|
||||
所有查找函数签名从 `(modelId, protocol, customModels[], overrides[])` 改为 `(modelId, protocol, customMap, overrideMap)`,内部使用 `Map.get()` 替代 `Array.find()`。
|
||||
|
||||
**优点**:
|
||||
|
||||
- 查找从 O(n) 降为 O(1)。
|
||||
- `useMemo` 依赖项正确,仅在数据变化时重建 Map。
|
||||
- `CustomModelsSection` 内部也独立构建 Map,不依赖父组件。
|
||||
|
||||
### 修复 7:ModelCompatPatch 类型修正(models.ts)
|
||||
|
||||
```typescript
|
||||
// 修复后 — 显式允许 null
|
||||
export type ModelCompatPatch = {
|
||||
normalizeToolCallId?: boolean;
|
||||
preserveOpenAIDeveloperRole?: boolean | null; // null = 取消设置/恢复默认
|
||||
compatByProtocol?: CompatByProtocolMap;
|
||||
};
|
||||
```
|
||||
|
||||
与 `mergeModelCompatOverride()` 内的 `=== null` 判断逻辑一致,类型安全。
|
||||
|
||||
### 修复 8:CompatByProtocolMap 类型收紧(page.tsx)
|
||||
|
||||
客户端 `CompatByProtocolMap` 从 `Record<string, ...>` 改为 `Record<ModelCompatProtocolKey, ...>`,增强类型安全,防止传入未知协议键。
|
||||
|
||||
### 修复 9:i18n 文案新增
|
||||
|
||||
| 键名 | 中文 | 英文 |
|
||||
| ------------------------------- | --------------------------------------------- | -------------------------------------------------------------- |
|
||||
| `compatProtocolLabel` | 客户端请求协议 | Client request protocol |
|
||||
| `compatProtocolHint` | 以下选项在 OmniRoute 识别到该请求形态时生效。 | These options apply when OmniRoute detects this request shape. |
|
||||
| `compatProtocolOpenAI` | OpenAI Chat Completions | OpenAI Chat Completions |
|
||||
| `compatProtocolOpenAIResponses` | OpenAI Responses API | OpenAI Responses API |
|
||||
| `compatProtocolClaude` | Anthropic Messages | Anthropic Messages |
|
||||
|
||||
---
|
||||
|
||||
## 四、使用方式
|
||||
|
||||
1. 点击模型行的 **「兼容性」** 按钮。
|
||||
2. 在弹层内先选择 **「客户端请求协议」**(OpenAI Chat / OpenAI Responses / Anthropic Messages)。
|
||||
3. 勾选该协议下的「工具 ID 9 位」或「不保留 developer 角色」。
|
||||
4. 保存后,仅在该协议形态的请求下生效。
|
||||
5. 未配置某协议时,该协议下行为回退到顶层兼容字段(若存在),再回退到默认值(保留 developer、不规范化 tool id)。
|
||||
6. 角标「ID×9」「不保留」在任意协议存在对应配置时显示。
|
||||
|
||||
---
|
||||
|
||||
## 五、预期效果
|
||||
|
||||
| 指标 | 修复前 | 修复后 |
|
||||
| ------------------------- | --------------------- | ------------------------------------------ |
|
||||
| 兼容性配置维度 | 全局(模型级) | 按协议(OpenAI Chat / Responses / Claude) |
|
||||
| developer 角色精确控制 | 不支持 | 支持(如:仅 Responses API 不保留) |
|
||||
| 前端兼容性查找性能 | O(n) Array.find | O(1) Map.get(useMemo 缓存) |
|
||||
| ModelCompatPatch 类型安全 | null 值无类型覆盖 | 显式 `boolean \| null` |
|
||||
| 客户端构建风险 | 可能引入 Node.js 模块 | 已隔离(shared/constants 层) |
|
||||
| API 验证 | 无 compatByProtocol | Zod strict schema 校验 |
|
||||
| 深色模式 | 协议选择器不可读 | bg/text 适配 dark 主题 |
|
||||
|
||||
---
|
||||
|
||||
## 六、涉及文件清单
|
||||
|
||||
| 区域 | 文件 | 改动类型 |
|
||||
| ---------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| 协议常量 | `src/shared/constants/modelCompat.ts` | **新建**,客户端安全的协议键与类型 |
|
||||
| 存储与读写 | `src/lib/db/models.ts` | `compatByProtocol` 数据结构、深度合并、getter 第三参 `sourceFormat`、`ModelCompatPatch` 类型修正 |
|
||||
| 再导出层 | `src/lib/localDb.ts` | 新增 `ModelCompatPatch` 类型导出 |
|
||||
| API 路由 | `src/app/api/provider-models/route.ts` | PUT 支持 `compatByProtocol`,使用 `ModelCompatPatch` 类型 |
|
||||
| 输入校验 | `src/shared/validation/schemas.ts` | `modelCompatPerProtocolSchema`(strict)+ `compatByProtocol` 记录校验 |
|
||||
| 请求管线 | `open-sse/handlers/chatCore.ts` | `getModelNormalizeToolCallId` / `getModelPreserveOpenAIDeveloperRole` 传入 `sourceFormat` |
|
||||
| 前端 UI | `src/app/(dashboard)/dashboard/providers/[id]/page.tsx` | 协议选择器、按协议解析/保存、角标逻辑、Map 性能优化、类型收紧 |
|
||||
| i18n | `src/i18n/messages/en.json`,`src/i18n/messages/zh-CN.json` | 5 条新文案 |
|
||||
|
||||
---
|
||||
|
||||
## 七、回退方案
|
||||
|
||||
- **禁用按协议配置**:删除 `compatByProtocol` 字段后,getter 自动回退到顶层字段,行为与 V2 一致。
|
||||
- **前端 Map 优化回退**:将 `Map.get()` 改回 `Array.find()` 即可,纯性能优化无功能耦合。
|
||||
- **客户端常量回退**:将 `MODEL_COMPAT_PROTOCOL_KEYS` 定义移回 `models.ts` 并从 `localDb.ts` 导出(需同时确保 `node:crypto` 问题不再存在)。
|
||||
- **生产环境**:以上修复对生产构建无负面影响。`compatByProtocol` 为可选字段,未配置时默认行为不变。API Zod 校验确保不会接受畸形数据。
|
||||
+23
-6
@@ -116,10 +116,8 @@ if (args.includes("--help") || args.includes("-h")) {
|
||||
|
||||
if (args.includes("--version") || args.includes("-v")) {
|
||||
try {
|
||||
const pkg = await import(join(ROOT, "package.json"), {
|
||||
with: { type: "json" },
|
||||
});
|
||||
console.log(pkg.default.version);
|
||||
const { version } = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8"));
|
||||
console.log(version);
|
||||
} catch {
|
||||
console.log("unknown");
|
||||
}
|
||||
@@ -189,8 +187,27 @@ const serverJs = join(APP_DIR, "server.js");
|
||||
|
||||
if (!existsSync(serverJs)) {
|
||||
console.error("\x1b[31m✖ Server not found at:\x1b[0m", serverJs);
|
||||
console.error(" This usually means the package was not built correctly.");
|
||||
console.error(" Try reinstalling: npm install -g omniroute");
|
||||
console.error(" The package may not have been built correctly.");
|
||||
console.error("");
|
||||
// (#492) Detect common non-standard Node managers that cause this issue
|
||||
const nodeExec = process.execPath || "";
|
||||
const isMise = nodeExec.includes("mise") || nodeExec.includes(".local/share/mise");
|
||||
const isNvm = nodeExec.includes(".nvm") || nodeExec.includes("nvm");
|
||||
if (isMise) {
|
||||
console.error(
|
||||
" \x1b[33m⚠ mise detected:\x1b[0m If you installed via `npm install -g omniroute`,"
|
||||
);
|
||||
console.error(" try: \x1b[36mnpx omniroute@latest\x1b[0m (downloads a fresh copy)");
|
||||
console.error(" or: \x1b[36mmise exec -- npx omniroute\x1b[0m");
|
||||
} else if (isNvm) {
|
||||
console.error(
|
||||
" \x1b[33m⚠ nvm detected:\x1b[0m Try reinstalling after loading the correct Node version:"
|
||||
);
|
||||
console.error(" \x1b[36mnvm use --lts && npm install -g omniroute\x1b[0m");
|
||||
} else {
|
||||
console.error(" Try: \x1b[36mnpm install -g omniroute\x1b[0m (reinstall)");
|
||||
console.error(" Or: \x1b[36mnpx omniroute@latest\x1b[0m");
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ services:
|
||||
container_name: omniroute-prod
|
||||
build:
|
||||
context: .
|
||||
target: runner-base
|
||||
target: runner-cli
|
||||
image: omniroute:prod
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
|
||||
@@ -59,6 +59,11 @@ services:
|
||||
ports:
|
||||
- "${DASHBOARD_PORT:-${PORT:-20128}}:${DASHBOARD_PORT:-${PORT:-20128}}"
|
||||
- "${API_PORT:-20129}:${API_PORT:-20129}"
|
||||
volumes:
|
||||
- omniroute-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
|
||||
profiles:
|
||||
- cli
|
||||
|
||||
|
||||
+43
-31
@@ -38,15 +38,20 @@ Content-Type: application/json
|
||||
|
||||
### Custom Headers
|
||||
|
||||
| Header | Direction | Description |
|
||||
| ------------------------ | --------- | --------------------------------- |
|
||||
| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
|
||||
| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
|
||||
| `Idempotency-Key` | Request | Dedup key (5s window) |
|
||||
| `X-Request-Id` | Request | Alternative dedup key |
|
||||
| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
|
||||
| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
|
||||
| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
|
||||
| Header | Direction | Description |
|
||||
| ------------------------ | --------- | ------------------------------------------------ |
|
||||
| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
|
||||
| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
|
||||
| `X-Session-Id` | Request | Sticky session key for external session affinity |
|
||||
| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
|
||||
| `Idempotency-Key` | Request | Dedup key (5s window) |
|
||||
| `X-Request-Id` | Request | Alternative dedup key |
|
||||
| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
|
||||
| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
|
||||
| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
|
||||
| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
|
||||
|
||||
> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
|
||||
|
||||
---
|
||||
|
||||
@@ -137,10 +142,10 @@ The provider prefix is auto-added if missing. Mismatched models return `400`.
|
||||
|
||||
```bash
|
||||
# Get cache stats
|
||||
GET /api/cache
|
||||
GET /api/cache/stats
|
||||
|
||||
# Clear all caches
|
||||
DELETE /api/cache
|
||||
DELETE /api/cache/stats
|
||||
```
|
||||
|
||||
Response example:
|
||||
@@ -211,23 +216,23 @@ Response example:
|
||||
|
||||
### Settings
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
| ------------------------------- | ------- | ---------------------- |
|
||||
| `/api/settings` | GET/PUT | General settings |
|
||||
| `/api/settings/proxy` | GET/PUT | Network proxy config |
|
||||
| `/api/settings/proxy/test` | POST | Test proxy connection |
|
||||
| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
|
||||
| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
|
||||
| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
|
||||
| Endpoint | Method | Description |
|
||||
| ------------------------------- | ------------- | ---------------------- |
|
||||
| `/api/settings` | GET/PUT/PATCH | General settings |
|
||||
| `/api/settings/proxy` | GET/PUT | Network proxy config |
|
||||
| `/api/settings/proxy/test` | POST | Test proxy connection |
|
||||
| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
|
||||
| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
|
||||
| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
|
||||
|
||||
### Monitoring
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
| ------------------------ | ---------- | ----------------------- |
|
||||
| `/api/sessions` | GET | Active session tracking |
|
||||
| `/api/rate-limits` | GET | Per-account rate limits |
|
||||
| `/api/monitoring/health` | GET | Health check |
|
||||
| `/api/cache` | GET/DELETE | Cache stats / clear |
|
||||
| Endpoint | Method | Description |
|
||||
| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| `/api/sessions` | GET | Active session tracking |
|
||||
| `/api/rate-limits` | GET | Per-account rate limits |
|
||||
| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
|
||||
| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
|
||||
|
||||
### Backup & Export/Import
|
||||
|
||||
@@ -248,6 +253,13 @@ Response example:
|
||||
| `/api/sync/initialize` | POST | Initialize sync |
|
||||
| `/api/cloud/*` | Various | Cloud management |
|
||||
|
||||
### Tunnels
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
| -------------------------- | ------ | ----------------------------------------------------------------------- |
|
||||
| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
|
||||
| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
|
||||
|
||||
### CLI Tools
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
@@ -272,12 +284,12 @@ GET response includes `agents[]` (id, name, binary, version, installed, protocol
|
||||
|
||||
### Resilience & Rate Limits
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
| ----------------------- | ------- | ------------------------------- |
|
||||
| `/api/resilience` | GET/PUT | Get/update resilience profiles |
|
||||
| `/api/resilience/reset` | POST | Reset circuit breakers |
|
||||
| `/api/rate-limits` | GET | Per-account rate limit status |
|
||||
| `/api/rate-limit` | GET | Global rate limit configuration |
|
||||
| Endpoint | Method | Description |
|
||||
| ----------------------- | --------- | ------------------------------- |
|
||||
| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
|
||||
| `/api/resilience/reset` | POST | Reset circuit breakers |
|
||||
| `/api/rate-limits` | GET | Per-account rate limit status |
|
||||
| `/api/rate-limit` | GET | Global rate limit configuration |
|
||||
|
||||
### Evals
|
||||
|
||||
|
||||
+55
-26
@@ -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-04_
|
||||
_Last updated: 2026-03-28_
|
||||
|
||||
## Executive Summary
|
||||
|
||||
@@ -65,6 +65,26 @@ Primary runtime model:
|
||||
- Provider SLA/control plane outside local process
|
||||
- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
|
||||
|
||||
## Dashboard Surface (Current)
|
||||
|
||||
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/costs` — cost aggregation and pricing visibility
|
||||
- `/dashboard/analytics` — usage analytics and evaluations
|
||||
- `/dashboard/limits` — quota/rate controls
|
||||
- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
|
||||
- `/dashboard/agents` — detected ACP agents + custom agent registration
|
||||
- `/dashboard/media` — image/video/music playground
|
||||
- `/dashboard/search-tools` — search provider testing and history
|
||||
- `/dashboard/health` — uptime, circuit breakers, rate limits
|
||||
- `/dashboard/logs` — request/proxy/audit/console logs
|
||||
- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
|
||||
- `/dashboard/api-manager` — API key lifecycle and model permissions
|
||||
|
||||
## High-Level System Context
|
||||
|
||||
```mermaid
|
||||
@@ -86,7 +106,7 @@ flowchart LR
|
||||
end
|
||||
|
||||
subgraph Upstreams[Upstream Providers]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/iFlow/GitHub/Kiro/Cursor/Antigravity]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
|
||||
P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
|
||||
P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
|
||||
end
|
||||
@@ -220,7 +240,7 @@ Domain layer modules:
|
||||
OAuth provider modules (12 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`, `iflow.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.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`
|
||||
- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
|
||||
|
||||
## 3) Persistence Layer
|
||||
@@ -254,8 +274,9 @@ Domain State DB (SQLite):
|
||||
|
||||
## 5) Cloud Sync
|
||||
|
||||
- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
|
||||
- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
|
||||
- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
|
||||
- Periodic task: `src/shared/services/modelSyncScheduler.ts`
|
||||
- Control route: `src/app/api/sync/cloud/route.ts`
|
||||
|
||||
## Request Lifecycle (`/v1/chat/completions`)
|
||||
@@ -335,7 +356,7 @@ flowchart TD
|
||||
Q -- No --> R[Return all unavailable]
|
||||
```
|
||||
|
||||
Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
|
||||
Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
|
||||
|
||||
## OAuth Onboarding and Token Refresh Lifecycle
|
||||
|
||||
@@ -593,7 +614,7 @@ Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/
|
||||
|
||||
| Executor | Provider(s) | Special Handling |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
|
||||
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, iFlow, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
|
||||
| `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 |
|
||||
@@ -617,7 +638,7 @@ 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 |
|
||||
| iFlow | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
|
||||
| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
|
||||
| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
@@ -665,25 +686,25 @@ Additional processing layers in the translation pipeline:
|
||||
|
||||
## Supported API Endpoints
|
||||
|
||||
| Endpoint | Format | Handler |
|
||||
| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
|
||||
| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
|
||||
| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
|
||||
| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
|
||||
| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
|
||||
| `GET /v1/embeddings` | Model listing | API route |
|
||||
| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
|
||||
| `GET /v1/images/generations` | Model listing | API route |
|
||||
| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
|
||||
| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
|
||||
| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
|
||||
| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
|
||||
| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
|
||||
| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
|
||||
| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
|
||||
| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
|
||||
| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
|
||||
| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
|
||||
| Endpoint | Format | Handler |
|
||||
| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
|
||||
| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
|
||||
| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
|
||||
| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
|
||||
| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
|
||||
| `GET /v1/embeddings` | Model listing | API route |
|
||||
| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
|
||||
| `GET /v1/images/generations` | Model listing | API route |
|
||||
| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
|
||||
| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
|
||||
| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
|
||||
| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
|
||||
| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
|
||||
| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
|
||||
| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
|
||||
| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
|
||||
| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
|
||||
| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
|
||||
|
||||
## Bypass Handler
|
||||
|
||||
@@ -735,10 +756,18 @@ Runtime visibility sources:
|
||||
|
||||
- console logs from `src/sse/utils/logger.ts`
|
||||
- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
|
||||
- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
|
||||
- textual request status log in `log.txt` (optional/compat)
|
||||
- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
|
||||
- dashboard usage endpoints (`/api/usage/*`) for UI consumption
|
||||
|
||||
Detailed request payload capture stores up to four JSON payload stages per routed call:
|
||||
|
||||
- raw request received from the client
|
||||
- translated request actually sent upstream
|
||||
- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
|
||||
- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
|
||||
|
||||
## Security-Sensitive Boundaries
|
||||
|
||||
- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
|
||||
|
||||
+35
-38
@@ -9,7 +9,7 @@ cost tracking, model switching, and request logging across every tool.
|
||||
## How It Works
|
||||
|
||||
```
|
||||
Claude / Codex / Gemini CLI / OpenCode / Cline / KiloCode / Continue / Kiro CLI
|
||||
Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
|
||||
│
|
||||
▼ (all point to OmniRoute)
|
||||
http://YOUR_SERVER:20128/v1
|
||||
@@ -27,21 +27,38 @@ Claude / Codex / Gemini CLI / OpenCode / Cline / KiloCode / Continue / Kiro CLI
|
||||
|
||||
---
|
||||
|
||||
## Supported Tools
|
||||
## Supported Tools (Dashboard Source of Truth)
|
||||
|
||||
| Tool | Command | Type | Install Method |
|
||||
| ---------------- | ------------------- | ----------------- | -------------- |
|
||||
| **Claude Code** | `claude` | CLI | npm |
|
||||
| **OpenAI Codex** | `codex` | CLI | npm |
|
||||
| **Gemini CLI** | `gemini` | CLI | npm |
|
||||
| **OpenCode** | `opencode` | CLI | npm |
|
||||
| **Cline** | `cline` | CLI + VS Code ext | npm |
|
||||
| **KiloCode** | `kilocode` / `kilo` | CLI + VS Code ext | npm |
|
||||
| **Continue** | guide-based | VS Code ext | VS Code |
|
||||
| **Kiro CLI** | `kiro-cli` | CLI | curl installer |
|
||||
| **Cursor** | `cursor` | Desktop app | Download |
|
||||
| **Droid** | web-based | Built-in agent | OmniRoute |
|
||||
| **OpenClaw** | web-based | Built-in agent | OmniRoute |
|
||||
The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
|
||||
Current list (v3.0.0-rc.16):
|
||||
|
||||
| Tool | ID | Command | Setup Mode | Install Method |
|
||||
| ---------------- | ------------- | ------------ | ---------- | -------------- |
|
||||
| **Claude Code** | `claude` | `claude` | env | npm |
|
||||
| **OpenAI Codex** | `codex` | `codex` | custom | npm |
|
||||
| **Factory Droid**| `droid` | `droid` | custom | bundled/CLI |
|
||||
| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
|
||||
| **Cursor** | `cursor` | app | guide | desktop app |
|
||||
| **Cline** | `cline` | `cline` | custom | npm |
|
||||
| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
|
||||
| **Continue** | `continue` | extension | guide | VS Code |
|
||||
| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
|
||||
| **GitHub Copilot**| `copilot` | extension | custom | VS Code |
|
||||
| **OpenCode** | `opencode` | `opencode` | guide | npm |
|
||||
| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
|
||||
|
||||
### CLI fingerprint sync (Agents + Settings)
|
||||
|
||||
`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
|
||||
This keeps provider IDs aligned with CLI cards and legacy IDs.
|
||||
|
||||
| CLI ID | Fingerprint Provider ID |
|
||||
| ------ | ----------------------- |
|
||||
| `kilo` | `kilocode` |
|
||||
| `copilot` | `github` |
|
||||
| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
|
||||
|
||||
Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
|
||||
|
||||
---
|
||||
|
||||
@@ -67,9 +84,6 @@ npm install -g @anthropic-ai/claude-code
|
||||
# OpenAI Codex
|
||||
npm install -g @openai/codex
|
||||
|
||||
# Gemini CLI (Google)
|
||||
npm install -g @google/gemini-cli
|
||||
|
||||
# OpenCode
|
||||
npm install -g opencode-ai
|
||||
|
||||
@@ -77,7 +91,7 @@ npm install -g opencode-ai
|
||||
npm install -g cline
|
||||
|
||||
# KiloCode
|
||||
npm install -g kilecode
|
||||
npm install -g kilocode
|
||||
|
||||
# Kiro CLI (Amazon — requires curl + unzip)
|
||||
apt-get install -y unzip # on Debian/Ubuntu
|
||||
@@ -90,7 +104,6 @@ export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
|
||||
```bash
|
||||
claude --version # 2.x.x
|
||||
codex --version # 0.x.x
|
||||
gemini --version # 0.x.x
|
||||
opencode --version # x.x.x
|
||||
cline --version # 2.x.x
|
||||
kilocode --version # x.x.x (or: kilo --version)
|
||||
@@ -153,21 +166,6 @@ EOF
|
||||
|
||||
---
|
||||
|
||||
### Gemini CLI
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
|
||||
{
|
||||
"apiKey": "sk-your-omniroute-key",
|
||||
"baseUrl": "http://localhost:20128/v1"
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
**Test:** `gemini "hello"`
|
||||
|
||||
---
|
||||
|
||||
### OpenCode
|
||||
|
||||
```bash
|
||||
@@ -324,17 +322,16 @@ They run as internal routes and use OmniRoute's model routing automatically.
|
||||
OMNIROUTE_URL="http://localhost:20128/v1"
|
||||
OMNIROUTE_KEY="sk-your-omniroute-key"
|
||||
|
||||
npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
|
||||
npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
|
||||
|
||||
# Kiro CLI
|
||||
apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
|
||||
|
||||
# Write configs
|
||||
mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
|
||||
mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
|
||||
|
||||
cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
|
||||
cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
|
||||
cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
|
||||
cat >> ~/.bashrc << EOF
|
||||
export OPENAI_BASE_URL="$OMNIROUTE_URL"
|
||||
export OPENAI_API_KEY="$OMNIROUTE_KEY"
|
||||
|
||||
@@ -267,7 +267,7 @@ Business logic that supports the handlers and executors.
|
||||
| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
|
||||
| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
|
||||
| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
|
||||
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, iFlow, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
|
||||
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
|
||||
| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
|
||||
| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
|
||||
| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
|
||||
@@ -539,7 +539,7 @@ A 2000-token buffer is added to reported usage to prevent clients from hitting c
|
||||
| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
|
||||
| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
|
||||
| Qwen | OAuth | Default | Standard auth |
|
||||
| iFlow | OAuth (Basic + Bearer) | Default | Dual auth header |
|
||||
| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
|
||||
| OpenRouter | API key | Default | Standard Bearer auth |
|
||||
| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
|
||||
| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
|
||||
|
||||
+5
-5
@@ -8,7 +8,7 @@ Visual guide to every section of the OmniRoute dashboard.
|
||||
|
||||
## 🔌 Providers
|
||||
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
|
||||

|
||||
|
||||
@@ -63,11 +63,11 @@ Customizable color themes for the entire dashboard. Choose from 7 preset colors
|
||||
Comprehensive settings panel with tabs:
|
||||
|
||||
- **General** — System storage, backup management (export/import database)
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
|
||||
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
|
||||
- **Routing** — Model aliases, background task degradation
|
||||
- **Resilience** — Rate limit persistence, circuit breaker tuning
|
||||
- **Advanced** — Configuration overrides
|
||||
- **Resilience** — Rate limit persistence, circuit breaker tuning, auto-disable banned accounts, provider expiration monitoring
|
||||
- **Advanced** — Configuration overrides, configuration audit trail, fallback degradation mode
|
||||
|
||||

|
||||
|
||||
@@ -108,7 +108,7 @@ Real-time request logging with filtering by provider, model, account, and API ke
|
||||
|
||||
## 🌐 API Endpoint
|
||||
|
||||
Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
|
||||
Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloudflare Quick Tunnel integration and cloud proxy support for remote access.
|
||||
|
||||

|
||||
|
||||
|
||||
+10
-10
@@ -38,16 +38,16 @@ See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot,
|
||||
|
||||
## Advanced Tools (8)
|
||||
|
||||
| Tool | Description |
|
||||
| :--------------------------------- | :---------------------------------------------- |
|
||||
| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
|
||||
| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
|
||||
| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
|
||||
| `omniroute_test_combo` | Live-test all models in a combo |
|
||||
| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
|
||||
| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
|
||||
| `omniroute_explain_route` | Explain a past routing decision |
|
||||
| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
|
||||
| Tool | Description |
|
||||
| :--------------------------------- | :---------------------------------------------------------- |
|
||||
| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
|
||||
| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
|
||||
| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
|
||||
| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
|
||||
| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
|
||||
| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
|
||||
| `omniroute_explain_route` | Explain a past routing decision |
|
||||
| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
|
||||
|
||||
## Authentication
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,
|
||||
|
||||
1. Check usage stats in Dashboard → Usage
|
||||
2. Switch primary model to GLM/MiniMax
|
||||
3. Use free tier (Gemini CLI, iFlow) for non-critical tasks
|
||||
3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
|
||||
4. Set cost budgets per API key: Dashboard → API Keys → Budget
|
||||
|
||||
---
|
||||
|
||||
+155
-23
@@ -39,11 +39,11 @@ Complete guide for configuring providers, creating combos, integrating CLI tools
|
||||
| **💰 CHEAP** | GLM-4.7 | $0.6/1M | Daily 10AM | Budget backup |
|
||||
| | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option |
|
||||
| | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost |
|
||||
| **🆓 FREE** | iFlow | $0 | Unlimited | 8 models free |
|
||||
| **🆓 FREE** | Qoder | $0 | Unlimited | 8 models free |
|
||||
| | Qwen | $0 | Unlimited | 3 models free |
|
||||
| | Kiro | $0 | Unlimited | Claude free |
|
||||
|
||||
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + iFlow (unlimited free) combo = $0 cost!
|
||||
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + Qoder (unlimited free) combo = $0 cost!
|
||||
|
||||
---
|
||||
|
||||
@@ -193,10 +193,10 @@ Models:
|
||||
|
||||
### 🆓 FREE Providers
|
||||
|
||||
#### iFlow (8 FREE models)
|
||||
#### Qoder (8 FREE models)
|
||||
|
||||
```bash
|
||||
Dashboard → Connect iFlow → OAuth login → Unlimited usage
|
||||
Dashboard → Connect Qoder → OAuth login → Unlimited usage
|
||||
|
||||
Models: if/kimi-k2-thinking, if/qwen3-coder-plus, if/glm-4.7, if/minimax-m2, if/deepseek-r1
|
||||
```
|
||||
@@ -405,25 +405,127 @@ docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-dat
|
||||
|
||||
For host-integrated mode with CLI binaries, see the Docker section in the main docs.
|
||||
|
||||
### Void Linux (xbps-src)
|
||||
|
||||
Void Linux users can package and install OmniRoute natively using the `xbps-src` cross-compilation framework. This automates the Node.js standalone build along with the required `better-sqlite3` native bindings.
|
||||
|
||||
<details>
|
||||
<summary><b>View xbps-src template</b></summary>
|
||||
|
||||
```bash
|
||||
# Template file for 'omniroute'
|
||||
pkgname=omniroute
|
||||
version=3.2.4
|
||||
revision=1
|
||||
hostmakedepends="nodejs python3 make"
|
||||
depends="openssl"
|
||||
short_desc="Universal AI gateway with smart routing for multiple LLM providers"
|
||||
maintainer="zenobit <zenobit@disroot.org>"
|
||||
license="MIT"
|
||||
homepage="https://github.com/diegosouzapw/OmniRoute"
|
||||
distfiles="https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz"
|
||||
checksum=009400afee90a9f32599d8fe734145cfd84098140b7287990183dde45ae2245b
|
||||
system_accounts="_omniroute"
|
||||
omniroute_homedir="/var/lib/omniroute"
|
||||
export NODE_ENV=production
|
||||
export npm_config_engine_strict=false
|
||||
export npm_config_loglevel=error
|
||||
export npm_config_fund=false
|
||||
export npm_config_audit=false
|
||||
|
||||
do_build() {
|
||||
# Determine target CPU arch for node-gyp
|
||||
local _gyp_arch
|
||||
case "$XBPS_TARGET_MACHINE" in
|
||||
aarch64*) _gyp_arch=arm64 ;;
|
||||
armv7*|armv6*) _gyp_arch=arm ;;
|
||||
i686*) _gyp_arch=ia32 ;;
|
||||
*) _gyp_arch=x64 ;;
|
||||
esac
|
||||
|
||||
# 1) Install all deps – skip scripts
|
||||
NODE_ENV=development npm ci --ignore-scripts
|
||||
|
||||
# 2) Build the Next.js standalone bundle
|
||||
npm run build
|
||||
|
||||
# 3) Copy static assets into standalone
|
||||
cp -r .next/static .next/standalone/.next/static
|
||||
[ -d public ] && cp -r public .next/standalone/public || true
|
||||
|
||||
# 4) Compile better-sqlite3 native binding
|
||||
local _node_gyp=/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js
|
||||
(cd node_modules/better-sqlite3 && node "$_node_gyp" rebuild --arch="$_gyp_arch")
|
||||
|
||||
# 5) Place the compiled binding into the standalone bundle
|
||||
local _bs3_release=.next/standalone/node_modules/better-sqlite3/build/Release
|
||||
mkdir -p "$_bs3_release"
|
||||
cp node_modules/better-sqlite3/build/Release/better_sqlite3.node "$_bs3_release/"
|
||||
|
||||
# 6) Remove arch-specific sharp bundles
|
||||
rm -rf .next/standalone/node_modules/@img
|
||||
|
||||
# 7) Copy pino runtime deps omitted by Next.js static analysis:
|
||||
for _mod in pino-abstract-transport split2 process-warning; do
|
||||
cp -r "node_modules/$_mod" .next/standalone/node_modules/
|
||||
done
|
||||
}
|
||||
|
||||
do_check() {
|
||||
npm run test:unit
|
||||
}
|
||||
|
||||
do_install() {
|
||||
vmkdir usr/lib/omniroute/.next
|
||||
vcopy .next/standalone/. usr/lib/omniroute/.next/standalone
|
||||
|
||||
# Prevent removal of empty Next.js app router dirs by the post-install hook
|
||||
for _d in \
|
||||
.next/standalone/.next/server/app/dashboard \
|
||||
.next/standalone/.next/server/app/dashboard/settings \
|
||||
.next/standalone/.next/server/app/dashboard/providers; do
|
||||
touch "${DESTDIR}/usr/lib/omniroute/${_d}/.keep"
|
||||
done
|
||||
|
||||
cat > "${WRKDIR}/omniroute" <<'EOF'
|
||||
#!/bin/sh
|
||||
export PORT="${PORT:-20128}"
|
||||
export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}"
|
||||
export LOG_TO_FILE="${LOG_TO_FILE:-false}"
|
||||
mkdir -p "${DATA_DIR}"
|
||||
exec node /usr/lib/omniroute/.next/standalone/server.js "$@"
|
||||
EOF
|
||||
vbin "${WRKDIR}/omniroute"
|
||||
}
|
||||
|
||||
post_install() {
|
||||
vlicense LICENSE
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
|
||||
| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
|
||||
| `INITIAL_PASSWORD` | `123456` | First login password |
|
||||
| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
|
||||
| `PORT` | framework default | Service port (`20128` in examples) |
|
||||
| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
|
||||
| `NODE_ENV` | runtime default | Set `production` for deploy |
|
||||
| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
|
||||
| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
|
||||
| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
|
||||
| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
|
||||
| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
|
||||
| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
|
||||
| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
|
||||
| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
|
||||
| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
|
||||
| Variable | Default | Description |
|
||||
| ------------------------- | ------------------------------------ | ---------------------------------------------------------------- |
|
||||
| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
|
||||
| `INITIAL_PASSWORD` | `123456` | First login password |
|
||||
| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
|
||||
| `PORT` | framework default | Service port (`20128` in examples) |
|
||||
| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
|
||||
| `NODE_ENV` | runtime default | Set `production` for deploy |
|
||||
| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
|
||||
| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
|
||||
| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
|
||||
| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
|
||||
| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
|
||||
| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
|
||||
| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
|
||||
| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
|
||||
| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
|
||||
| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
|
||||
| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
|
||||
|
||||
For the full environment variable reference, see the [README](../README.md).
|
||||
|
||||
@@ -446,7 +548,7 @@ For the full environment variable reference, see the [README](../README.md).
|
||||
|
||||
**MiniMax (`minimax/`)** — $0.2/1M: `minimax/MiniMax-M2.1`
|
||||
|
||||
**iFlow (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
|
||||
**Qoder (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
|
||||
|
||||
**Qwen (`qw/`)** — FREE: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`
|
||||
|
||||
@@ -494,6 +596,11 @@ curl -X POST http://localhost:20128/api/provider-models \
|
||||
|
||||
Or use Dashboard: **Providers → [Provider] → Custom Models**.
|
||||
|
||||
Notes:
|
||||
|
||||
- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
|
||||
- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
|
||||
|
||||
### Dedicated Provider Routes
|
||||
|
||||
Route requests directly to a specific provider with model validation:
|
||||
@@ -538,6 +645,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
|
||||
- Automatic background sync with timeout + fail-fast
|
||||
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
|
||||
|
||||
### Cloudflare Quick Tunnel
|
||||
|
||||
- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
|
||||
- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
|
||||
- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
|
||||
- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
|
||||
- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
|
||||
|
||||
### LLM Gateway Intelligence (Phase 9)
|
||||
|
||||
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
|
||||
@@ -578,6 +693,22 @@ Configure via **Dashboard → Settings → Routing**.
|
||||
| **Least Used** | Routes to the account with the oldest `lastUsedAt` timestamp, distributing traffic evenly |
|
||||
| **Cost Optimized** | Routes to the account with the lowest priority value, optimizing for lowest-cost providers |
|
||||
|
||||
#### External Sticky Session Header
|
||||
|
||||
For external session affinity (for example, Claude Code/Codex agents behind reverse proxies), send:
|
||||
|
||||
```http
|
||||
X-Session-Id: your-session-key
|
||||
```
|
||||
|
||||
OmniRoute also accepts `x_session_id` and returns the effective session key in `X-OmniRoute-Session-Id`.
|
||||
|
||||
If you use Nginx and send underscore-form headers, enable:
|
||||
|
||||
```nginx
|
||||
underscores_in_headers on;
|
||||
```
|
||||
|
||||
#### Wildcard Model Aliases
|
||||
|
||||
Create wildcard patterns to remap model names:
|
||||
@@ -667,10 +798,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
|
||||
|
||||
### Settings Dashboard
|
||||
|
||||
The settings page is organized into 5 tabs for easy navigation:
|
||||
The settings page is organized into 6 tabs for easy navigation:
|
||||
|
||||
| Tab | Contents |
|
||||
| -------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
|
||||
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
|
||||
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
|
||||
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
|
||||
|
||||
+32
-10
@@ -1,13 +1,35 @@
|
||||
# Multilingual Documentation
|
||||
# 🌐 Multilingual Documentation — 9router
|
||||
|
||||
This directory contains machine-assisted translations based on the English docs.
|
||||
Translations of documentation into 30 languages. Code blocks remain in English.
|
||||
|
||||
- **API_REFERENCE.md**: 🇺🇸 [English](../API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](./pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](./es/API_REFERENCE.md) | 🇫🇷 [Français](./fr/API_REFERENCE.md) | 🇮🇹 [Italiano](./it/API_REFERENCE.md) | 🇷🇺 [Русский](./ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](./zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](./de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](./in/API_REFERENCE.md) | 🇹🇭 [ไทย](./th/API_REFERENCE.md) | 🇺🇦 [Українська](./uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](./ar/API_REFERENCE.md) | 🇯🇵 [日本語](./ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](./vi/API_REFERENCE.md) | 🇧🇬 [Български](./bg/API_REFERENCE.md) | 🇩🇰 [Dansk](./da/API_REFERENCE.md) | 🇫🇮 [Suomi](./fi/API_REFERENCE.md) | 🇮🇱 [עברית](./he/API_REFERENCE.md) | 🇭🇺 [Magyar](./hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](./id/API_REFERENCE.md) | 🇰🇷 [한국어](./ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](./ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](./nl/API_REFERENCE.md) | 🇳🇴 [Norsk](./no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](./pt/API_REFERENCE.md) | 🇷🇴 [Română](./ro/API_REFERENCE.md) | 🇵🇱 [Polski](./pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](./sk/API_REFERENCE.md) | 🇸🇪 [Svenska](./sv/API_REFERENCE.md) | 🇵🇭 [Filipino](./phi/API_REFERENCE.md) | 🇨🇿 [Čeština](./cs/API_REFERENCE.md)
|
||||
- **ARCHITECTURE.md**: 🇺🇸 [English](../ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](./pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](./es/ARCHITECTURE.md) | 🇫🇷 [Français](./fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](./it/ARCHITECTURE.md) | 🇷🇺 [Русский](./ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](./zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](./de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](./in/ARCHITECTURE.md) | 🇹🇭 [ไทย](./th/ARCHITECTURE.md) | 🇺🇦 [Українська](./uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](./ar/ARCHITECTURE.md) | 🇯🇵 [日本語](./ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](./vi/ARCHITECTURE.md) | 🇧🇬 [Български](./bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](./da/ARCHITECTURE.md) | 🇫🇮 [Suomi](./fi/ARCHITECTURE.md) | 🇮🇱 [עברית](./he/ARCHITECTURE.md) | 🇭🇺 [Magyar](./hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](./id/ARCHITECTURE.md) | 🇰🇷 [한국어](./ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](./ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](./nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](./no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](./pt/ARCHITECTURE.md) | 🇷🇴 [Română](./ro/ARCHITECTURE.md) | 🇵🇱 [Polski](./pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](./sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](./sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](./phi/ARCHITECTURE.md) | 🇨🇿 [Čeština](./cs/ARCHITECTURE.md)
|
||||
- **CODEBASE_DOCUMENTATION.md**: 🇺🇸 [English](../CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](./pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](./es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](./fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](./it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](./ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](./zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](./de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](./in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](./th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](./uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](./ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](./ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](./vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](./bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](./da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](./fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](./he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](./hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](./id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](./ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](./ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](./nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](./no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](./pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](./ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](./pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](./sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](./sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](./phi/CODEBASE_DOCUMENTATION.md) | 🇨🇿 [Čeština](./cs/CODEBASE_DOCUMENTATION.md)
|
||||
- **FEATURES.md**: 🇺🇸 [English](../FEATURES.md) | 🇧🇷 [Português (Brasil)](./pt-BR/FEATURES.md) | 🇪🇸 [Español](./es/FEATURES.md) | 🇫🇷 [Français](./fr/FEATURES.md) | 🇮🇹 [Italiano](./it/FEATURES.md) | 🇷🇺 [Русский](./ru/FEATURES.md) | 🇨🇳 [中文 (简体)](./zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](./de/FEATURES.md) | 🇮🇳 [हिन्दी](./in/FEATURES.md) | 🇹🇭 [ไทย](./th/FEATURES.md) | 🇺🇦 [Українська](./uk-UA/FEATURES.md) | 🇸🇦 [العربية](./ar/FEATURES.md) | 🇯🇵 [日本語](./ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](./vi/FEATURES.md) | 🇧🇬 [Български](./bg/FEATURES.md) | 🇩🇰 [Dansk](./da/FEATURES.md) | 🇫🇮 [Suomi](./fi/FEATURES.md) | 🇮🇱 [עברית](./he/FEATURES.md) | 🇭🇺 [Magyar](./hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](./id/FEATURES.md) | 🇰🇷 [한국어](./ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](./ms/FEATURES.md) | 🇳🇱 [Nederlands](./nl/FEATURES.md) | 🇳🇴 [Norsk](./no/FEATURES.md) | 🇵🇹 [Português (Portugal)](./pt/FEATURES.md) | 🇷🇴 [Română](./ro/FEATURES.md) | 🇵🇱 [Polski](./pl/FEATURES.md) | 🇸🇰 [Slovenčina](./sk/FEATURES.md) | 🇸🇪 [Svenska](./sv/FEATURES.md) | 🇵🇭 [Filipino](./phi/FEATURES.md) | 🇨🇿 [Čeština](./cs/FEATURES.md)
|
||||
- **TROUBLESHOOTING.md**: 🇺🇸 [English](../TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](./pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](./es/TROUBLESHOOTING.md) | 🇫🇷 [Français](./fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](./it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](./ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](./zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](./de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](./in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](./th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](./uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](./ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](./ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](./vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](./bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](./da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](./fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](./he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](./hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](./id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](./ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](./ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](./nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](./no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](./pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](./ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](./pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](./sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](./sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](./phi/TROUBLESHOOTING.md) | 🇨🇿 [Čeština](./cs/TROUBLESHOOTING.md)
|
||||
- **USER_GUIDE.md**: 🇺🇸 [English](../USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](./pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](./es/USER_GUIDE.md) | 🇫🇷 [Français](./fr/USER_GUIDE.md) | 🇮🇹 [Italiano](./it/USER_GUIDE.md) | 🇷🇺 [Русский](./ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](./zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](./de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](./in/USER_GUIDE.md) | 🇹🇭 [ไทย](./th/USER_GUIDE.md) | 🇺🇦 [Українська](./uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](./ar/USER_GUIDE.md) | 🇯🇵 [日本語](./ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](./vi/USER_GUIDE.md) | 🇧🇬 [Български](./bg/USER_GUIDE.md) | 🇩🇰 [Dansk](./da/USER_GUIDE.md) | 🇫🇮 [Suomi](./fi/USER_GUIDE.md) | 🇮🇱 [עברית](./he/USER_GUIDE.md) | 🇭🇺 [Magyar](./hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](./id/USER_GUIDE.md) | 🇰🇷 [한국어](./ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](./ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](./nl/USER_GUIDE.md) | 🇳🇴 [Norsk](./no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](./pt/USER_GUIDE.md) | 🇷🇴 [Română](./ro/USER_GUIDE.md) | 🇵🇱 [Polski](./pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](./sk/USER_GUIDE.md) | 🇸🇪 [Svenska](./sv/USER_GUIDE.md) | 🇵🇭 [Filipino](./phi/USER_GUIDE.md) | 🇨🇿 [Čeština](./cs/USER_GUIDE.md)
|
||||
- **VM_DEPLOYMENT_GUIDE.md**: 🇺🇸 [English](../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](./pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](./es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](./fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](./it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](./ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](./zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](./de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](./in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](./th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](./uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](./ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](./ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](./vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](./bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](./da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](./fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](./he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](./hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](./id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](./ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](./ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](./nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](./no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](./pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](./ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](./pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](./sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](./sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](./phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](./cs/VM_DEPLOYMENT_GUIDE.md)
|
||||
---
|
||||
|
||||
Generated on 2026-03-19.
|
||||
- 🇪🇸 **Español** (`es`): [Docs Root](./es/README.md)
|
||||
- 🇫🇷 **Français** (`fr`): [Docs Root](./fr/README.md)
|
||||
- 🇩🇪 **Deutsch** (`de`): [Docs Root](./de/README.md)
|
||||
- 🇮🇹 **Italiano** (`it`): [Docs Root](./it/README.md)
|
||||
- 🇷🇺 **Русский** (`ru`): [Docs Root](./ru/README.md)
|
||||
- 🇨🇳 **中文(简体)** (`zh-CN`): [Docs Root](./zh-CN/README.md)
|
||||
- 🇯🇵 **日本語** (`ja`): [Docs Root](./ja/README.md)
|
||||
- 🇰🇷 **한국어** (`ko`): [Docs Root](./ko/README.md)
|
||||
- 🇸🇦 **العربية** (`ar`): [Docs Root](./ar/README.md)
|
||||
- 🇮🇳 **हिन्दी** (`in`): [Docs Root](./in/README.md)
|
||||
- 🇹🇭 **ไทย** (`th`): [Docs Root](./th/README.md)
|
||||
- 🇻🇳 **Tiếng Việt** (`vi`): [Docs Root](./vi/README.md)
|
||||
- 🇮🇩 **Bahasa Indonesia** (`id`): [Docs Root](./id/README.md)
|
||||
- 🇲🇾 **Bahasa Melayu** (`ms`): [Docs Root](./ms/README.md)
|
||||
- 🇳🇱 **Nederlands** (`nl`): [Docs Root](./nl/README.md)
|
||||
- 🇵🇱 **Polski** (`pl`): [Docs Root](./pl/README.md)
|
||||
- 🇸🇪 **Svenska** (`sv`): [Docs Root](./sv/README.md)
|
||||
- 🇳🇴 **Norsk** (`no`): [Docs Root](./no/README.md)
|
||||
- 🇩🇰 **Dansk** (`da`): [Docs Root](./da/README.md)
|
||||
- 🇫🇮 **Suomi** (`fi`): [Docs Root](./fi/README.md)
|
||||
- 🇵🇹 **Português (Portugal)** (`pt`): [Docs Root](./pt/README.md)
|
||||
- 🇷🇴 **Română** (`ro`): [Docs Root](./ro/README.md)
|
||||
- 🇭🇺 **Magyar** (`hu`): [Docs Root](./hu/README.md)
|
||||
- 🇧🇬 **Български** (`bg`): [Docs Root](./bg/README.md)
|
||||
- 🇸🇰 **Slovenčina** (`sk`): [Docs Root](./sk/README.md)
|
||||
- 🇺🇦 **Українська** (`uk-UA`): [Docs Root](./uk-UA/README.md)
|
||||
- 🇮🇱 **עברית** (`he`): [Docs Root](./he/README.md)
|
||||
- 🇵🇭 **Filipino** (`phi`): [Docs Root](./phi/README.md)
|
||||
- 🇧🇷 **Português (Brasil)** (`pt-BR`): [Docs Root](./pt-BR/README.md)
|
||||
|
||||
@@ -90,7 +90,7 @@ flowchart LR
|
||||
end
|
||||
|
||||
subgraph Upstreams[Upstream Providers]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/iFlow/GitHub/Kiro/Cursor/Antigravity]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
|
||||
P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
|
||||
P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
|
||||
end
|
||||
@@ -224,7 +224,7 @@ Domain layer modules:
|
||||
OAuth provider modules (12 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`, `iflow.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.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`
|
||||
- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
|
||||
|
||||
## 3) Persistence Layer
|
||||
@@ -597,7 +597,7 @@ Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/
|
||||
|
||||
| Executor | Provider(s) | Special Handling |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
|
||||
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, iFlow, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
|
||||
| `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 |
|
||||
@@ -621,7 +621,7 @@ 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 |
|
||||
| iFlow | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
|
||||
| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
|
||||
| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
@@ -271,7 +271,7 @@ Business logic that supports the handlers and executors.
|
||||
| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
|
||||
| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
|
||||
| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
|
||||
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, iFlow, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
|
||||
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
|
||||
| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
|
||||
| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
|
||||
| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
|
||||
@@ -543,7 +543,7 @@ A 2000-token buffer is added to reported usage to prevent clients from hitting c
|
||||
| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
|
||||
| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
|
||||
| Qwen | OAuth | Default | Standard auth |
|
||||
| iFlow | OAuth (Basic + Bearer) | Default | Dual auth header |
|
||||
| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
|
||||
| OpenRouter | API key | Default | Standard Bearer auth |
|
||||
| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
|
||||
| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
|
||||
|
||||
@@ -12,7 +12,7 @@ Visual guide to every section of the OmniRoute dashboard.
|
||||
|
||||
## 🔌 Providers
|
||||
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
|
||||

|
||||
|
||||
@@ -67,7 +67,7 @@ Customizable color themes for the entire dashboard. Choose from 7 preset colors
|
||||
Comprehensive settings panel with tabs:
|
||||
|
||||
- **General** — System storage, backup management (export/import database)
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
|
||||
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
|
||||
- **Routing** — Model aliases, background task degradation
|
||||
- **Resilience** — Rate limit persistence, circuit breaker tuning
|
||||
|
||||
+1160
-720
File diff suppressed because it is too large
Load Diff
@@ -101,7 +101,7 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,
|
||||
|
||||
1. Check usage stats in Dashboard → Usage
|
||||
2. Switch primary model to GLM/MiniMax
|
||||
3. Use free tier (Gemini CLI, iFlow) for non-critical tasks
|
||||
3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
|
||||
4. Set cost budgets per API key: Dashboard → API Keys → Budget
|
||||
|
||||
---
|
||||
|
||||
+127
-11
@@ -1,11 +1,11 @@
|
||||
🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
|
||||
# User Guide (العربية)
|
||||
|
||||
🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
|
||||
|
||||
> 🇺🇸 [English](../../USER_GUIDE.md)
|
||||
|
||||
---
|
||||
|
||||
# User Guide
|
||||
|
||||
🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md)
|
||||
|
||||
Complete guide for configuring providers, creating combos, integrating CLI tools, and deploying OmniRoute.
|
||||
|
||||
---
|
||||
@@ -43,11 +43,11 @@ Complete guide for configuring providers, creating combos, integrating CLI tools
|
||||
| **💰 CHEAP** | GLM-4.7 | $0.6/1M | Daily 10AM | Budget backup |
|
||||
| | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option |
|
||||
| | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost |
|
||||
| **🆓 FREE** | iFlow | $0 | Unlimited | 8 models free |
|
||||
| **🆓 FREE** | Qoder | $0 | Unlimited | 8 models free |
|
||||
| | Qwen | $0 | Unlimited | 3 models free |
|
||||
| | Kiro | $0 | Unlimited | Claude free |
|
||||
|
||||
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + iFlow (unlimited free) combo = $0 cost!
|
||||
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + Qoder (unlimited free) combo = $0 cost!
|
||||
|
||||
---
|
||||
|
||||
@@ -197,10 +197,10 @@ Models:
|
||||
|
||||
### 🆓 FREE Providers
|
||||
|
||||
#### iFlow (8 FREE models)
|
||||
#### Qoder (8 FREE models)
|
||||
|
||||
```bash
|
||||
Dashboard → Connect iFlow → OAuth login → Unlimited usage
|
||||
Dashboard → Connect Qoder → OAuth login → Unlimited usage
|
||||
|
||||
Models: if/kimi-k2-thinking, if/qwen3-coder-plus, if/glm-4.7, if/minimax-m2, if/deepseek-r1
|
||||
```
|
||||
@@ -409,6 +409,106 @@ docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-dat
|
||||
|
||||
For host-integrated mode with CLI binaries, see the Docker section in the main docs.
|
||||
|
||||
### Void Linux (xbps-src)
|
||||
|
||||
Void Linux users can package and install OmniRoute natively using the `xbps-src` cross-compilation framework. This automates the Node.js standalone build along with the required `better-sqlite3` native bindings.
|
||||
|
||||
<details>
|
||||
<summary><b>View xbps-src template</b></summary>
|
||||
|
||||
```bash
|
||||
# Template file for 'omniroute'
|
||||
pkgname=omniroute
|
||||
version=3.2.4
|
||||
revision=1
|
||||
hostmakedepends="nodejs python3 make"
|
||||
depends="openssl"
|
||||
short_desc="Universal AI gateway with smart routing for multiple LLM providers"
|
||||
maintainer="zenobit <zenobit@disroot.org>"
|
||||
license="MIT"
|
||||
homepage="https://github.com/diegosouzapw/OmniRoute"
|
||||
distfiles="https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz"
|
||||
checksum=009400afee90a9f32599d8fe734145cfd84098140b7287990183dde45ae2245b
|
||||
system_accounts="_omniroute"
|
||||
omniroute_homedir="/var/lib/omniroute"
|
||||
export NODE_ENV=production
|
||||
export npm_config_engine_strict=false
|
||||
export npm_config_loglevel=error
|
||||
export npm_config_fund=false
|
||||
export npm_config_audit=false
|
||||
|
||||
do_build() {
|
||||
# Determine target CPU arch for node-gyp
|
||||
local _gyp_arch
|
||||
case "$XBPS_TARGET_MACHINE" in
|
||||
aarch64*) _gyp_arch=arm64 ;;
|
||||
armv7*|armv6*) _gyp_arch=arm ;;
|
||||
i686*) _gyp_arch=ia32 ;;
|
||||
*) _gyp_arch=x64 ;;
|
||||
esac
|
||||
|
||||
# 1) Install all deps – skip scripts
|
||||
NODE_ENV=development npm ci --ignore-scripts
|
||||
|
||||
# 2) Build the Next.js standalone bundle
|
||||
npm run build
|
||||
|
||||
# 3) Copy static assets into standalone
|
||||
cp -r .next/static .next/standalone/.next/static
|
||||
[ -d public ] && cp -r public .next/standalone/public || true
|
||||
|
||||
# 4) Compile better-sqlite3 native binding
|
||||
local _node_gyp=/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js
|
||||
(cd node_modules/better-sqlite3 && node "$_node_gyp" rebuild --arch="$_gyp_arch")
|
||||
|
||||
# 5) Place the compiled binding into the standalone bundle
|
||||
local _bs3_release=.next/standalone/node_modules/better-sqlite3/build/Release
|
||||
mkdir -p "$_bs3_release"
|
||||
cp node_modules/better-sqlite3/build/Release/better_sqlite3.node "$_bs3_release/"
|
||||
|
||||
# 6) Remove arch-specific sharp bundles
|
||||
rm -rf .next/standalone/node_modules/@img
|
||||
|
||||
# 7) Copy pino runtime deps omitted by Next.js static analysis:
|
||||
for _mod in pino-abstract-transport split2 process-warning; do
|
||||
cp -r "node_modules/$_mod" .next/standalone/node_modules/
|
||||
done
|
||||
}
|
||||
|
||||
do_check() {
|
||||
npm run test:unit
|
||||
}
|
||||
|
||||
do_install() {
|
||||
vmkdir usr/lib/omniroute/.next
|
||||
vcopy .next/standalone/. usr/lib/omniroute/.next/standalone
|
||||
|
||||
# Prevent removal of empty Next.js app router dirs by the post-install hook
|
||||
for _d in \
|
||||
.next/standalone/.next/server/app/dashboard \
|
||||
.next/standalone/.next/server/app/dashboard/settings \
|
||||
.next/standalone/.next/server/app/dashboard/providers; do
|
||||
touch "${DESTDIR}/usr/lib/omniroute/${_d}/.keep"
|
||||
done
|
||||
|
||||
cat > "${WRKDIR}/omniroute" <<'EOF'
|
||||
#!/bin/sh
|
||||
export PORT="${PORT:-20128}"
|
||||
export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}"
|
||||
export LOG_TO_FILE="${LOG_TO_FILE:-false}"
|
||||
mkdir -p "${DATA_DIR}"
|
||||
exec node /usr/lib/omniroute/.next/standalone/server.js "$@"
|
||||
EOF
|
||||
vbin "${WRKDIR}/omniroute"
|
||||
}
|
||||
|
||||
post_install() {
|
||||
vlicense LICENSE
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
@@ -450,7 +550,7 @@ For the full environment variable reference, see the [README](../README.md).
|
||||
|
||||
**MiniMax (`minimax/`)** — $0.2/1M: `minimax/MiniMax-M2.1`
|
||||
|
||||
**iFlow (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
|
||||
**Qoder (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
|
||||
|
||||
**Qwen (`qw/`)** — FREE: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`
|
||||
|
||||
@@ -582,6 +682,22 @@ Configure via **Dashboard → Settings → Routing**.
|
||||
| **Least Used** | Routes to the account with the oldest `lastUsedAt` timestamp, distributing traffic evenly |
|
||||
| **Cost Optimized** | Routes to the account with the lowest priority value, optimizing for lowest-cost providers |
|
||||
|
||||
#### External Sticky Session Header
|
||||
|
||||
For external session affinity (for example, Claude Code/Codex agents behind reverse proxies), send:
|
||||
|
||||
```http
|
||||
X-Session-Id: your-session-key
|
||||
```
|
||||
|
||||
OmniRoute also accepts `x_session_id` and returns the effective session key in `X-OmniRoute-Session-Id`.
|
||||
|
||||
If you use Nginx and send underscore-form headers, enable:
|
||||
|
||||
```nginx
|
||||
underscores_in_headers on;
|
||||
```
|
||||
|
||||
#### Wildcard Model Aliases
|
||||
|
||||
Create wildcard patterns to remap model names:
|
||||
@@ -766,7 +882,7 @@ Access via **Dashboard → Health**. Real-time system health overview with 6 car
|
||||
|
||||
OmniRoute is available as a native desktop application for Windows, macOS, and Linux.
|
||||
|
||||
### Installation
|
||||
### تثبيت
|
||||
|
||||
```bash
|
||||
# From the electron directory:
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
# OmniRoute — Dashboard Features Gallery (العربية)
|
||||
|
||||
🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
|
||||
|
||||
---
|
||||
|
||||
Visual guide to every section of the OmniRoute dashboard.
|
||||
|
||||
---
|
||||
|
||||
## 🔌 Providers
|
||||
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🎨 Combos
|
||||
|
||||
Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 📊 Analytics
|
||||
|
||||
Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🏥 System Health
|
||||
|
||||
Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🔧 Translator Playground
|
||||
|
||||
Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🎮 Model Playground _(v2.0.9+)_
|
||||
|
||||
Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Themes _(v2.0.5+)_
|
||||
|
||||
Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Settings
|
||||
|
||||
Comprehensive settings panel with tabs:
|
||||
|
||||
- **General** — System storage, backup management (export/import database)
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
|
||||
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
|
||||
- **Routing** — Model aliases, background task degradation
|
||||
- **Resilience** — Rate limit persistence, circuit breaker tuning, auto-disable banned accounts, provider expiration monitoring
|
||||
- **Advanced** — Configuration overrides, configuration audit trail, fallback degradation mode
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🔧 CLI Tools
|
||||
|
||||
One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🤖 CLI Agents _(v2.0.11+)_
|
||||
|
||||
Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
|
||||
|
||||
- **Installation status** — Installed / Not Found with version detection
|
||||
- **Protocol badges** — stdio, HTTP, etc.
|
||||
- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
|
||||
- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
|
||||
|
||||
---
|
||||
|
||||
## 🖼️ 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.
|
||||
|
||||
---
|
||||
|
||||
## 📝 Request Logs
|
||||
|
||||
Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🌐 API Endpoint
|
||||
|
||||
Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloudflare Quick Tunnel integration and cloud proxy support for remote access.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🔑 API Key Management
|
||||
|
||||
Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Audit Log
|
||||
|
||||
Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ Desktop Application
|
||||
|
||||
Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
|
||||
|
||||
Key features:
|
||||
|
||||
- Server readiness polling (no blank screen on cold start)
|
||||
- System tray with port management
|
||||
- Content Security Policy
|
||||
- Single-instance lock
|
||||
- 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+)
|
||||
|
||||
📖 See [`electron/README.md`](../electron/README.md) for full documentation.
|
||||
@@ -90,7 +90,7 @@ flowchart LR
|
||||
end
|
||||
|
||||
subgraph Upstreams[Upstream Providers]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/iFlow/GitHub/Kiro/Cursor/Antigravity]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
|
||||
P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
|
||||
P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
|
||||
end
|
||||
@@ -224,7 +224,7 @@ Domain layer modules:
|
||||
OAuth provider modules (12 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`, `iflow.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.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`
|
||||
- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
|
||||
|
||||
## 3) Persistence Layer
|
||||
@@ -597,7 +597,7 @@ Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/
|
||||
|
||||
| Executor | Provider(s) | Special Handling |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
|
||||
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, iFlow, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
|
||||
| `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 |
|
||||
@@ -621,7 +621,7 @@ 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 |
|
||||
| iFlow | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
|
||||
| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
|
||||
| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
@@ -271,7 +271,7 @@ Business logic that supports the handlers and executors.
|
||||
| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
|
||||
| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
|
||||
| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
|
||||
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, iFlow, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
|
||||
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
|
||||
| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
|
||||
| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
|
||||
| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
|
||||
@@ -543,7 +543,7 @@ A 2000-token buffer is added to reported usage to prevent clients from hitting c
|
||||
| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
|
||||
| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
|
||||
| Qwen | OAuth | Default | Standard auth |
|
||||
| iFlow | OAuth (Basic + Bearer) | Default | Dual auth header |
|
||||
| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
|
||||
| OpenRouter | API key | Default | Standard Bearer auth |
|
||||
| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
|
||||
| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
|
||||
|
||||
@@ -12,7 +12,7 @@ Visual guide to every section of the OmniRoute dashboard.
|
||||
|
||||
## 🔌 Providers
|
||||
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
|
||||

|
||||
|
||||
@@ -67,7 +67,7 @@ Customizable color themes for the entire dashboard. Choose from 7 preset colors
|
||||
Comprehensive settings panel with tabs:
|
||||
|
||||
- **General** — System storage, backup management (export/import database)
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
|
||||
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
|
||||
- **Routing** — Model aliases, background task degradation
|
||||
- **Resilience** — Rate limit persistence, circuit breaker tuning
|
||||
|
||||
+1137
-705
File diff suppressed because it is too large
Load Diff
@@ -101,7 +101,7 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,
|
||||
|
||||
1. Check usage stats in Dashboard → Usage
|
||||
2. Switch primary model to GLM/MiniMax
|
||||
3. Use free tier (Gemini CLI, iFlow) for non-critical tasks
|
||||
3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
|
||||
4. Set cost budgets per API key: Dashboard → API Keys → Budget
|
||||
|
||||
---
|
||||
|
||||
+127
-11
@@ -1,11 +1,11 @@
|
||||
🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
|
||||
# User Guide (Български)
|
||||
|
||||
🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
|
||||
|
||||
> 🇺🇸 [English](../../USER_GUIDE.md)
|
||||
|
||||
---
|
||||
|
||||
# User Guide
|
||||
|
||||
🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md)
|
||||
|
||||
Complete guide for configuring providers, creating combos, integrating CLI tools, and deploying OmniRoute.
|
||||
|
||||
---
|
||||
@@ -43,11 +43,11 @@ Complete guide for configuring providers, creating combos, integrating CLI tools
|
||||
| **💰 CHEAP** | GLM-4.7 | $0.6/1M | Daily 10AM | Budget backup |
|
||||
| | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option |
|
||||
| | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost |
|
||||
| **🆓 FREE** | iFlow | $0 | Unlimited | 8 models free |
|
||||
| **🆓 FREE** | Qoder | $0 | Unlimited | 8 models free |
|
||||
| | Qwen | $0 | Unlimited | 3 models free |
|
||||
| | Kiro | $0 | Unlimited | Claude free |
|
||||
|
||||
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + iFlow (unlimited free) combo = $0 cost!
|
||||
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + Qoder (unlimited free) combo = $0 cost!
|
||||
|
||||
---
|
||||
|
||||
@@ -197,10 +197,10 @@ Models:
|
||||
|
||||
### 🆓 FREE Providers
|
||||
|
||||
#### iFlow (8 FREE models)
|
||||
#### Qoder (8 FREE models)
|
||||
|
||||
```bash
|
||||
Dashboard → Connect iFlow → OAuth login → Unlimited usage
|
||||
Dashboard → Connect Qoder → OAuth login → Unlimited usage
|
||||
|
||||
Models: if/kimi-k2-thinking, if/qwen3-coder-plus, if/glm-4.7, if/minimax-m2, if/deepseek-r1
|
||||
```
|
||||
@@ -409,6 +409,106 @@ docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-dat
|
||||
|
||||
For host-integrated mode with CLI binaries, see the Docker section in the main docs.
|
||||
|
||||
### Void Linux (xbps-src)
|
||||
|
||||
Void Linux users can package and install OmniRoute natively using the `xbps-src` cross-compilation framework. This automates the Node.js standalone build along with the required `better-sqlite3` native bindings.
|
||||
|
||||
<details>
|
||||
<summary><b>View xbps-src template</b></summary>
|
||||
|
||||
```bash
|
||||
# Template file for 'omniroute'
|
||||
pkgname=omniroute
|
||||
version=3.2.4
|
||||
revision=1
|
||||
hostmakedepends="nodejs python3 make"
|
||||
depends="openssl"
|
||||
short_desc="Universal AI gateway with smart routing for multiple LLM providers"
|
||||
maintainer="zenobit <zenobit@disroot.org>"
|
||||
license="MIT"
|
||||
homepage="https://github.com/diegosouzapw/OmniRoute"
|
||||
distfiles="https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz"
|
||||
checksum=009400afee90a9f32599d8fe734145cfd84098140b7287990183dde45ae2245b
|
||||
system_accounts="_omniroute"
|
||||
omniroute_homedir="/var/lib/omniroute"
|
||||
export NODE_ENV=production
|
||||
export npm_config_engine_strict=false
|
||||
export npm_config_loglevel=error
|
||||
export npm_config_fund=false
|
||||
export npm_config_audit=false
|
||||
|
||||
do_build() {
|
||||
# Determine target CPU arch for node-gyp
|
||||
local _gyp_arch
|
||||
case "$XBPS_TARGET_MACHINE" in
|
||||
aarch64*) _gyp_arch=arm64 ;;
|
||||
armv7*|armv6*) _gyp_arch=arm ;;
|
||||
i686*) _gyp_arch=ia32 ;;
|
||||
*) _gyp_arch=x64 ;;
|
||||
esac
|
||||
|
||||
# 1) Install all deps – skip scripts
|
||||
NODE_ENV=development npm ci --ignore-scripts
|
||||
|
||||
# 2) Build the Next.js standalone bundle
|
||||
npm run build
|
||||
|
||||
# 3) Copy static assets into standalone
|
||||
cp -r .next/static .next/standalone/.next/static
|
||||
[ -d public ] && cp -r public .next/standalone/public || true
|
||||
|
||||
# 4) Compile better-sqlite3 native binding
|
||||
local _node_gyp=/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js
|
||||
(cd node_modules/better-sqlite3 && node "$_node_gyp" rebuild --arch="$_gyp_arch")
|
||||
|
||||
# 5) Place the compiled binding into the standalone bundle
|
||||
local _bs3_release=.next/standalone/node_modules/better-sqlite3/build/Release
|
||||
mkdir -p "$_bs3_release"
|
||||
cp node_modules/better-sqlite3/build/Release/better_sqlite3.node "$_bs3_release/"
|
||||
|
||||
# 6) Remove arch-specific sharp bundles
|
||||
rm -rf .next/standalone/node_modules/@img
|
||||
|
||||
# 7) Copy pino runtime deps omitted by Next.js static analysis:
|
||||
for _mod in pino-abstract-transport split2 process-warning; do
|
||||
cp -r "node_modules/$_mod" .next/standalone/node_modules/
|
||||
done
|
||||
}
|
||||
|
||||
do_check() {
|
||||
npm run test:unit
|
||||
}
|
||||
|
||||
do_install() {
|
||||
vmkdir usr/lib/omniroute/.next
|
||||
vcopy .next/standalone/. usr/lib/omniroute/.next/standalone
|
||||
|
||||
# Prevent removal of empty Next.js app router dirs by the post-install hook
|
||||
for _d in \
|
||||
.next/standalone/.next/server/app/dashboard \
|
||||
.next/standalone/.next/server/app/dashboard/settings \
|
||||
.next/standalone/.next/server/app/dashboard/providers; do
|
||||
touch "${DESTDIR}/usr/lib/omniroute/${_d}/.keep"
|
||||
done
|
||||
|
||||
cat > "${WRKDIR}/omniroute" <<'EOF'
|
||||
#!/bin/sh
|
||||
export PORT="${PORT:-20128}"
|
||||
export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}"
|
||||
export LOG_TO_FILE="${LOG_TO_FILE:-false}"
|
||||
mkdir -p "${DATA_DIR}"
|
||||
exec node /usr/lib/omniroute/.next/standalone/server.js "$@"
|
||||
EOF
|
||||
vbin "${WRKDIR}/omniroute"
|
||||
}
|
||||
|
||||
post_install() {
|
||||
vlicense LICENSE
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
@@ -450,7 +550,7 @@ For the full environment variable reference, see the [README](../README.md).
|
||||
|
||||
**MiniMax (`minimax/`)** — $0.2/1M: `minimax/MiniMax-M2.1`
|
||||
|
||||
**iFlow (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
|
||||
**Qoder (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
|
||||
|
||||
**Qwen (`qw/`)** — FREE: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`
|
||||
|
||||
@@ -582,6 +682,22 @@ Configure via **Dashboard → Settings → Routing**.
|
||||
| **Least Used** | Routes to the account with the oldest `lastUsedAt` timestamp, distributing traffic evenly |
|
||||
| **Cost Optimized** | Routes to the account with the lowest priority value, optimizing for lowest-cost providers |
|
||||
|
||||
#### External Sticky Session Header
|
||||
|
||||
For external session affinity (for example, Claude Code/Codex agents behind reverse proxies), send:
|
||||
|
||||
```http
|
||||
X-Session-Id: your-session-key
|
||||
```
|
||||
|
||||
OmniRoute also accepts `x_session_id` and returns the effective session key in `X-OmniRoute-Session-Id`.
|
||||
|
||||
If you use Nginx and send underscore-form headers, enable:
|
||||
|
||||
```nginx
|
||||
underscores_in_headers on;
|
||||
```
|
||||
|
||||
#### Wildcard Model Aliases
|
||||
|
||||
Create wildcard patterns to remap model names:
|
||||
@@ -766,7 +882,7 @@ Access via **Dashboard → Health**. Real-time system health overview with 6 car
|
||||
|
||||
OmniRoute is available as a native desktop application for Windows, macOS, and Linux.
|
||||
|
||||
### Installation
|
||||
### Инсталиране
|
||||
|
||||
```bash
|
||||
# From the electron directory:
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
# OmniRoute — Dashboard Features Gallery (Български)
|
||||
|
||||
🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
|
||||
|
||||
---
|
||||
|
||||
Visual guide to every section of the OmniRoute dashboard.
|
||||
|
||||
---
|
||||
|
||||
## 🔌 Providers
|
||||
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🎨 Combos
|
||||
|
||||
Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 📊 Analytics
|
||||
|
||||
Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🏥 System Health
|
||||
|
||||
Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🔧 Translator Playground
|
||||
|
||||
Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🎮 Model Playground _(v2.0.9+)_
|
||||
|
||||
Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Themes _(v2.0.5+)_
|
||||
|
||||
Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Settings
|
||||
|
||||
Comprehensive settings panel with tabs:
|
||||
|
||||
- **General** — System storage, backup management (export/import database)
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
|
||||
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
|
||||
- **Routing** — Model aliases, background task degradation
|
||||
- **Resilience** — Rate limit persistence, circuit breaker tuning, auto-disable banned accounts, provider expiration monitoring
|
||||
- **Advanced** — Configuration overrides, configuration audit trail, fallback degradation mode
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🔧 CLI Tools
|
||||
|
||||
One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🤖 CLI Agents _(v2.0.11+)_
|
||||
|
||||
Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
|
||||
|
||||
- **Installation status** — Installed / Not Found with version detection
|
||||
- **Protocol badges** — stdio, HTTP, etc.
|
||||
- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
|
||||
- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
|
||||
|
||||
---
|
||||
|
||||
## 🖼️ 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.
|
||||
|
||||
---
|
||||
|
||||
## 📝 Request Logs
|
||||
|
||||
Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🌐 API Endpoint
|
||||
|
||||
Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloudflare Quick Tunnel integration and cloud proxy support for remote access.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🔑 API Key Management
|
||||
|
||||
Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Audit Log
|
||||
|
||||
Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ Desktop Application
|
||||
|
||||
Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
|
||||
|
||||
Key features:
|
||||
|
||||
- Server readiness polling (no blank screen on cold start)
|
||||
- System tray with port management
|
||||
- Content Security Policy
|
||||
- Single-instance lock
|
||||
- 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+)
|
||||
|
||||
📖 See [`electron/README.md`](../electron/README.md) for full documentation.
|
||||
+117
-115
@@ -38,15 +38,17 @@ Content-Type: application/json
|
||||
|
||||
### Vlastní záhlaví
|
||||
|
||||
Záhlaví | Směr | Popis
|
||||
--- | --- | ---
|
||||
`X-OmniRoute-No-Cache` | Žádost | Nastavením na `true` se vynechá mezipaměť
|
||||
`X-OmniRoute-Progress` | Žádost | Nastaveno na `true` pro události průběhu
|
||||
`Idempotency-Key` | Žádost | Klíč pro deduplikaci (okno 5 s)
|
||||
`X-Request-Id` | Žádost | Alternativní klíč pro odstranění duplicitních dat
|
||||
`X-OmniRoute-Cache` | Odpověď | `HIT` or `MISS` (nestreamované)
|
||||
`X-OmniRoute-Idempotent` | Odpověď | `true` , pokud je odstraněna duplikace
|
||||
`X-OmniRoute-Progress` | Odpověď | `enabled` pokud je zapnuto sledování průběhu
|
||||
| Záhlaví | Směr | Popis |
|
||||
| ------------------------ | ------- | ------------------------------------------------- |
|
||||
| `X-OmniRoute-No-Cache` | Žádost | Nastavením na `true` se vynechá mezipaměť |
|
||||
| `X-OmniRoute-Progress` | Žádost | Nastaveno na `true` pro události průběhu |
|
||||
| `Idempotency-Key` | Žádost | Klíč pro deduplikaci (okno 5 s) |
|
||||
| `X-Request-Id` | Žádost | Alternativní klíč pro odstranění duplicitních dat |
|
||||
| `X-OmniRoute-Cache` | Odpověď | `HIT` or `MISS` (nestreamované) |
|
||||
| `X-OmniRoute-Idempotent` | Odpověď | `true` , pokud je odstraněna duplikace |
|
||||
| `X-OmniRoute-Progress` | Odpověď | `enabled` pokud je zapnuto sledování průběhu |
|
||||
|
||||
> Poznámka Nginx: pokud spoléháte na hlavičky s podtržítkem (například `x_session_id`), povolte `underscores_in_headers on;`.
|
||||
|
||||
---
|
||||
|
||||
@@ -108,18 +110,18 @@ Authorization: Bearer your-api-key
|
||||
|
||||
## Koncové body kompatibility
|
||||
|
||||
Metoda | Cesta | Formát
|
||||
--- | --- | ---
|
||||
ZVEŘEJNIT | `/v1/chat/completions` | OpenAI
|
||||
ZVEŘEJNIT | `/v1/messages` | Antropický
|
||||
ZVEŘEJNIT | `/v1/responses` | Reakce OpenAI
|
||||
ZVEŘEJNIT | `/v1/embeddings` | OpenAI
|
||||
ZVEŘEJNIT | `/v1/images/generations` | OpenAI
|
||||
ZÍSKAT | `/v1/models` | OpenAI
|
||||
ZVEŘEJNIT | `/v1/messages/count_tokens` | Antropický
|
||||
ZÍSKAT | `/v1beta/models` | Blíženci
|
||||
ZVEŘEJNIT | `/v1beta/models/{...path}` | Gemini generuje obsah
|
||||
ZVEŘEJNIT | `/v1/api/chat` | Ollama
|
||||
| Metoda | Cesta | Formát |
|
||||
| ------ | --------------------------- | --------------------- |
|
||||
| POST | `/v1/chat/completions` | OpenAI |
|
||||
| POST | `/v1/messages` | Anthropic |
|
||||
| POST | `/v1/responses` | Reakce OpenAI |
|
||||
| POST | `/v1/embeddings` | OpenAI |
|
||||
| POST | `/v1/images/generations` | OpenAI |
|
||||
| GET | `/v1/models` | OpenAI |
|
||||
| POST | `/v1/messages/count_tokens` | Anthropic |
|
||||
| GET | `/v1beta/models` | Blíženci |
|
||||
| POST | `/v1beta/models/{...path}` | Gemini generuje obsah |
|
||||
| POST | `/v1/api/chat` | Ollama |
|
||||
|
||||
### Vyhrazené trasy poskytovatelů
|
||||
|
||||
@@ -166,154 +168,154 @@ Příklad odpovědi:
|
||||
|
||||
### Ověřování
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/auth/login` | ZVEŘEJNIT | Přihlášení
|
||||
`/api/auth/logout` | ZVEŘEJNIT | Odhlásit se
|
||||
`/api/settings/require-login` | ZÍSKAT/VLOŽIT | Vyžaduje se přepnutí přihlášení
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| ----------------------------- | ------- | ------------------------------- |
|
||||
| `/api/auth/login` | POST | Přihlášení |
|
||||
| `/api/auth/logout` | POST | Odhlásit se |
|
||||
| `/api/settings/require-login` | GET/PUT | Vyžaduje se přepnutí přihlášení |
|
||||
|
||||
### Správa poskytovatelů
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/providers` | ZÍSKAT/ODESLAT | Seznam / vytvoření poskytovatelů
|
||||
`/api/providers/[id]` | ZÍSKAT/VLOŽIT/ODSTRANIT | Správa poskytovatele
|
||||
`/api/providers/[id]/test` | ZVEŘEJNIT | Testovací připojení poskytovatele
|
||||
`/api/providers/[id]/models` | ZÍSKAT | Seznam modelů poskytovatelů
|
||||
`/api/providers/validate` | ZVEŘEJNIT | Ověření konfigurace poskytovatele
|
||||
`/api/provider-nodes*` | Různé | Správa uzlů poskytovatelů
|
||||
`/api/provider-models` | ZÍSKAT/ODESLAT/SMAZAT | Vlastní modely
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| ---------------------------- | --------------- | --------------------------------- |
|
||||
| `/api/providers` | GET/POST | Seznam / vytvoření poskytovatelů |
|
||||
| `/api/providers/[id]` | GET/PUT/DELETE | Správa poskytovatele |
|
||||
| `/api/providers/[id]/test` | POST | Testovací připojení poskytovatele |
|
||||
| `/api/providers/[id]/models` | GET | Seznam modelů poskytovatelů |
|
||||
| `/api/providers/validate` | POST | Ověření konfigurace poskytovatele |
|
||||
| `/api/provider-nodes*` | Různé | Správa uzlů poskytovatelů |
|
||||
| `/api/provider-models` | GET/POST/DELETE | Vlastní modely |
|
||||
|
||||
### Toky OAuth
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/oauth/[provider]/[action]` | Různé | OAuth specifický pro poskytovatele
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| -------------------------------- | ------ | ---------------------------------- |
|
||||
| `/api/oauth/[provider]/[action]` | Různé | OAuth specifický pro poskytovatele |
|
||||
|
||||
### Směrování a konfigurace
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/models/alias` | ZÍSKAT/ODESLAT | Aliasy modelů
|
||||
`/api/models/catalog` | ZÍSKAT | Všechny modely podle poskytovatele + typu
|
||||
`/api/combos*` | Různé | Správa kombinací
|
||||
`/api/keys*` | Různé | Správa klíčů API
|
||||
`/api/pricing` | ZÍSKAT | Cena modelu
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| --------------------- | -------- | ----------------------------------------- |
|
||||
| `/api/models/alias` | GET/POST | Aliasy modelů |
|
||||
| `/api/models/catalog` | GET | Všechny modely podle poskytovatele + typu |
|
||||
| `/api/combos*` | Různé | Správa kombinací |
|
||||
| `/api/keys*` | Různé | Správa klíčů API |
|
||||
| `/api/pricing` | GET | Cena modelu |
|
||||
|
||||
### Využití a analýzy
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/usage/history` | ZÍSKAT | Historie používání
|
||||
`/api/usage/logs` | ZÍSKAT | Protokoly používání
|
||||
`/api/usage/request-logs` | ZÍSKAT | Protokoly na úrovni požadavků
|
||||
`/api/usage/[connectionId]` | ZÍSKAT | Využití na připojení
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| --------------------------- | ------ | ----------------------------- |
|
||||
| `/api/usage/history` | GET | Historie používání |
|
||||
| `/api/usage/logs` | GET | Protokoly používání |
|
||||
| `/api/usage/request-logs` | GET | Protokoly na úrovni požadavků |
|
||||
| `/api/usage/[connectionId]` | GET | Využití na připojení |
|
||||
|
||||
### Nastavení
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/settings` | ZÍSKAT/VLOŽIT | Obecná nastavení
|
||||
`/api/settings/proxy` | ZÍSKAT/VLOŽIT | Konfigurace síťového proxy serveru
|
||||
`/api/settings/proxy/test` | ZVEŘEJNIT | Testovací připojení k proxy serveru
|
||||
`/api/settings/ip-filter` | ZÍSKAT/VLOŽIT | Seznam povolených/blokovaných IP adres
|
||||
`/api/settings/thinking-budget` | ZÍSKAT/VLOŽIT | Zdůvodnění rozpočtu tokenů
|
||||
`/api/settings/system-prompt` | ZÍSKAT/VLOŽIT | Globální systémový výzva
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| ------------------------------- | ------- | -------------------------------------- |
|
||||
| `/api/settings` | GET/PUT | Obecná nastavení |
|
||||
| `/api/settings/proxy` | GET/PUT | Konfigurace síťového proxy serveru |
|
||||
| `/api/settings/proxy/test` | POST | Testovací připojení k proxy serveru |
|
||||
| `/api/settings/ip-filter` | GET/PUT | Seznam povolených/blokovaných IP adres |
|
||||
| `/api/settings/thinking-budget` | GET/PUT | Zdůvodnění rozpočtu tokenů |
|
||||
| `/api/settings/system-prompt` | GET/PUT | Globální systémový výzva |
|
||||
|
||||
### Monitorování
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/sessions` | ZÍSKAT | Sledování aktivních relací
|
||||
`/api/rate-limits` | ZÍSKAT | Limity sazeb na účet
|
||||
`/api/monitoring/health` | ZÍSKAT | Kontrola stavu
|
||||
`/api/cache` | ZÍSKAT/SMAZAT | Statistiky mezipaměti / vymazat
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| ------------------------ | ---------- | ------------------------------- |
|
||||
| `/api/sessions` | GET | Sledování aktivních relací |
|
||||
| `/api/rate-limits` | GET | Limity sazeb na účet |
|
||||
| `/api/monitoring/health` | GET | Kontrola stavu |
|
||||
| `/api/cache` | GET/DELETE | Statistiky mezipaměti / vymazat |
|
||||
|
||||
### Zálohování a export/import
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/db-backups` | ZÍSKAT | Seznam dostupných záloh
|
||||
`/api/db-backups` | DÁT | Vytvořte ruční zálohu
|
||||
`/api/db-backups` | ZVEŘEJNIT | Obnovení z konkrétní zálohy
|
||||
`/api/db-backups/export` | ZÍSKAT | Stáhnout databázi jako soubor .sqlite
|
||||
`/api/db-backups/import` | ZVEŘEJNIT | Nahrajte soubor .sqlite pro nahrazení databáze
|
||||
`/api/db-backups/exportAll` | ZÍSKAT | Stáhnout plnou zálohu jako archiv .tar.gz
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| --------------------------- | ------ | ---------------------------------------------- |
|
||||
| `/api/db-backups` | GET | Seznam dostupných záloh |
|
||||
| `/api/db-backups` | DÁT | Vytvořte ruční zálohu |
|
||||
| `/api/db-backups` | POST | Obnovení z konkrétní zálohy |
|
||||
| `/api/db-backups/export` | GET | Stáhnout databázi jako soubor .sqlite |
|
||||
| `/api/db-backups/import` | POST | Nahrajte soubor .sqlite pro nahrazení databáze |
|
||||
| `/api/db-backups/exportAll` | GET | Stáhnout plnou zálohu jako archiv .tar.gz |
|
||||
|
||||
### Synchronizace s cloudem
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/sync/cloud` | Různé | Operace synchronizace s cloudem
|
||||
`/api/sync/initialize` | ZVEŘEJNIT | Inicializovat synchronizaci
|
||||
`/api/cloud/*` | Různé | Správa cloudu
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| ---------------------- | ------ | ------------------------------- |
|
||||
| `/api/sync/cloud` | Různé | Operace synchronizace s cloudem |
|
||||
| `/api/sync/initialize` | POST | Inicializovat synchronizaci |
|
||||
| `/api/cloud/*` | Různé | Správa cloudu |
|
||||
|
||||
### Nástroje CLI
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/cli-tools/claude-settings` | ZÍSKAT | Stav Clauda CLI
|
||||
`/api/cli-tools/codex-settings` | ZÍSKAT | Stav příkazového řádku Codexu
|
||||
`/api/cli-tools/droid-settings` | ZÍSKAT | Stav příkazového řádku Droidu
|
||||
`/api/cli-tools/openclaw-settings` | ZÍSKAT | Stav rozhraní příkazového řádku OpenClaw
|
||||
`/api/cli-tools/runtime/[toolId]` | ZÍSKAT | Generické běhové prostředí CLI
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| ---------------------------------- | ------ | ---------------------------------------- |
|
||||
| `/api/cli-tools/claude-settings` | GET | Stav Clauda CLI |
|
||||
| `/api/cli-tools/codex-settings` | GET | Stav příkazového řádku Codexu |
|
||||
| `/api/cli-tools/droid-settings` | GET | Stav příkazového řádku Droidu |
|
||||
| `/api/cli-tools/openclaw-settings` | GET | Stav rozhraní příkazového řádku OpenClaw |
|
||||
| `/api/cli-tools/runtime/[toolId]` | GET | Generické běhové prostředí CLI |
|
||||
|
||||
Mezi odpovědi CLI patří: `installed` , `runnable` , `command` , `commandPath` , `runtimeMode` , `reason` .
|
||||
|
||||
### Agenti ACP
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/acp/agents` | ZÍSKAT | Zobrazit seznam všech detekovaných agentů (vestavěných + vlastních) se stavem
|
||||
`/api/acp/agents` | ZVEŘEJNIT | Přidat vlastního agenta nebo obnovit mezipaměť detekce
|
||||
`/api/acp/agents` | VYMAZAT | Odebrání vlastního agenta podle parametru dotazu `id`
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| ----------------- | ------- | ----------------------------------------------------------------------------- |
|
||||
| `/api/acp/agents` | GET | Zobrazit seznam všech detekovaných agentů (vestavěných + vlastních) se stavem |
|
||||
| `/api/acp/agents` | POST | Přidat vlastního agenta nebo obnovit mezipaměť detekce |
|
||||
| `/api/acp/agents` | VYMAZAT | Odebrání vlastního agenta podle parametru dotazu `id` |
|
||||
|
||||
Odpověď GET obsahuje `agents[]` (id, name, binary, version, installed, protocol, isCustom) a `summary` (total, installed, notFound, builtIn, custom).
|
||||
|
||||
### Odolnost a limity rychlosti
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/resilience` | ZÍSKAT/VLOŽIT | Získání/aktualizace profilů odolnosti
|
||||
`/api/resilience/reset` | ZVEŘEJNIT | Resetujte jističe
|
||||
`/api/rate-limits` | ZÍSKAT | Stav limitu sazby na účet
|
||||
`/api/rate-limit` | ZÍSKAT | Konfigurace globálního limitu rychlosti
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| ----------------------- | ------- | --------------------------------------- |
|
||||
| `/api/resilience` | GET/PUT | Získání/aktualizace profilů odolnosti |
|
||||
| `/api/resilience/reset` | POST | Resetujte jističe |
|
||||
| `/api/rate-limits` | GET | Stav limitu sazby na účet |
|
||||
| `/api/rate-limit` | GET | Konfigurace globálního limitu rychlosti |
|
||||
|
||||
### Evals
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/evals` | ZÍSKAT/ODESLAT | Vypsat eval sady / spustit vyhodnocení
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| ------------ | -------- | -------------------------------------- |
|
||||
| `/api/evals` | GET/POST | Vypsat eval sady / spustit vyhodnocení |
|
||||
|
||||
### Zásady
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/policies` | ZÍSKAT/ODESLAT/SMAZAT | Správa směrovacích zásad
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| --------------- | --------------- | ------------------------ |
|
||||
| `/api/policies` | GET/POST/DELETE | Správa směrovacích zásad |
|
||||
|
||||
### Dodržování
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/compliance/audit-log` | ZÍSKAT | Protokol auditu shody (poslední N)
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| --------------------------- | ------ | ---------------------------------- |
|
||||
| `/api/compliance/audit-log` | GET | Protokol auditu shody (poslední N) |
|
||||
|
||||
### v1beta (kompatibilní s Gemini)
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/v1beta/models` | ZÍSKAT | Seznam modelů ve formátu Gemini
|
||||
`/v1beta/models/{...path}` | ZVEŘEJNIT | Koncový bod Gemini `generateContent`
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| -------------------------- | ------ | ------------------------------------ |
|
||||
| `/v1beta/models` | GET | Seznam modelů ve formátu Gemini |
|
||||
| `/v1beta/models/{...path}` | POST | Koncový bod Gemini `generateContent` |
|
||||
|
||||
Tyto koncové body zrcadlí formát API Gemini pro klienty, kteří očekávají nativní kompatibilitu sady Gemini SDK.
|
||||
|
||||
### Interní / systémová API
|
||||
|
||||
Koncový bod | Metoda | Popis
|
||||
--- | --- | ---
|
||||
`/api/init` | ZÍSKAT | Kontrola inicializace aplikace (používá se při prvním spuštění)
|
||||
`/api/tags` | ZÍSKAT | Tagy modelů kompatibilní s Ollamou (pro klienty Ollamy)
|
||||
`/api/restart` | ZVEŘEJNIT | Spustit řádný restart serveru
|
||||
`/api/shutdown` | ZVEŘEJNIT | Spustit řádné vypnutí serveru
|
||||
| Koncový bod | Metoda | Popis |
|
||||
| --------------- | ------ | --------------------------------------------------------------- |
|
||||
| `/api/init` | GET | Kontrola inicializace aplikace (používá se při prvním spuštění) |
|
||||
| `/api/tags` | GET | Tagy modelů kompatibilní s Ollamou (pro klienty Ollamy) |
|
||||
| `/api/restart` | POST | Spustit řádný restart serveru |
|
||||
| `/api/shutdown` | POST | Spustit řádné vypnutí serveru |
|
||||
|
||||
> **Poznámka:** Tyto koncové body používá interně systém nebo pro kompatibilitu s klienty Ollama. Koncoví uživatelé je obvykle nevolají.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
🌐 **Jazyky:** 🇺🇸 [angličtina](ARCHITECTURE.md) | 🇧🇷 [Português (Brazílie)](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) | 🇩🇰 [Dánsko](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [maďarština](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonésie](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nizozemsko](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugalsko)](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) | 🇵🇭 [Filipínec](i18n/phi/ARCHITECTURE.md) | 🇨🇿 [Čeština](i18n/cs/ARCHITECTURE.md)
|
||||
|
||||
*Poslední aktualizace: 2026-03-04*
|
||||
_Poslední aktualizace: 2026-03-04_
|
||||
|
||||
## Shrnutí pro manažery
|
||||
|
||||
@@ -85,7 +85,7 @@ flowchart LR
|
||||
end
|
||||
|
||||
subgraph Upstreams[Upstream Providers]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/iFlow/GitHub/Kiro/Cursor/Antigravity]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
|
||||
P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
|
||||
P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
|
||||
end
|
||||
@@ -219,7 +219,7 @@ Moduly doménové vrstvy:
|
||||
Moduly poskytovatelů OAuth (12 jednotlivých souborů v adresáři `src/lib/oauth/providers/` ):
|
||||
|
||||
- Index registru: `src/lib/oauth/providers/index.ts`
|
||||
- Jednotliví poskytovatelé: `claude.ts` , `codex.ts` , `gemini.ts` , `antigravity.ts` , `iflow.ts` , `qwen.ts` , `kimi-coding.ts` , `github.ts` , `kiro.ts` , `cursor.ts` , `kilocode.ts` , `cline.ts`
|
||||
- Jednotliví poskytovatelé: `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`
|
||||
- Thin wrapper: `src/lib/oauth/providers.ts` — reexporty z jednotlivých modulů
|
||||
|
||||
## 3) Vrstva perzistence
|
||||
@@ -590,45 +590,45 @@ flowchart LR
|
||||
|
||||
Každý poskytovatel má specializovaný exekutor rozšiřující `BaseExecutor` (v `open-sse/executors/base.ts` ), který zajišťuje vytváření URL adres, konstrukci hlaviček, opakování s exponenciálním odkladem, hooky pro obnovení pověření a orchestrační metodu `execute()` .
|
||||
|
||||
Vykonavatel | Poskytovatel(é) | Speciální manipulace
|
||||
--- | --- | ---
|
||||
`DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, iFlow, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Konfigurace dynamické adresy URL/záhlaví pro každého poskytovatele
|
||||
`AntigravityExecutor` | Google Antigravitace | Vlastní ID projektů/relací, analýza Opakování po
|
||||
`CodexExecutor` | Kodex OpenAI | Vkládá systémové instrukce, vynucuje úsilí k uvažování
|
||||
`CursorExecutor` | IDE kurzoru | Protokol ConnectRPC, kódování Protobuf, podepisování požadavků pomocí kontrolního součtu
|
||||
`GithubExecutor` | GitHub Copilot | Aktualizace tokenu Copilot, hlavičky napodobující VSCode
|
||||
`KiroExecutor` | AWS CodeWhisperer/Kiro | Binární formát AWS EventStream → konverze SSE
|
||||
`GeminiCLIExecutor` | Rozhraní příkazového řádku Gemini | Cyklus obnovy tokenu Google OAuth
|
||||
| Vykonavatel | Poskytovatel(é) | Speciální manipulace |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
|
||||
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Konfigurace dynamické adresy URL/záhlaví pro každého poskytovatele |
|
||||
| `AntigravityExecutor` | Google Antigravity | Vlastní ID projektů/relací, analýza Opakování po |
|
||||
| `CodexExecutor` | OpenAI Codex | Vkládá systémové instrukce, vynucuje úsilí k uvažování |
|
||||
| `CursorExecutor` | IDE kurzoru | Protokol ConnectRPC, kódování Protobuf, podepisování požadavků pomocí kontrolního součtu |
|
||||
| `GithubExecutor` | GitHub Copilot | Aktualizace tokenu Copilot, hlavičky napodobující VSCode |
|
||||
| `KiroExecutor` | AWS CodeWhisperer/Kiro | Binární formát AWS EventStream → konverze SSE |
|
||||
| `GeminiCLIExecutor` | Gemini CLI | Cyklus obnovy tokenu Google OAuth |
|
||||
|
||||
Všichni ostatní poskytovatelé (včetně uzlů kompatibilních s vlastními funkcemi) používají `DefaultExecutor` .
|
||||
|
||||
## Matice kompatibility poskytovatelů
|
||||
|
||||
Poskytovatel | Formát | Autorizace | Proud | Nestreamované | Obnovení tokenu | API pro použití
|
||||
--- | --- | --- | --- | --- | --- | ---
|
||||
Claude | Claude | Klíč API / OAuth | ✅ | ✅ | ✅ | ⚠️ Pouze pro administrátory
|
||||
Blíženci | Blíženci | Klíč API / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloudová konzole
|
||||
Rozhraní příkazového řádku Gemini | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloudová konzole
|
||||
Antigravitace | antigravitace | OAuth | ✅ | ✅ | ✅ | ✅ Plná kvóta API
|
||||
OpenAI | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
Kodex | openai-odpovědi | OAuth | ✅ vynucený | ❌ | ✅ | ✅ Limity sazeb
|
||||
GitHub Copilot | otevřeno | OAuth + token Copilota | ✅ | ✅ | ✅ | ✅ Snímky kvót
|
||||
Kurzor | kurzor | Vlastní kontrolní součet | ✅ | ✅ | ❌ | ❌
|
||||
Kiro | Kiro | OIDC pro jednotné přihlašování AWS | ✅ (Stream událostí) | ❌ | ✅ | ✅ Limity použití
|
||||
Qwen | otevřeno | OAuth | ✅ | ✅ | ✅ | ⚠️ Na vyžádání
|
||||
iFlow | otevřeno | OAuth (základní) | ✅ | ✅ | ✅ | ⚠️ Na vyžádání
|
||||
OpenRouter | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
GLM/Kimi/MiniMax | Claude | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
Hluboké vyhledávání | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
Groq | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
xAI (Grok) | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
Mistral | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
Zmatek | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
Společně s umělou inteligencí | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
Ohňostroj s umělou inteligencí | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
Mozky | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
Soudržný | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
NVIDIA NIM | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌
|
||||
| Poskytovatel | Formát | Autorizace | Proud | Nestreamované | Obnovení tokenu | API pro použití |
|
||||
| ------------------------------ | --------------- | ---------------------------------- | -------------------- | ------------- | --------------- | --------------------------- |
|
||||
| Claude | Claude | Klíč API / OAuth | ✅ | ✅ | ✅ | ⚠️ Pouze pro administrátory |
|
||||
| Blíženci | Blíženci | Klíč API / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloudová konzole |
|
||||
| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloudová konzole |
|
||||
| Antigravity | antigravitace | OAuth | ✅ | ✅ | ✅ | ✅ Plná kvóta API |
|
||||
| OpenAI | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| Kodex | openai-odpovědi | OAuth | ✅ vynucený | ❌ | ✅ | ✅ Limity sazeb |
|
||||
| GitHub Copilot | otevřeno | OAuth + token Copilota | ✅ | ✅ | ✅ | ✅ Snímky kvót |
|
||||
| Kurzor | kurzor | Vlastní kontrolní součet | ✅ | ✅ | ❌ | ❌ |
|
||||
| Kiro | Kiro | OIDC pro jednotné přihlašování AWS | ✅ (Stream událostí) | ❌ | ✅ | ✅ Limity použití |
|
||||
| Qwen | otevřeno | OAuth | ✅ | ✅ | ✅ | ⚠️ Na vyžádání |
|
||||
| Qoder | otevřeno | OAuth (základní) | ✅ | ✅ | ✅ | ⚠️ Na vyžádání |
|
||||
| OpenRouter | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| GLM/Kimi/MiniMax | Claude | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| Hluboké vyhledávání | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| Groq | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| xAI (Grok) | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| Mistral | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| Zmatek | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| Společně s umělou inteligencí | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| Ohňostroj s umělou inteligencí | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| Mozky | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| Soudržný | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
| NVIDIA NIM | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
## Pokrytí překladů formátů
|
||||
|
||||
@@ -643,7 +643,7 @@ Cílové formáty zahrnují:
|
||||
|
||||
- Chat/Odpovědi v OpenAI
|
||||
- Claude
|
||||
- Obálka Gemini/Gemini-CLI/Antigravitace
|
||||
- Obálka Gemini/Gemini-CLI/Antigravity
|
||||
- Kiro
|
||||
- Kurzor
|
||||
|
||||
@@ -664,25 +664,25 @@ Další vrstvy zpracování v překladovém kanálu:
|
||||
|
||||
## Podporované koncové body API
|
||||
|
||||
Koncový bod | Formát | Psovod
|
||||
--- | --- | ---
|
||||
`POST /v1/chat/completions` | Chat s OpenAI | `src/sse/handlers/chat.ts`
|
||||
`POST /v1/messages` | Claude Messages | Stejný obslužný program (automaticky detekováno)
|
||||
`POST /v1/responses` | Reakce OpenAI | `open-sse/handlers/responsesHandler.ts`
|
||||
`POST /v1/embeddings` | Vkládání OpenAI | `open-sse/handlers/embeddings.ts`
|
||||
`GET /v1/embeddings` | Seznam modelů | Trasa API
|
||||
`POST /v1/images/generations` | Obrázky OpenAI | `open-sse/handlers/imageGeneration.ts`
|
||||
`GET /v1/images/generations` | Seznam modelů | Trasa API
|
||||
`POST /v1/providers/{provider}/chat/completions` | Chat s OpenAI | Vyhrazené pro každého poskytovatele s ověřováním modelu
|
||||
`POST /v1/providers/{provider}/embeddings` | Vkládání OpenAI | Vyhrazené pro každého poskytovatele s ověřováním modelu
|
||||
`POST /v1/providers/{provider}/images/generations` | Obrázky OpenAI | Vyhrazené pro každého poskytovatele s ověřováním modelu
|
||||
`POST /v1/messages/count_tokens` | Počet žetonů Claude | Trasa API
|
||||
`GET /v1/models` | Seznam modelů OpenAI | Trasa API (chat + vkládání + obrázek + vlastní modely)
|
||||
`GET /api/models/catalog` | Katalog | Všechny modely seskupené podle poskytovatele + typu
|
||||
`POST /v1beta/models/*:streamGenerateContent` | Rodák z Blíženců | Trasa API
|
||||
`GET/PUT/DELETE /api/settings/proxy` | Konfigurace proxy serveru | Konfigurace síťového proxy serveru
|
||||
`POST /api/settings/proxy/test` | Připojení proxy serveru | Koncový bod testu stavu/připojení proxy serveru
|
||||
`GET/POST/DELETE /api/provider-models` | Vlastní modely | Správa vlastních modelů pro každého poskytovatele
|
||||
| Koncový bod | Formát | Psovod |
|
||||
| -------------------------------------------------- | ------------------------- | ------------------------------------------------------- |
|
||||
| `POST /v1/chat/completions` | Chat s OpenAI | `src/sse/handlers/chat.ts` |
|
||||
| `POST /v1/messages` | Claude Messages | Stejný obslužný program (automaticky detekováno) |
|
||||
| `POST /v1/responses` | Reakce OpenAI | `open-sse/handlers/responsesHandler.ts` |
|
||||
| `POST /v1/embeddings` | Vkládání OpenAI | `open-sse/handlers/embeddings.ts` |
|
||||
| `GET /v1/embeddings` | Seznam modelů | Trasa API |
|
||||
| `POST /v1/images/generations` | Obrázky OpenAI | `open-sse/handlers/imageGeneration.ts` |
|
||||
| `GET /v1/images/generations` | Seznam modelů | Trasa API |
|
||||
| `POST /v1/providers/{provider}/chat/completions` | Chat s OpenAI | Vyhrazené pro každého poskytovatele s ověřováním modelu |
|
||||
| `POST /v1/providers/{provider}/embeddings` | Vkládání OpenAI | Vyhrazené pro každého poskytovatele s ověřováním modelu |
|
||||
| `POST /v1/providers/{provider}/images/generations` | Obrázky OpenAI | Vyhrazené pro každého poskytovatele s ověřováním modelu |
|
||||
| `POST /v1/messages/count_tokens` | Počet žetonů Claude | Trasa API |
|
||||
| `GET /v1/models` | Seznam modelů OpenAI | Trasa API (chat + vkládání + obrázek + vlastní modely) |
|
||||
| `GET /api/models/catalog` | Katalog | Všechny modely seskupené podle poskytovatele + typu |
|
||||
| `POST /v1beta/models/*:streamGenerateContent` | Rodák z Blíženců | Trasa API |
|
||||
| `GET/PUT/DELETE /api/settings/proxy` | Konfigurace proxy serveru | Konfigurace síťového proxy serveru |
|
||||
| `POST /api/settings/proxy/test` | Připojení proxy serveru | Koncový bod testu stavu/připojení proxy serveru |
|
||||
| `GET/POST/DELETE /api/provider-models` | Vlastní modely | Správa vlastních modelů pro každého poskytovatele |
|
||||
|
||||
## Obejít obslužnou rutinu
|
||||
|
||||
|
||||
+50
-50
@@ -52,11 +52,11 @@
|
||||
### 🚀 Vlastnosti
|
||||
|
||||
- **feat(search)** : Přidáno hřiště pro vyhledávání (10. koncový bod), stránka s nástroji pro vyhledávání s porovnáním poskytovatelů/kanálovým přeřazením/historií vyhledávání, lokální směrování pro přeřazení, ochrana autorizace ve vyhledávacím API (#443 od @Regis-RCR)
|
||||
- Nová trasa: `/dashboard/search-tools`
|
||||
- Položka postranního panelu v sekci Ladění
|
||||
- `GET /api/search/providers` a `GET /api/search/stats` s ochranou autorizace
|
||||
- Lokální směrování provider_nodes pro `/v1/rerank`
|
||||
- 30+ klíčů i18n ve vyhledávacím jmenném prostoru
|
||||
- Nová trasa: `/dashboard/search-tools`
|
||||
- Položka postranního panelu v sekci Ladění
|
||||
- `GET /api/search/providers` a `GET /api/search/stats` s ochranou autorizace
|
||||
- Lokální směrování provider_nodes pro `/v1/rerank`
|
||||
- 30+ klíčů i18n ve vyhledávacím jmenném prostoru
|
||||
|
||||
### 🐛 Opravy chyb
|
||||
|
||||
@@ -74,9 +74,9 @@
|
||||
### 🐛 Opravy chyb
|
||||
|
||||
- **oprava(codex)** : Blokování týdenních vyčerpávajících účtů v přímém záložním rozhraní API (#440)
|
||||
- Porovnávání prefixů `resolveQuotaWindow()` : `"weekly"` nyní odpovídá klíčům mezipaměti `"weekly (7d)"`
|
||||
- `applyCodexWindowPolicy()` správně vynucuje přepínání `useWeekly` / `use5h`
|
||||
- 4 nové regresní testy (celkem 766)
|
||||
- Porovnávání prefixů `resolveQuotaWindow()` : `"weekly"` nyní odpovídá klíčům mezipaměti `"weekly (7d)"`
|
||||
- `applyCodexWindowPolicy()` správně vynucuje přepínání `useWeekly` / `use5h`
|
||||
- 4 nové regresní testy (celkem 766)
|
||||
|
||||
---
|
||||
|
||||
@@ -87,8 +87,8 @@
|
||||
### 🐛 Opravy chyb
|
||||
|
||||
- **fix(logs)** : Oprava kontrastu světelného režimu v protokolech požadavků, tlačítek filtrů a kombinovaného odznaku (#378)
|
||||
- Tlačítka filtrů Chyba/Úspěch/Kombinace jsou nyní čitelná i ve světlém režimu.
|
||||
- Odznak kombinované řady používá ve světlém režimu silnější fialovou barvu
|
||||
- Tlačítka filtrů Chyba/Úspěch/Kombinace jsou nyní čitelná i ve světlém režimu.
|
||||
- Odznak kombinované řady používá ve světlém režimu silnější fialovou barvu
|
||||
|
||||
---
|
||||
|
||||
@@ -99,32 +99,32 @@
|
||||
### ✨ Nové funkce
|
||||
|
||||
- **feat(search)** : Sjednocené směrování webového vyhledávání — `POST /v1/search` s 5 poskytovateli (Serper, Brave, Perplexity, Exa, Tavily)
|
||||
- Automatické přepnutí napříč poskytovateli, více než 6 500 bezplatných vyhledávání/měsíc
|
||||
- Mezipaměť v paměti se slučováním požadavků (konfigurovatelné TTL)
|
||||
- Dashboard: Karta Analytika vyhledávání v `/dashboard/analytics` s rozpisem poskytovatelů, mírou zásahů do mezipaměti a sledováním nákladů
|
||||
- Nové API: `GET /api/v1/search/analytics` pro statistiky vyhledávacích požadavků
|
||||
- Migrace databáze: sloupec `request_type` v `call_logs` pro sledování požadavků mimo chat
|
||||
- Ověření Zod ( `v1SearchSchema` ), chráněné autorizací, náklady zaznamenány pomocí `recordCost()`
|
||||
- Automatické přepnutí napříč poskytovateli, více než 6 500 bezplatných vyhledávání/měsíc
|
||||
- Mezipaměť v paměti se slučováním požadavků (konfigurovatelné TTL)
|
||||
- Dashboard: Karta Analytika vyhledávání v `/dashboard/analytics` s rozpisem poskytovatelů, mírou zásahů do mezipaměti a sledováním nákladů
|
||||
- Nové API: `GET /api/v1/search/analytics` pro statistiky vyhledávacích požadavků
|
||||
- Migrace databáze: sloupec `request_type` v `call_logs` pro sledování požadavků mimo chat
|
||||
- Ověření Zod ( `v1SearchSchema` ), chráněné autorizací, náklady zaznamenány pomocí `recordCost()`
|
||||
|
||||
### 🔒 Bezpečnost
|
||||
|
||||
- **deps** : Next.js 16.1.6 → 16.1.7 — opravuje 6 CVE:
|
||||
- **Kritické** : CVE-2026-29057 (pašování HTTP požadavků přes http-proxy)
|
||||
- **Vysoká** : CVE-2026-27977, CVE-2026-27978 (WebSocket + akce serveru)
|
||||
- **Médium** : CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7
|
||||
- **Kritické** : CVE-2026-29057 (pašování HTTP požadavků přes http-proxy)
|
||||
- **Vysoká** : CVE-2026-27977, CVE-2026-27978 (WebSocket + akce serveru)
|
||||
- **Médium** : CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7
|
||||
|
||||
### 📁 Nové soubory
|
||||
|
||||
Soubor | Účel
|
||||
--- | ---
|
||||
`open-sse/handlers/search.ts` | Vyhledávací obslužná rutina s routováním 5 poskytovatelů
|
||||
`open-sse/config/searchRegistry.ts` | Registr poskytovatelů (autorizace, náklady, kvóta, TTL)
|
||||
`open-sse/services/searchCache.ts` | Mezipaměť v paměti se slučováním požadavků
|
||||
`src/app/api/v1/search/route.ts` | Trasa Next.js (POST + GET)
|
||||
`src/app/api/v1/search/analytics/route.ts` | API pro statistiky vyhledávání
|
||||
`src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Karta analytického panelu
|
||||
`src/lib/db/migrations/007_search_request_type.sql` | Migrace databáze
|
||||
`tests/unit/search-registry.test.mjs` | 277 řádků jednotkových testů
|
||||
| Soubor | Účel |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------- |
|
||||
| `open-sse/handlers/search.ts` | Vyhledávací obslužná rutina s routováním 5 poskytovatelů |
|
||||
| `open-sse/config/searchRegistry.ts` | Registr poskytovatelů (autorizace, náklady, kvóta, TTL) |
|
||||
| `open-sse/services/searchCache.ts` | Mezipaměť v paměti se slučováním požadavků |
|
||||
| `src/app/api/v1/search/route.ts` | Trasa Next.js (POST + GET) |
|
||||
| `src/app/api/v1/search/analytics/route.ts` | API pro statistiky vyhledávání |
|
||||
| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Karta analytického panelu |
|
||||
| `src/lib/db/migrations/007_search_request_type.sql` | Migrace databáze |
|
||||
| `tests/unit/search-registry.test.mjs` | 277 řádků jednotkových testů |
|
||||
|
||||
---
|
||||
|
||||
@@ -283,10 +283,10 @@ Soubor | Účel
|
||||
### 🐛 Opravy chyb
|
||||
|
||||
- **fix(providers)** : Odstraněny neexistující názvy modelů u 5 poskytovatelů:
|
||||
- **gemini / gemini-cli** : odstraněny `gemini-3.1-pro/flash` a `gemini-3-*-preview` (neexistují v Google API v1beta); nahrazeny `gemini-2.5-pro` , `gemini-2.5-flash` , `gemini-2.0-flash` , `gemini-1.5-pro/flash`
|
||||
- **antigravity** : odstraněny `gemini-3.1-pro-high/low` a `gemini-3-flash` (neplatné interní aliasy); nahrazeny skutečnými modely z verze 2.x
|
||||
- **github (Copilot)** : odstraněny `gemini-3-flash-preview` a `gemini-3-pro-preview` ; nahrazeny `gemini-2.5-flash`
|
||||
- **nvidia** : opraveno `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM používá pro modely Meta jmenný prostor `meta/` /); přidány `nvidia/llama-3.1-70b-instruct` a `nvidia/llama-3.1-405b-instruct`
|
||||
- **gemini / gemini-cli** : odstraněny `gemini-3.1-pro/flash` a `gemini-3-*-preview` (neexistují v Google API v1beta); nahrazeny `gemini-2.5-pro` , `gemini-2.5-flash` , `gemini-2.0-flash` , `gemini-1.5-pro/flash`
|
||||
- **antigravity** : odstraněny `gemini-3.1-pro-high/low` a `gemini-3-flash` (neplatné interní aliasy); nahrazeny skutečnými modely z verze 2.x
|
||||
- **github (Copilot)** : odstraněny `gemini-3-flash-preview` a `gemini-3-pro-preview` ; nahrazeny `gemini-2.5-flash`
|
||||
- **nvidia** : opraveno `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM používá pro modely Meta jmenný prostor `meta/` /); přidány `nvidia/llama-3.1-70b-instruct` a `nvidia/llama-3.1-405b-instruct`
|
||||
- **fix(db/combo)** : Aktualizováno `free-stack` combo na vzdálené databázi: odstraněno `qw/qwen3-coder-plus` (prošlý obnovovací token), opraveno `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct` , opraveno `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash` , přidáno `if/deepseek-v3.2`
|
||||
|
||||
---
|
||||
@@ -356,7 +356,7 @@ Soubor | Účel
|
||||
|
||||
- **oprava(média)** : ComfyUI a SD WebUI se již nezobrazují v seznamu poskytovatelů na stránce Média, pokud nejsou nakonfigurovány — při připojení načtou `/api/providers` a skryjí lokální poskytovatele bez připojení (#390)
|
||||
- **oprava(auth)** : Round-robin již po zpoždění znovu nevybírá účty s omezenou rychlostí ihned – `backoffLevel` se nyní používá jako primární třídicí klíč v rotaci LRU (#340)
|
||||
- **oprava(oauth)** : iFlow (a další poskytovatelé, kteří přesměrovávají na své vlastní uživatelské rozhraní) již nenechávají modální okno OAuth zaseknuté na „Čekání na autorizaci“ – detektor zavřených vyskakovacích oken automaticky přechází do režimu ručního zadávání URL (#344)
|
||||
- **oprava(oauth)** : Qoder (a další poskytovatelé, kteří přesměrovávají na své vlastní uživatelské rozhraní) již nenechávají modální okno OAuth zaseknuté na „Čekání na autorizaci“ – detektor zavřených vyskakovacích oken automaticky přechází do režimu ručního zadávání URL (#344)
|
||||
- **oprava(logy)** : Tabulka protokolů požadavků je nyní čitelná ve světlém režimu – stavové odznaky, počty tokenů a kombinované tagy používají adaptivní `dark:` barevné třídy (#378)
|
||||
|
||||
### ✨ Funkce
|
||||
@@ -508,7 +508,7 @@ Soubor | Účel
|
||||
### ✨ Nové funkce
|
||||
|
||||
- **Strategie směrování Fill-First a P2C** : Do výběru kombinované strategie přidány strategie `fill-first` (vyčerpání kvóty před přesunem) a `p2c` (výběr Power-of-Two-Choices s nízkou latencí) s kompletními panely s pokyny a barevně odlišenými odznaky.
|
||||
- **Přednastavené modely Free Stack** : Vytvoření kombinace pomocí šablony Free Stack nyní automaticky vyplní 7 nejlepších modelů bezplatných poskytovatelů ve své třídě (Gemini CLI, Kiro, iFlow×2, Qwen, NVIDIA NIM, Groq). Uživatelé stačí aktivovat poskytovatele a ihned získají kombinaci 0 $/měsíc.
|
||||
- **Přednastavené modely Free Stack** : Vytvoření kombinace pomocí šablony Free Stack nyní automaticky vyplní 7 nejlepších modelů bezplatných poskytovatelů ve své třídě (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Uživatelé stačí aktivovat poskytovatele a ihned získají kombinaci 0 $/měsíc.
|
||||
- **Širší kombo modální okno** : Modální okno pro vytvoření/úpravu komba nyní používá `max-w-4xl` pro pohodlnou úpravu velkých komb.
|
||||
|
||||
### 🐛 Opravy chyb
|
||||
@@ -554,13 +554,13 @@ Soubor | Účel
|
||||
|
||||
### 📁 Nové soubory
|
||||
|
||||
Soubor | Účel
|
||||
--- | ---
|
||||
`open-sse/services/taskAwareRouter.ts` | Logika směrování s ohledem na úlohy (7 typů úloh)
|
||||
`src/app/api/settings/task-routing/route.ts` | API pro konfiguraci směrování úloh
|
||||
`src/app/api/providers/[id]/refresh/route.ts` | Ruční aktualizace tokenu OAuth
|
||||
`src/lib/db/readCache.ts` | Efektivní mezipaměť pro čtení databáze
|
||||
`src/shared/utils/clipboard.ts` | Zpevněná schránka s funkcí
|
||||
| Soubor | Účel |
|
||||
| --------------------------------------------- | ------------------------------------------------- |
|
||||
| `open-sse/services/taskAwareRouter.ts` | Logika směrování s ohledem na úlohy (7 typů úloh) |
|
||||
| `src/app/api/settings/task-routing/route.ts` | API pro konfiguraci směrování úloh |
|
||||
| `src/app/api/providers/[id]/refresh/route.ts` | Ruční aktualizace tokenu OAuth |
|
||||
| `src/lib/db/readCache.ts` | Efektivní mezipaměť pro čtení databáze |
|
||||
| `src/shared/utils/clipboard.ts` | Zpevněná schránka s funkcí |
|
||||
|
||||
## [2.4.1] - 13. 3. 2026
|
||||
|
||||
@@ -574,7 +574,7 @@ Soubor | Účel
|
||||
|
||||
### ✨ Funkce
|
||||
|
||||
- **Kombinace: Šablona Free Stack** — Nová 4. šablona „Free Stack (0 $)“ využívající round-robin napříč Kiro + iFlow + Qwen + Gemini CLI. Při prvním použití doporučuje předpřipravenou kombinaci s nulovými náklady.
|
||||
- **Kombinace: Šablona Free Stack** — Nová 4. šablona „Free Stack (0 $)“ využívající round-robin napříč Kiro + Qoder + Qwen + Gemini CLI. Při prvním použití doporučuje předpřipravenou kombinaci s nulovými náklady.
|
||||
- **Média/Přepis: Deepgram jako výchozí** – Deepgram (Nova 3, 200 dolarů zdarma) je nyní výchozím poskytovatelem přepisu. AssemblyAI (50 dolarů zdarma) a Groq Whisper (navždy zdarma) jsou zobrazeny s odznaky bezplatného kreditu.
|
||||
- **README: Sekce „Začít zdarma“** – Nová tabulka s 5 kroky v předběžném souboru README, která ukazuje, jak nastavit umělou inteligenci s nulovými náklady během několika minut.
|
||||
- **README: Kombinace bezplatného přepisu** – Nová sekce s návrhem kombinací Deepgram/AssemblyAI/Groq a informacemi o bezplatném kreditu pro každého poskytovatele.
|
||||
@@ -586,9 +586,9 @@ Soubor | Účel
|
||||
### 📖 Dokumentace
|
||||
|
||||
- **README: 44+ poskytovatelů** — Všechny 3 výskyty výrazu „36+ poskytovatelů“ byly aktualizovány na „44+“, což odráží skutečný počet kódové základny (44 poskytovatelů v souboru providers.ts).
|
||||
- **README: Nová sekce „🆓 Bezplatné modely – Co skutečně získáte“** – Přidána tabulka 7 poskytovatelů s limity rychlosti pro každý model pro: Kiro (Claude neomezeně přes AWS Builder ID), iFlow (5 modelů neomezeně), Qwen (4 modely neomezeně), Gemini CLI (180K/měsíc), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/den / 60K TPM), Groq (30 RPM / 14.4K RPD). Zahrnuje doporučení pro kombinaci /usr/bin/bash Ultimate Free Stack.
|
||||
- **Soubor README: Aktualizace cenové tabulky** – přidán Cerebras do úrovně API KEY, opravena změna NVIDIA z „1000 kreditů“ na „navždy zdarma pro vývojáře“, aktualizovány počty a názvy modelů iFlow/Qwen
|
||||
- **README: Modely iFlow 8→5** (s názvy: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)
|
||||
- **README: Nová sekce „🆓 Bezplatné modely – Co skutečně získáte“** – Přidána tabulka 7 poskytovatelů s limity rychlosti pro každý model pro: Kiro (Claude neomezeně přes AWS Builder ID), Qoder (5 modelů neomezeně), Qwen (4 modely neomezeně), Gemini CLI (180K/měsíc), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/den / 60K TPM), Groq (30 RPM / 14.4K RPD). Zahrnuje doporučení pro kombinaci /usr/bin/bash Ultimate Free Stack.
|
||||
- **Soubor README: Aktualizace cenové tabulky** – přidán Cerebras do úrovně API KEY, opravena změna NVIDIA z „1000 kreditů“ na „navždy zdarma pro vývojáře“, aktualizovány počty a názvy modelů Qoder/Qwen
|
||||
- **README: Modely Qoder 8→5** (s názvy: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)
|
||||
- **README: Modely Qwen 3→4** (s názvy: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)
|
||||
|
||||
## [2.3.15] - 13. 3. 2026
|
||||
@@ -602,7 +602,7 @@ Soubor | Účel
|
||||
|
||||
### 🐛 Opravy chyb
|
||||
|
||||
- **iFlow OAuth (#339)** : Obnoven platný výchozí `clientSecret` – dříve to byl prázdný řetězec, který při každém pokusu o připojení způsoboval chybu „Chybné přihlašovací údaje klienta“. Veřejné přihlašovací údaje jsou nyní výchozím záložním nastavením (lze je přepsat pomocí proměnné prostředí `IFLOW_OAUTH_CLIENT_SECRET` ).
|
||||
- **Qoder OAuth (#339)** : Obnoven platný výchozí `clientSecret` – dříve to byl prázdný řetězec, který při každém pokusu o připojení způsoboval chybu „Chybné přihlašovací údaje klienta“. Veřejné přihlašovací údaje jsou nyní výchozím záložním nastavením (lze je přepsat pomocí proměnné prostředí `QODER_OAUTH_CLIENT_SECRET` ).
|
||||
- **MITM server nenalezen (#335)** : `prepublish.mjs` nyní kompiluje `src/mitm/*.ts` do JavaScriptu pomocí `tsc` před zkopírováním do npm balíčku. Dříve se kopírovaly pouze nezpracované soubory `.ts` – což znamenalo, že `server.js` nikdy neexistoval v globálních instalacích npm/Volta.
|
||||
- **Chybí projectId v GeminiCLI (#338)** : Namísto vyvolání hardwarové chyby 500, když v uložených přihlašovacích údajích chybí `projectId` (např. po restartu Dockeru), OmniRoute nyní zaznamená varování a pokusí se o požadavek – vrátí smysluplnou chybu na straně poskytovatele místo pádu OmniRoute.
|
||||
- **Neshoda verzí balíčku Electron (#323)** : Synchronizována verze `electron/package.json` s verzí `2.3.13` (dříve `2.0.13` ), takže binární verze pro stolní počítače odpovídá balíčku npm.
|
||||
@@ -640,9 +640,9 @@ Soubor | Účel
|
||||
|
||||
### 📁 Nové soubory
|
||||
|
||||
Soubor | Účel
|
||||
--- | ---
|
||||
`open-sse/services/modelFamilyFallback.ts` | Definice modelových rodin a logika záložních řešení v rámci rodiny
|
||||
| Soubor | Účel |
|
||||
| ------------------------------------------ | ------------------------------------------------------------------ |
|
||||
| `open-sse/services/modelFamilyFallback.ts` | Definice modelových rodin a logika záložních řešení v rámci rodiny |
|
||||
|
||||
### Opraveno
|
||||
|
||||
|
||||
+129
-126
@@ -1,60 +1,79 @@
|
||||
# Průvodce nastavením nástrojů CLI — OmniRoute
|
||||
|
||||
Tato příručka vysvětluje, jak nainstalovat a nakonfigurovat všechny podporované nástroje CLI pro kódování umělé inteligence tak, aby **OmniRoute** fungoval jako jednotný backend, což vám umožní centralizovanou správu klíčů, sledování nákladů, přepínání modelů a protokolování požadavků napříč všemi nástroji.
|
||||
Tato příručka vysvětluje, jak nainstalovat a nakonfigurovat všechny podporované nástroje CLI pro kódování umělé inteligence
|
||||
tak, aby **OmniRoute** fungoval jako jednotný backend, což vám umožní centralizovanou správu klíčů,
|
||||
sledování nákladů, přepínání modelů a protokolování požadavků napříč všemi nástroji.
|
||||
|
||||
---
|
||||
|
||||
## Jak to funguje
|
||||
|
||||
```
|
||||
Claude / Codex / Gemini CLI / OpenCode / Cline / KiloCode / Continue / Kiro CLI
|
||||
│
|
||||
▼ (all point to OmniRoute)
|
||||
http://YOUR_SERVER:20128/v1
|
||||
│
|
||||
▼ (OmniRoute routes to the right provider)
|
||||
Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
|
||||
Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
|
||||
│
|
||||
▼ (všechny ukazují na OmniRoute)
|
||||
http://VASE_SERVER:20128/v1
|
||||
│
|
||||
▼ (OmniRoute směruje ke správnému poskytovateli)
|
||||
Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
|
||||
```
|
||||
|
||||
**Výhody:**
|
||||
|
||||
- Jeden klíč API pro správu všech nástrojů
|
||||
- Sledování nákladů napříč všemi rozhraními příkazového řádku v dashboardu
|
||||
- Jeden API klíč pro správu všech nástrojů
|
||||
- Sledování nákladů napříč všemi CLI v dashboardu
|
||||
- Přepínání modelů bez nutnosti překonfigurování každého nástroje
|
||||
- Funguje lokálně i na vzdálených serverech (VPS)
|
||||
|
||||
---
|
||||
|
||||
## Podporované nástroje
|
||||
## Podporované nástroje (Zdroj pravdy v dashboardu)
|
||||
|
||||
Nástroj | Příkaz | Typ | Metoda instalace
|
||||
--- | --- | --- | ---
|
||||
**Claude Code** | `claude` | Rozhraní příkazového řádku | npm
|
||||
**Kodex OpenAI** | `codex` | Rozhraní příkazového řádku | npm
|
||||
**Rozhraní příkazového řádku Gemini** | `gemini` | Rozhraní příkazového řádku | npm
|
||||
**OpenCode** | `opencode` | Rozhraní příkazového řádku | npm
|
||||
**Cline** | `cline` | Rozšíření CLI + VS kódu | npm
|
||||
**KiloCode** | `kilocode` / `kilo` | Rozšíření CLI + VS kódu | npm
|
||||
**Pokračovat** | průvodce | VS Code ext | VS kód
|
||||
**Kiro CLI** | `kiro-cli` | Rozhraní příkazového řádku | instalační program Curl
|
||||
**Kurzor** | `cursor` | Aplikace pro stolní počítače | Stáhnout
|
||||
**Droid** | webový | Vestavěný agent | OmniRoute
|
||||
**OpenClaw** | webový | Vestavěný agent | OmniRoute
|
||||
Karty dashboardu v `/dashboard/cli-tools` jsou generovány z `src/shared/constants/cliTools.ts`.
|
||||
Aktuální seznam (v3.0.0-rc.16):
|
||||
|
||||
| Nástroj | ID | Příkaz | Režim nastavení | Metoda instalace |
|
||||
| ------------------ | ------------- | ------------ | --------------- | ---------------- |
|
||||
| **Claude Code** | `claude` | `claude` | env | npm |
|
||||
| **OpenAI Codex** | `codex` | `codex` | custom | npm |
|
||||
| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
|
||||
| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
|
||||
| **Cursor** | `cursor` | aplikace | guide | desktop app |
|
||||
| **Cline** | `cline` | `cline` | custom | npm |
|
||||
| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
|
||||
| **Continue** | `continue` | rozšíření | guide | VS Code |
|
||||
| **Antigravity** | `antigravity` | interní | mitm | OmniRoute |
|
||||
| **GitHub Copilot** | `copilot` | rozšíření | custom | VS Code |
|
||||
| **OpenCode** | `opencode` | `opencode` | guide | npm |
|
||||
| **Kiro AI** | `kiro` | aplikace/CLI | mitm | desktop/CLI |
|
||||
|
||||
### Synchronizace otisků CLI (Agenti + Nastavení)
|
||||
|
||||
`/dashboard/agents` a `Nastavení > CLI Otisk` používají `src/shared/constants/cliCompatProviders.ts`.
|
||||
To udržuje ID poskytovatelů v souladu s kartami CLI a staršími ID.
|
||||
|
||||
| CLI ID | ID poskytovatele otisku |
|
||||
| ---------------------------------------------------------------------------------------------------- | ----------------------- |
|
||||
| `kilo` | `kilocode` |
|
||||
| `copilot` | `github` |
|
||||
| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | stejné ID |
|
||||
|
||||
Starší ID jsou stále přijímána pro kompatibilitu: `copilot`, `kimi-coding`, `qwen`.
|
||||
|
||||
---
|
||||
|
||||
## Krok 1 – Získejte klíč OmniRoute API
|
||||
## Krok 1 — Získejte OmniRoute API klíč
|
||||
|
||||
1. Otevřete dashboard OmniRoute → **Správce API** ( `/dashboard/api-manager` )
|
||||
2. Klikněte na **Vytvořit klíč API**
|
||||
3. Pojmenujte to (např. `cli-tools` ) a vyberte všechna oprávnění.
|
||||
4. Zkopírujte klíč – budete ho potřebovat pro každé níže uvedené rozhraní příkazového řádku.
|
||||
1. Otevřete OmniRoute dashboard → **Správce API** (`/dashboard/api-manager`)
|
||||
2. Klikněte na **Vytvořit API klíč**
|
||||
3. Dejte mu název (např. `cli-tools`) a vyberte všechna oprávnění
|
||||
4. Zkopírujte klíč — budete ho potřebovat pro každý CLI níže
|
||||
|
||||
> Váš klíč vypadá takto: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
|
||||
|
||||
---
|
||||
|
||||
## Krok 2 – Instalace nástrojů CLI
|
||||
## Krok 2 — Nainstalujte nástroje CLI
|
||||
|
||||
Všechny nástroje založené na npm vyžadují Node.js 18+:
|
||||
|
||||
@@ -65,9 +84,6 @@ npm install -g @anthropic-ai/claude-code
|
||||
# OpenAI Codex
|
||||
npm install -g @openai/codex
|
||||
|
||||
# Gemini CLI (Google)
|
||||
npm install -g @google/gemini-cli
|
||||
|
||||
# OpenCode
|
||||
npm install -g opencode-ai
|
||||
|
||||
@@ -75,47 +91,47 @@ npm install -g opencode-ai
|
||||
npm install -g cline
|
||||
|
||||
# KiloCode
|
||||
npm install -g kilecode
|
||||
npm install -g kilocode
|
||||
|
||||
# Kiro CLI (Amazon — requires curl + unzip)
|
||||
apt-get install -y unzip # on Debian/Ubuntu
|
||||
# Kiro CLI (Amazon — vyžaduje curl + unzip)
|
||||
apt-get install -y unzip # na Debian/Ubuntu
|
||||
curl -fsSL https://cli.kiro.dev/install | bash
|
||||
export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
|
||||
export PATH="$HOME/.local/bin:$PATH" # přidat do ~/.bashrc
|
||||
```
|
||||
|
||||
**Ověřit:**
|
||||
**Ověření:**
|
||||
|
||||
```bash
|
||||
claude --version # 2.x.x
|
||||
codex --version # 0.x.x
|
||||
gemini --version # 0.x.x
|
||||
opencode --version # x.x.x
|
||||
cline --version # 2.x.x
|
||||
kilocode --version # x.x.x (or: kilo --version)
|
||||
kilocode --version # x.x.x (nebo: kilo --version)
|
||||
kiro-cli --version # 1.x.x
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Krok 3 – Nastavení globálních proměnných prostředí
|
||||
## Krok 3 — Nastavte globální proměnné prostředí
|
||||
|
||||
Přidejte do `~/.bashrc` (nebo `~/.zshrc` ) a poté spusťte `source ~/.bashrc` :
|
||||
Přidejte do `~/.bashrc` (nebo `~/.zshrc`), pak spusťte `source ~/.bashrc`:
|
||||
|
||||
```bash
|
||||
# OmniRoute Universal Endpoint
|
||||
# OmniRoute Univerzální koncový bod
|
||||
export OPENAI_BASE_URL="http://localhost:20128/v1"
|
||||
export OPENAI_API_KEY="sk-your-omniroute-key"
|
||||
export OPENAI_API_KEY="sk-vase-omniroute-klic"
|
||||
export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
|
||||
export ANTHROPIC_API_KEY="sk-your-omniroute-key"
|
||||
export ANTHROPIC_API_KEY="sk-vase-omniroute-klic"
|
||||
export GEMINI_BASE_URL="http://localhost:20128/v1"
|
||||
export GEMINI_API_KEY="sk-your-omniroute-key"
|
||||
export GEMINI_API_KEY="sk-vase-omniroute-klic"
|
||||
```
|
||||
|
||||
> Pro **vzdálený server** nahraďte `localhost:20128` IP adresou nebo doménou serveru, např. `http://192.168.0.15:20128` .
|
||||
> Pro **vzdálený server** nahraďte `localhost:20128` IP adresou nebo doménou serveru,
|
||||
> např. `http://192.168.0.15:20128`.
|
||||
|
||||
---
|
||||
|
||||
## Krok 4 – Konfigurace jednotlivých nástrojů
|
||||
## Krok 4 — Nakonfigurujte každý nástroj
|
||||
|
||||
### Claude Code
|
||||
|
||||
@@ -123,11 +139,11 @@ export GEMINI_API_KEY="sk-your-omniroute-key"
|
||||
# Via CLI:
|
||||
claude config set --global api-base-url http://localhost:20128/v1
|
||||
|
||||
# Or create ~/.claude/settings.json:
|
||||
# Nebo vytvořte ~/.claude/settings.json:
|
||||
mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
|
||||
{
|
||||
"apiBaseUrl": "http://localhost:20128/v1",
|
||||
"apiKey": "sk-your-omniroute-key"
|
||||
"apiKey": "sk-vase-omniroute-klic"
|
||||
}
|
||||
EOF
|
||||
```
|
||||
@@ -136,12 +152,12 @@ EOF
|
||||
|
||||
---
|
||||
|
||||
### Kodex OpenAI
|
||||
### OpenAI Codex
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
|
||||
model: auto
|
||||
apiKey: sk-your-omniroute-key
|
||||
apiKey: sk-vase-omniroute-klic
|
||||
apiBaseUrl: http://localhost:20128/v1
|
||||
EOF
|
||||
```
|
||||
@@ -150,28 +166,13 @@ EOF
|
||||
|
||||
---
|
||||
|
||||
### Rozhraní příkazového řádku Gemini
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
|
||||
{
|
||||
"apiKey": "sk-your-omniroute-key",
|
||||
"baseUrl": "http://localhost:20128/v1"
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
**Test:** `gemini "hello"`
|
||||
|
||||
---
|
||||
|
||||
### OpenCode
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
|
||||
[provider.openai]
|
||||
base_url = "http://localhost:20128/v1"
|
||||
api_key = "sk-your-omniroute-key"
|
||||
api_key = "sk-vase-omniroute-klic"
|
||||
EOF
|
||||
```
|
||||
|
||||
@@ -179,7 +180,7 @@ EOF
|
||||
|
||||
---
|
||||
|
||||
### Cline (CLI nebo VS kód)
|
||||
### Cline (CLI nebo VS Code)
|
||||
|
||||
**Režim CLI:**
|
||||
|
||||
@@ -188,41 +189,42 @@ mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
|
||||
{
|
||||
"apiProvider": "openai",
|
||||
"openAiBaseUrl": "http://localhost:20128/v1",
|
||||
"openAiApiKey": "sk-your-omniroute-key"
|
||||
"openAiApiKey": "sk-vase-omniroute-klic"
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
**Režim VS Code:** Nastavení rozšíření Cline → Poskytovatel API: `OpenAI Compatible` → Základní URL: `http://localhost:20128/v1`
|
||||
**Režim VS Code:**
|
||||
Nastavení rozšíření Cline → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
|
||||
|
||||
Nebo použijte dashboard OmniRoute → **CLI Tools → Cline → Apply Config** .
|
||||
Nebo použijte OmniRoute dashboard → **CLI Nástroje → Cline → Použít konfiguraci**.
|
||||
|
||||
---
|
||||
|
||||
### KiloCode (CLI nebo VS kód)
|
||||
### KiloCode (CLI nebo VS Code)
|
||||
|
||||
**Režim CLI:**
|
||||
|
||||
```bash
|
||||
kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
|
||||
kilocode --api-base http://localhost:20128/v1 --api-key sk-vase-omniroute-klic
|
||||
```
|
||||
|
||||
**Nastavení VS kódu:**
|
||||
**Nastavení VS Code:**
|
||||
|
||||
```json
|
||||
{
|
||||
"kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
|
||||
"kilo-code.apiKey": "sk-your-omniroute-key"
|
||||
"kilo-code.apiKey": "sk-vase-omniroute-klic"
|
||||
}
|
||||
```
|
||||
|
||||
Nebo použijte dashboard OmniRoute → **CLI Tools → KiloCode → Apply Config** .
|
||||
Nebo použijte OmniRoute dashboard → **CLI Nástroje → KiloCode → Použít konfiguraci**.
|
||||
|
||||
---
|
||||
|
||||
### Pokračovat (rozšíření kódu VS)
|
||||
### Continue (Rozšíření VS Code)
|
||||
|
||||
Upravit `~/.continue/config.yaml` :
|
||||
Upravte `~/.continue/config.yaml`:
|
||||
|
||||
```yaml
|
||||
models:
|
||||
@@ -230,7 +232,7 @@ models:
|
||||
provider: openai
|
||||
model: auto
|
||||
apiBase: http://localhost:20128/v1
|
||||
apiKey: sk-your-omniroute-key
|
||||
apiKey: sk-vase-omniroute-klic
|
||||
default: true
|
||||
```
|
||||
|
||||
@@ -241,94 +243,95 @@ Po úpravě restartujte VS Code.
|
||||
### Kiro CLI (Amazon)
|
||||
|
||||
```bash
|
||||
# Login to your AWS/Kiro account:
|
||||
# Přihlaste se ke svému AWS/Kiro účtu:
|
||||
kiro-cli login
|
||||
|
||||
# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
|
||||
# Use kiro-cli alongside OmniRoute for other tools.
|
||||
# CLI používá vlastní autentifikaci — OmniRoute není potřeba jako backend pro samotný Kiro CLI.
|
||||
# Používejte kiro-cli společně s OmniRoute pro ostatní nástroje.
|
||||
kiro-cli status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Kurzor (aplikace pro stolní počítače)
|
||||
### Cursor (Desktop aplikace)
|
||||
|
||||
> **Poznámka:** Cursor směruje požadavky přes svůj cloud. Pro integraci OmniRoute povolte **cloudový koncový bod** v nastavení OmniRoute a použijte URL adresu vaší veřejné domény.
|
||||
> **Poznámka:** Cursor směruje požadavky přes svůj cloud. Pro integraci s OmniRoute,
|
||||
> povolte **Cloud Endpoint** v nastavení OmniRoute a použijte vaši veřejnou doménu.
|
||||
|
||||
Přes GUI: **Nastavení → Modely → Klíč OpenAI API**
|
||||
Via GUI: **Settings → Models → OpenAI API Key**
|
||||
|
||||
- Základní URL: `https://your-domain.com/v1`
|
||||
- Klíč API: váš klíč OmniRoute
|
||||
- Base URL: `https://vase-domena.com/v1`
|
||||
- API Key: váš OmniRoute klíč
|
||||
|
||||
---
|
||||
|
||||
## Automatická konfigurace řídicího panelu
|
||||
## Automatická konfigurace v dashboardu
|
||||
|
||||
Ovládací panel OmniRoute automatizuje konfiguraci většiny nástrojů:
|
||||
OmniRoute dashboard automatizuje konfiguraci většiny nástrojů:
|
||||
|
||||
1. Přejděte na `http://localhost:20128/dashboard/cli-tools`
|
||||
2. Rozbalit libovolnou kartu nástroje
|
||||
3. Vyberte klíč API z rozbalovací nabídky
|
||||
4. Klikněte **na Použít konfiguraci** (pokud je nástroj detekován jako nainstalovaný)
|
||||
5. Nebo zkopírujte vygenerovaný konfigurační úryvek ručně
|
||||
1. Jděte na `http://localhost:20128/dashboard/cli-tools`
|
||||
2. Rozbalte libovolnou kartu nástroje
|
||||
3. Vyberte svůj API klíč z rozbalovacího seznamu
|
||||
4. Klikněte na **Použít konfiguraci** (pokud je nástroj detekován jako nainstalovaný)
|
||||
5. Nebo ručně zkopírujte vygenerovaný konfigurační snippet
|
||||
|
||||
---
|
||||
|
||||
## Vestavění agenti: Droid a OpenClaw
|
||||
## Vestavěný agenti: Droid & OpenClaw
|
||||
|
||||
**Droid** a **OpenClaw** jsou agenti umělé inteligence zabudovaní přímo do OmniRoute – není nutná žádná instalace. Běží jako interní trasy a automaticky používají modelové směrování OmniRoute.
|
||||
**Droid** a **OpenClaw** jsou AI agenti vestavění přímo do OmniRoute — není potřeba žádná instalace.
|
||||
Běží jako interní trasy a automaticky používají směrování modelů OmniRoute.
|
||||
|
||||
- Přístup: `http://localhost:20128/dashboard/agents`
|
||||
- Konfigurace: stejné kombinace a poskytovatelé jako u všech ostatních nástrojů
|
||||
- Není vyžadována instalace klíče API ani příkazového řádku
|
||||
- Konfigurace: stejné kombinace a poskytovatelé jako všechny ostatní nástroje
|
||||
- Není potřeba API klíč ani instalace CLI
|
||||
|
||||
---
|
||||
|
||||
## Dostupné koncové body API
|
||||
## Dostupné API koncové body
|
||||
|
||||
Koncový bod | Popis | Použití pro
|
||||
--- | --- | ---
|
||||
`/v1/chat/completions` | Standardní chat (všichni poskytovatelé) | Všechny moderní nástroje
|
||||
`/v1/responses` | API pro odpovědi (formát OpenAI) | Kodex, agentické pracovní postupy
|
||||
`/v1/completions` | Doplňování starších textů | Starší nástroje používající `prompt:`
|
||||
`/v1/embeddings` | Vkládání textu | RAG, vyhledávání
|
||||
`/v1/images/generations` | Generování obrázků | DALL-E, Flux atd.
|
||||
`/v1/audio/speech` | Převod textu na řeč | ElevenLabs, OpenAI TTS
|
||||
`/v1/audio/transcriptions` | Převod řeči na text | Deepgram, AssemblyAI
|
||||
| Koncový bod | Popis | Použití pro |
|
||||
| -------------------------- | --------------------------------------- | ------------------------------------- |
|
||||
| `/v1/chat/completions` | Standardní chat (všichni poskytovatelé) | Všechny moderní nástroje |
|
||||
| `/v1/responses` | Responses API (formát OpenAI) | Codex, agentní workflowy |
|
||||
| `/v1/completions` | Legacy textové dokončení | Starší nástroje používající `prompt:` |
|
||||
| `/v1/embeddings` | Textové vložení | RAG, vyhledávání |
|
||||
| `/v1/images/generations` | Generování obrázků | DALL-E, Flux, atd. |
|
||||
| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
|
||||
| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
|
||||
|
||||
---
|
||||
|
||||
## Odstraňování problémů
|
||||
## Řešení problémů
|
||||
|
||||
Chyba | Příčina | Opravit
|
||||
--- | --- | ---
|
||||
`Connection refused` | OmniRoute neběží | `pm2 start omniroute`
|
||||
`401 Unauthorized` | Chybný klíč API | Zkontrolovat `/dashboard/api-manager`
|
||||
`No combo configured` | Žádná aktivní routingová kombinace | Nastavení v `/dashboard/combos`
|
||||
`invalid model` | Model není v katalogu | Použijte `auto` nebo zkontrolujte `/dashboard/providers`
|
||||
CLI zobrazuje „není nainstalováno“ | Binární soubor není v cestě PATH | Zkontrolujte, `which <command>`
|
||||
`kiro-cli: not found` | Není v PATH | `export PATH="$HOME/.local/bin:$PATH"`
|
||||
| Chyba | Příčina | Oprava |
|
||||
| ----------------------------- | ----------------------- | -------------------------------------------------------- |
|
||||
| `Connection refused` | OmniRoute neběží | `pm2 start omniroute` |
|
||||
| `401 Unauthorized` | Špatný API klíč | Zkontrolujte v `/dashboard/api-manager` |
|
||||
| `No combo configured` | Žádná aktivní kombinace | Nastavte v `/dashboard/combos` |
|
||||
| `invalid model` | Model není v katalogu | Použijte `auto` nebo zkontrolujte `/dashboard/providers` |
|
||||
| CLI zobrazuje "not installed" | Binárka není v PATH | Zkontrolujte `which <příkaz>` |
|
||||
| `kiro-cli: not found` | Není v PATH | `export PATH="$HOME/.local/bin:$PATH"` |
|
||||
|
||||
---
|
||||
|
||||
## Skript pro rychlé nastavení (jeden příkaz)
|
||||
## Rychlý skript pro nastavení (jeden příkaz)
|
||||
|
||||
```bash
|
||||
# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
|
||||
# Nainstalujte všechny CLI a nakonfigurujte pro OmniRoute (nahraďte svým klíčem a URL serveru)
|
||||
OMNIROUTE_URL="http://localhost:20128/v1"
|
||||
OMNIROUTE_KEY="sk-your-omniroute-key"
|
||||
OMNIROUTE_KEY="sk-vase-omniroute-klic"
|
||||
|
||||
npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
|
||||
npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
|
||||
|
||||
# Kiro CLI
|
||||
apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
|
||||
|
||||
# Write configs
|
||||
mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
|
||||
# Zápis konfigurací
|
||||
mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
|
||||
|
||||
cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
|
||||
cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
|
||||
cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
|
||||
cat >> ~/.bashrc << EOF
|
||||
export OPENAI_BASE_URL="$OMNIROUTE_URL"
|
||||
export OPENAI_API_KEY="$OMNIROUTE_KEY"
|
||||
@@ -337,5 +340,5 @@ export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
|
||||
EOF
|
||||
|
||||
source ~/.bashrc
|
||||
echo "✅ All CLIs installed and configured for OmniRoute"
|
||||
echo "✅ Všechny CLI nainstalovány a nakonfigurovány pro OmniRoute"
|
||||
```
|
||||
|
||||
@@ -110,14 +110,14 @@ omniroute/
|
||||
|
||||
Jediný **zdroj pravdivých informací** pro všechny konfigurace poskytovatelů.
|
||||
|
||||
Soubor | Účel
|
||||
--- | ---
|
||||
`constants.ts` | Objekt `PROVIDERS` se základními URL adresami, přihlašovacími údaji OAuth (výchozí), záhlavími a výchozími systémovými výzvami pro každého poskytovatele. Definuje také `HTTP_STATUS` , `ERROR_TYPES` , `COOLDOWN_MS` , `BACKOFF_CONFIG` a `SKIP_PATTERNS` .
|
||||
`credentialLoader.ts` | Načte externí přihlašovací údaje z `data/provider-credentials.json` a sloučí je s pevně zakódovanými výchozími hodnotami v `PROVIDERS` . Uchovává tajné údaje mimo kontrolu zdrojového kódu a zároveň zachovává zpětnou kompatibilitu.
|
||||
`providerModels.ts` | Centrální registr modelů: mapuje aliasy poskytovatelů → ID modelů. Funkce jako `getModels()` , `getProviderByAlias()` .
|
||||
`codexInstructions.ts` | Systémové instrukce vložené do požadavků Codexu (omezení úprav, pravidla sandboxu, zásady schvalování).
|
||||
`defaultThinkingSignature.ts` | Výchozí „myšlenkové“ podpisy pro modely Claude a Gemini.
|
||||
`ollamaModels.ts` | Definice schématu pro lokální Ollama modely (název, velikost, rodina, kvantizace).
|
||||
| Soubor | Účel |
|
||||
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `constants.ts` | Objekt `PROVIDERS` se základními URL adresami, přihlašovacími údaji OAuth (výchozí), záhlavími a výchozími systémovými výzvami pro každého poskytovatele. Definuje také `HTTP_STATUS` , `ERROR_TYPES` , `COOLDOWN_MS` , `BACKOFF_CONFIG` a `SKIP_PATTERNS` . |
|
||||
| `credentialLoader.ts` | Načte externí přihlašovací údaje z `data/provider-credentials.json` a sloučí je s pevně zakódovanými výchozími hodnotami v `PROVIDERS` . Uchovává tajné údaje mimo kontrolu zdrojového kódu a zároveň zachovává zpětnou kompatibilitu. |
|
||||
| `providerModels.ts` | Centrální registr modelů: mapuje aliasy poskytovatelů → ID modelů. Funkce jako `getModels()` , `getProviderByAlias()` . |
|
||||
| `codexInstructions.ts` | Systémové instrukce vložené do požadavků Codexu (omezení úprav, pravidla sandboxu, zásady schvalování). |
|
||||
| `defaultThinkingSignature.ts` | Výchozí „myšlenkové“ podpisy pro modely Claude a Gemini. |
|
||||
| `ollamaModels.ts` | Definice schématu pro lokální Ollama modely (název, velikost, rodina, kvantizace). |
|
||||
|
||||
#### Postup načítání přihlašovacích údajů
|
||||
|
||||
@@ -194,17 +194,17 @@ classDiagram
|
||||
BaseExecutor <|-- GithubExecutor
|
||||
```
|
||||
|
||||
Vykonavatel | Poskytovatel | Klíčové specializace
|
||||
--- | --- | ---
|
||||
`base.ts` | — | Abstraktní základ: tvorba URL adres, hlavičky, logika opakování, aktualizace přihlašovacích údajů
|
||||
`default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Aktualizace generického tokenu OAuth pro standardní poskytovatele
|
||||
`antigravity.ts` | Kód Google Cloud | Generování ID projektu/relace, záložní více URL adres, vlastní analýza opakovaných pokusů z chybových zpráv („reset po 2h7m23s“)
|
||||
`cursor.ts` | IDE kurzoru | **Nejsložitější** : autorizace kontrolního součtu SHA-256, kódování požadavků Protobuf, analýza binárních EventStream → SSE odpovědí
|
||||
`codex.ts` | Kodex OpenAI | Vkládá systémové instrukce, spravuje úrovně myšlení, odstraňuje nepodporované parametry
|
||||
`gemini-cli.ts` | Rozhraní příkazového řádku Google Gemini | Vytvoření vlastní URL adresy ( `streamGenerateContent` ), aktualizace tokenu Google OAuth
|
||||
`github.ts` | GitHub Copilot | Systém duálních tokenů (GitHub OAuth + Copilot token), napodobování hlaviček VSCode
|
||||
`kiro.ts` | AWS CodeWhisperer | Binární parsování AWS EventStream, rámce událostí AMZN, odhad tokenů
|
||||
`index.ts` | — | Továrna: název poskytovatele map → třída exekutoru s výchozím záložním nastavením
|
||||
| Vykonavatel | Poskytovatel | Klíčové specializace |
|
||||
| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `base.ts` | — | Abstraktní základ: tvorba URL adres, hlavičky, logika opakování, aktualizace přihlašovacích údajů |
|
||||
| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Aktualizace generického tokenu OAuth pro standardní poskytovatele |
|
||||
| `antigravity.ts` | Kód Google Cloud | Generování ID projektu/relace, záložní více URL adres, vlastní analýza opakovaných pokusů z chybových zpráv („reset po 2h7m23s“) |
|
||||
| `cursor.ts` | IDE kurzoru | **Nejsložitější** : autorizace kontrolního součtu SHA-256, kódování požadavků Protobuf, analýza binárních EventStream → SSE odpovědí |
|
||||
| `codex.ts` | OpenAI Codex | Vkládá systémové instrukce, spravuje úrovně myšlení, odstraňuje nepodporované parametry |
|
||||
| `gemini-cli.ts` | Google Gemini CLI | Vytvoření vlastní URL adresy ( `streamGenerateContent` ), aktualizace tokenu Google OAuth |
|
||||
| `github.ts` | GitHub Copilot | Systém duálních tokenů (GitHub OAuth + Copilot token), napodobování hlaviček VSCode |
|
||||
| `kiro.ts` | AWS CodeWhisperer | Binární parsování AWS EventStream, rámce událostí AMZN, odhad tokenů |
|
||||
| `index.ts` | — | Továrna: název poskytovatele map → třída exekutoru s výchozím záložním nastavením |
|
||||
|
||||
---
|
||||
|
||||
@@ -212,12 +212,12 @@ Vykonavatel | Poskytovatel | Klíčové specializace
|
||||
|
||||
**Orchestrační vrstva** – koordinuje překlad, provádění, streamování a zpracování chyb.
|
||||
|
||||
Soubor | Účel
|
||||
--- | ---
|
||||
`chatCore.ts` | **Centrální orchestrátor** (~600 řádků). Zvládá kompletní životní cyklus požadavku: detekce formátu → překlad → odeslání exekutoru → streamovaná/nestreamovaná odpověď → aktualizace tokenu → zpracování chyb → protokolování využití.
|
||||
`responsesHandler.ts` | Adaptér pro OpenAI Responses API: převádí formát odpovědí → Dokončení chatu → odesílá do `chatCore` → převádí SSE zpět do formátu odpovědí.
|
||||
`embeddings.ts` | Obslužná rutina generování embeddingu: řeší model embeddingu → poskytovatele, odesílá do API poskytovatele, vrací odpověď na embedding kompatibilní s OpenAI. Podporuje 6+ poskytovatelů.
|
||||
`imageGeneration.ts` | Obslužná rutina generování obrázků: řeší model obrázku → poskytovatele, podporuje režimy kompatibilní s OpenAI, Gemini-image (Antigravity) a fallback (Nebius). Vrací obrázky v base64 nebo URL.
|
||||
| Soubor | Účel |
|
||||
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `chatCore.ts` | **Centrální orchestrátor** (~600 řádků). Zvládá kompletní životní cyklus požadavku: detekce formátu → překlad → odeslání exekutoru → streamovaná/nestreamovaná odpověď → aktualizace tokenu → zpracování chyb → protokolování využití. |
|
||||
| `responsesHandler.ts` | Adaptér pro OpenAI Responses API: převádí formát odpovědí → Dokončení chatu → odesílá do `chatCore` → převádí SSE zpět do formátu odpovědí. |
|
||||
| `embeddings.ts` | Obslužná rutina generování embeddingu: řeší model embeddingu → poskytovatele, odesílá do API poskytovatele, vrací odpověď na embedding kompatibilní s OpenAI. Podporuje 6+ poskytovatelů. |
|
||||
| `imageGeneration.ts` | Obslužná rutina generování obrázků: řeší model obrázku → poskytovatele, podporuje režimy kompatibilní s OpenAI, Gemini-image (Antigravity) a fallback (Nebius). Vrací obrázky v base64 nebo URL. |
|
||||
|
||||
#### Životní cyklus požadavku (chatCore.ts)
|
||||
|
||||
@@ -262,22 +262,22 @@ sequenceDiagram
|
||||
|
||||
Obchodní logika, která podporuje obslužné rutiny a vykonavatele.
|
||||
|
||||
Soubor | Účel
|
||||
--- | ---
|
||||
`provider.ts` | **Detekce formátu** ( `detectFormat` ): analyzuje strukturu těla požadavku a identifikuje formáty Claude/OpenAI/Gemini/Antigravity/Responses (včetně heuristiky `max_tokens` pro Claude). Dále: tvorba URL, tvorba hlaviček, normalizace konfigurace thinking. Podporuje dynamické poskytovatele kompatibilní `openai-compatible-*` a `anthropic-compatible-*` .
|
||||
`model.ts` | Analýza řetězců modelu ( `claude/model-name` → `{provider: "claude", model: "model-name"}` ), rozlišení aliasů s detekcí kolizí, sanitizace vstupu (odmítá průchod cestou/řídicí znaky) a rozlišení informací o modelu s podporou asynchronních metod pro získávání aliasů.
|
||||
`accountFallback.ts` | Ovládání limitů rychlosti: exponenciální upomínka (1 s → 2 s → 4 s → max. 2 min), správa doby zpoždění účtu, klasifikace chyb (které chyby spouštějí fallback a které ne).
|
||||
`tokenRefresh.ts` | Aktualizace tokenu OAuth pro **všechny poskytovatele** : Google (Gemini, Antigravity), Claude, Codex, Qwen, iFlow, GitHub (duální token OAuth + Copilot), Kiro (AWS SSO OIDC + sociální ověřování). Zahrnuje mezipaměť deduplikace promise za provozu a opakování s exponenciálním zpožděním.
|
||||
`combo.ts` | **Kombinované modely** : řetězce záložních modelů. Pokud model A selže s chybou způsobilou pro záložní model, zkuste model B, poté C atd. Vrací skutečné stavové kódy upstreamu.
|
||||
`usage.ts` | Načítá data o kvótách/využití z API poskytovatelů (kvóty GitHub Copilot, kvóty modelu Antigravity, limity rychlosti Codexu, rozpisy využití Kiro, nastavení Claude).
|
||||
`accountSelector.ts` | Inteligentní výběr účtu s algoritmem bodování: pro výběr optimálního účtu pro každý požadavek se zohledňuje priorita, zdravotní stav, pozice v systému round robin a stav ochlazování.
|
||||
`contextManager.ts` | Správa životního cyklu kontextu požadavku: vytváří a sleduje objekty kontextu pro každý požadavek s metadaty (ID požadavku, časová razítka, informace o poskytovateli) pro ladění a protokolování.
|
||||
`ipFilter.ts` | Řízení přístupu založené na IP adrese: podporuje režimy povolených seznamů a blokovaných seznamů. Před zpracováním požadavků API ověřuje IP adresu klienta podle nakonfigurovaných pravidel.
|
||||
`sessionManager.ts` | Sledování relací s otisky prstů klientů: sleduje aktivní relace pomocí hašovaných identifikátorů klientů, monitoruje počty požadavků a poskytuje metriky relací.
|
||||
`signatureCache.ts` | Mezipaměť deduplikace na základě signatur požadavků: zabraňuje duplicitním požadavkům ukládáním nedávných signatur požadavků do mezipaměti a vrácením odpovědí z mezipaměti pro identické požadavky v rámci časového okna.
|
||||
`systemPrompt.ts` | Globální vložení systémového výzvy: přidá konfigurovatelnou systémovou výzvu ke všem požadavkům s možností kompatibility pro jednotlivé poskytovatele.
|
||||
`thinkingBudget.ts` | Správa rozpočtu tokenů uvažování: podporuje režimy průchodu, automatický (konfigurace strip thinking), vlastní (pevný rozpočet) a adaptivní (měřítko složitosti) pro řízení tokenů myšlení/uvažování.
|
||||
`wildcardRouter.ts` | Směrování podle vzorů zástupných znaků: rozpoznává vzory zástupných znaků (např. `*/claude-*` ) na konkrétní páry poskytovatel/model na základě dostupnosti a priority.
|
||||
| Soubor | Účel |
|
||||
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `provider.ts` | **Detekce formátu** ( `detectFormat` ): analyzuje strukturu těla požadavku a identifikuje formáty Claude/OpenAI/Gemini/Antigravity/Responses (včetně heuristiky `max_tokens` pro Claude). Dále: tvorba URL, tvorba hlaviček, normalizace konfigurace thinking. Podporuje dynamické poskytovatele kompatibilní `openai-compatible-*` a `anthropic-compatible-*` . |
|
||||
| `model.ts` | Analýza řetězců modelu ( `claude/model-name` → `{provider: "claude", model: "model-name"}` ), rozlišení aliasů s detekcí kolizí, sanitizace vstupu (odmítá průchod cestou/řídicí znaky) a rozlišení informací o modelu s podporou asynchronních metod pro získávání aliasů. |
|
||||
| `accountFallback.ts` | Ovládání limitů rychlosti: exponenciální upomínka (1 s → 2 s → 4 s → max. 2 min), správa doby zpoždění účtu, klasifikace chyb (které chyby spouštějí fallback a které ne). |
|
||||
| `tokenRefresh.ts` | Aktualizace tokenu OAuth pro **všechny poskytovatele** : Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (duální token OAuth + Copilot), Kiro (AWS SSO OIDC + sociální ověřování). Zahrnuje mezipaměť deduplikace promise za provozu a opakování s exponenciálním zpožděním. |
|
||||
| `combo.ts` | **Kombinované modely** : řetězce záložních modelů. Pokud model A selže s chybou způsobilou pro záložní model, zkuste model B, poté C atd. Vrací skutečné stavové kódy upstreamu. |
|
||||
| `usage.ts` | Načítá data o kvótách/využití z API poskytovatelů (kvóty GitHub Copilot, kvóty modelu Antigravity, limity rychlosti Codexu, rozpisy využití Kiro, nastavení Claude). |
|
||||
| `accountSelector.ts` | Inteligentní výběr účtu s algoritmem bodování: pro výběr optimálního účtu pro každý požadavek se zohledňuje priorita, zdravotní stav, pozice v systému round robin a stav ochlazování. |
|
||||
| `contextManager.ts` | Správa životního cyklu kontextu požadavku: vytváří a sleduje objekty kontextu pro každý požadavek s metadaty (ID požadavku, časová razítka, informace o poskytovateli) pro ladění a protokolování. |
|
||||
| `ipFilter.ts` | Řízení přístupu založené na IP adrese: podporuje režimy povolených seznamů a blokovaných seznamů. Před zpracováním požadavků API ověřuje IP adresu klienta podle nakonfigurovaných pravidel. |
|
||||
| `sessionManager.ts` | Sledování relací s otisky prstů klientů: sleduje aktivní relace pomocí hašovaných identifikátorů klientů, monitoruje počty požadavků a poskytuje metriky relací. |
|
||||
| `signatureCache.ts` | Mezipaměť deduplikace na základě signatur požadavků: zabraňuje duplicitním požadavkům ukládáním nedávných signatur požadavků do mezipaměti a vrácením odpovědí z mezipaměti pro identické požadavky v rámci časového okna. |
|
||||
| `systemPrompt.ts` | Globální vložení systémového výzvy: přidá konfigurovatelnou systémovou výzvu ke všem požadavkům s možností kompatibility pro jednotlivé poskytovatele. |
|
||||
| `thinkingBudget.ts` | Správa rozpočtu tokenů uvažování: podporuje režimy průchodu, automatický (konfigurace strip thinking), vlastní (pevný rozpočet) a adaptivní (měřítko složitosti) pro řízení tokenů myšlení/uvažování. |
|
||||
| `wildcardRouter.ts` | Směrování podle vzorů zástupných znaků: rozpoznává vzory zástupných znaků (např. `*/claude-*` ) na konkrétní páry poskytovatel/model na základě dostupnosti a priority. |
|
||||
|
||||
#### Deduplikace obnovení tokenů
|
||||
|
||||
@@ -374,13 +374,13 @@ graph TD
|
||||
end
|
||||
```
|
||||
|
||||
Adresář | Soubory | Popis
|
||||
--- | --- | ---
|
||||
`request/` | 8 překladatelů | Převod těl požadavků mezi formáty. Každý soubor se při importu sám zaregistruje pomocí `register(from, to, fn)` .
|
||||
`response/` | 7 překladatelů | Převádí bloky odpovědí streamovaných dat mezi formáty. Zpracovává typy událostí SSE, myšlenkové bloky a volání nástrojů.
|
||||
`helpers/` | 6 pomocníků | Sdílené utility: `claudeHelper` (extrakce systémových prompts, thinking config), `geminiHelper` (mapování částí/obsahu), `openaiHelper` (filtrování formátů), `toolCallHelper` (generování ID, vkládání chybějících odpovědí), `maxTokensHelper` , `responsesApiHelper` .
|
||||
`index.ts` | — | Překladový engine: `translateRequest()` , `translateResponse()` , správa stavu, registr.
|
||||
`formats.ts` | — | Formátovací konstanty: `OPENAI` , `CLAUDE` , `GEMINI` , `ANTIGRAVITY` , `KIRO` , `CURSOR` , `OPENAI_RESPONSES` .
|
||||
| Adresář | Soubory | Popis |
|
||||
| ------------ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `request/` | 8 překladatelů | Převod těl požadavků mezi formáty. Každý soubor se při importu sám zaregistruje pomocí `register(from, to, fn)` . |
|
||||
| `response/` | 7 překladatelů | Převádí bloky odpovědí streamovaných dat mezi formáty. Zpracovává typy událostí SSE, myšlenkové bloky a volání nástrojů. |
|
||||
| `helpers/` | 6 pomocníků | Sdílené utility: `claudeHelper` (extrakce systémových prompts, thinking config), `geminiHelper` (mapování částí/obsahu), `openaiHelper` (filtrování formátů), `toolCallHelper` (generování ID, vkládání chybějících odpovědí), `maxTokensHelper` , `responsesApiHelper` . |
|
||||
| `index.ts` | — | Překladový engine: `translateRequest()` , `translateResponse()` , správa stavu, registr. |
|
||||
| `formats.ts` | — | Formátovací konstanty: `OPENAI` , `CLAUDE` , `GEMINI` , `ANTIGRAVITY` , `KIRO` , `CURSOR` , `OPENAI_RESPONSES` . |
|
||||
|
||||
#### Klíčový design: Samoregistrující se pluginy
|
||||
|
||||
@@ -397,15 +397,15 @@ import "./request/claude-to-openai.js"; // ← self-registers
|
||||
|
||||
### 4.6 Nástroje ( `open-sse/utils/` )
|
||||
|
||||
Soubor | Účel
|
||||
--- | ---
|
||||
`error.ts` | Vytváření chybové odezvy (formát kompatibilní s OpenAI), parsování chyb v upstreamu, extrakce doby opakování Antigravity z chybových zpráv, streamování chyb SSE.
|
||||
`stream.ts` | **SSE Transform Stream** — základní streamovací kanál. Dva režimy: `TRANSLATE` (plný překlad formátu) a `PASSTHROUGH` (normalizace + extrakce využití). Zpracovává ukládání bloků do vyrovnávací paměti, odhad využití a sledování délky obsahu. Instance kodéru/dekodéru pro každý stream se vyhýbají sdílenému stavu.
|
||||
`streamHelpers.ts` | Nízkoúrovňové utility SSE: `parseSSELine` (tolerantní k bílým znakům), `hasValuableContent` (filtruje prázdné segmenty pro OpenAI/Claude/Gemini), `fixInvalidId` , `formatSSE` (serializace SSE s ohledem na formát s čištěním `perf_metrics` ).
|
||||
`usageTracking.ts` | Extrakce využití tokenů z libovolného formátu (Claude/OpenAI/Gemini/Responses), odhad s oddělenými poměry znaků na token pro jednotlivé nástroje/zprávy, přidání vyrovnávací paměti (bezpečnostní rezerva 2000 tokenů), filtrování polí specifických pro formát, protokolování konzole s barvami ANSI.
|
||||
`requestLogger.ts` | Protokolování požadavků na základě souborů (přihlášení pomocí `ENABLE_REQUEST_LOGS=true` ). Vytváří složky relací s očíslovanými soubory: `1_req_client.json` → `7_res_client.txt` . Veškeré I/O operace jsou asynchronní (aktivní a zapomenutý). Maskuje citlivé hlavičky.
|
||||
`bypassHandler.ts` | Zachycuje specifické vzory z Claude CLI (extrakce názvu, zahřívání, počet) a vrací falešné odpovědi bez volání jakéhokoli poskytovatele. Podporuje streamování i nestreamování. Záměrně omezeno na rozsah Claude CLI.
|
||||
`networkProxy.ts` | Rozpozná URL odchozí proxy pro daného poskytovatele s prioritou: konfigurace specifická pro poskytovatele → globální konfigurace → proměnné prostředí ( `HTTPS_PROXY` / `HTTP_PROXY` / `ALL_PROXY` ). Podporuje výjimky `NO_PROXY` . Ukládá konfiguraci do mezipaměti po dobu 30 sekund.
|
||||
| Soubor | Účel |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `error.ts` | Vytváření chybové odezvy (formát kompatibilní s OpenAI), parsování chyb v upstreamu, extrakce doby opakování Antigravity z chybových zpráv, streamování chyb SSE. |
|
||||
| `stream.ts` | **SSE Transform Stream** — základní streamovací kanál. Dva režimy: `TRANSLATE` (plný překlad formátu) a `PASSTHROUGH` (normalizace + extrakce využití). Zpracovává ukládání bloků do vyrovnávací paměti, odhad využití a sledování délky obsahu. Instance kodéru/dekodéru pro každý stream se vyhýbají sdílenému stavu. |
|
||||
| `streamHelpers.ts` | Nízkoúrovňové utility SSE: `parseSSELine` (tolerantní k bílým znakům), `hasValuableContent` (filtruje prázdné segmenty pro OpenAI/Claude/Gemini), `fixInvalidId` , `formatSSE` (serializace SSE s ohledem na formát s čištěním `perf_metrics` ). |
|
||||
| `usageTracking.ts` | Extrakce využití tokenů z libovolného formátu (Claude/OpenAI/Gemini/Responses), odhad s oddělenými poměry znaků na token pro jednotlivé nástroje/zprávy, přidání vyrovnávací paměti (bezpečnostní rezerva 2000 tokenů), filtrování polí specifických pro formát, protokolování konzole s barvami ANSI. |
|
||||
| `requestLogger.ts` | Protokolování požadavků na základě souborů (přihlášení pomocí `ENABLE_REQUEST_LOGS=true` ). Vytváří složky relací s očíslovanými soubory: `1_req_client.json` → `7_res_client.txt` . Veškeré I/O operace jsou asynchronní (aktivní a zapomenutý). Maskuje citlivé hlavičky. |
|
||||
| `bypassHandler.ts` | Zachycuje specifické vzory z Claude CLI (extrakce názvu, zahřívání, počet) a vrací falešné odpovědi bez volání jakéhokoli poskytovatele. Podporuje streamování i nestreamování. Záměrně omezeno na rozsah Claude CLI. |
|
||||
| `networkProxy.ts` | Rozpozná URL odchozí proxy pro daného poskytovatele s prioritou: konfigurace specifická pro poskytovatele → globální konfigurace → proměnné prostředí ( `HTTPS_PROXY` / `HTTP_PROXY` / `ALL_PROXY` ). Podporuje výjimky `NO_PROXY` . Ukládá konfiguraci do mezipaměti po dobu 30 sekund. |
|
||||
|
||||
#### Streamovací kanál SSE
|
||||
|
||||
@@ -449,32 +449,32 @@ logs/
|
||||
|
||||
### 4.7 Aplikační vrstva ( `src/` )
|
||||
|
||||
Adresář | Účel
|
||||
--- | ---
|
||||
`src/app/` | Webové uživatelské rozhraní, trasy API, middleware Express, obslužné rutiny zpětných volání OAuth
|
||||
`src/lib/` | Přístup k databázi ( `localDb.ts` , `usageDb.ts` ), ověřování, sdílení
|
||||
`src/mitm/` | Nástroje proxy typu „man-in-the-middle“ pro zachycení provozu poskytovatelů
|
||||
`src/models/` | Definice modelů databáze
|
||||
`src/shared/` | Obálky kolem funkcí open-sse (provider, stream, error atd.)
|
||||
`src/sse/` | Obslužné rutiny koncových bodů SSE, které propojují knihovnu open-sse s trasami Express
|
||||
`src/store/` | Správa stavu aplikací
|
||||
| Adresář | Účel |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| `src/app/` | Webové uživatelské rozhraní, trasy API, middleware Express, obslužné rutiny zpětných volání OAuth |
|
||||
| `src/lib/` | Přístup k databázi ( `localDb.ts` , `usageDb.ts` ), ověřování, sdílení |
|
||||
| `src/mitm/` | Nástroje proxy typu „man-in-the-middle“ pro zachycení provozu poskytovatelů |
|
||||
| `src/models/` | Definice modelů databáze |
|
||||
| `src/shared/` | Obálky kolem funkcí open-sse (provider, stream, error atd.) |
|
||||
| `src/sse/` | Obslužné rutiny koncových bodů SSE, které propojují knihovnu open-sse s trasami Express |
|
||||
| `src/store/` | Správa stavu aplikací |
|
||||
|
||||
#### Významné trasy API
|
||||
|
||||
Trasa | Metody | Účel
|
||||
--- | --- | ---
|
||||
`/api/provider-models` | ZÍSKAT/ODESLAT/SMAZAT | CRUD pro vlastní modely na poskytovatele
|
||||
`/api/models/catalog` | ZÍSKAT | Agregovaný katalog všech modelů (chat, embedding, image, custom) seskupených podle poskytovatele
|
||||
`/api/settings/proxy` | ZÍSKAT/VLOŽIT/ODSTRANIT | Konfigurace hierarchické odchozí proxy ( `global/providers/combos/keys` )
|
||||
`/api/settings/proxy/test` | ZVEŘEJNIT | Ověřuje připojení proxy a vrací veřejnou IP adresu/latenci
|
||||
`/v1/providers/[provider]/chat/completions` | ZVEŘEJNIT | Vyhrazené dokončování chatu pro jednotlivé poskytovatele s ověřováním modelu
|
||||
`/v1/providers/[provider]/embeddings` | ZVEŘEJNIT | Vyhrazené vkládání pro jednotlivé poskytovatele s ověřováním modelu
|
||||
`/v1/providers/[provider]/images/generations` | ZVEŘEJNIT | Vyhrazené generování obrázků pro každého poskytovatele s ověřováním modelu
|
||||
`/api/settings/ip-filter` | ZÍSKAT/VLOŽIT | Správa povolených/blokovaných IP adres
|
||||
`/api/settings/thinking-budget` | ZÍSKAT/VLOŽIT | Konfigurace rozpočtu tokenů zdůvodnění (průchozí/automatická/vlastní/adaptivní)
|
||||
`/api/settings/system-prompt` | ZÍSKAT/VLOŽIT | Globální vložení systémového promptu pro všechny požadavky
|
||||
`/api/sessions` | ZÍSKAT | Sledování a metriky aktivních relací
|
||||
`/api/rate-limits` | ZÍSKAT | Stav limitu sazby na účet
|
||||
| Trasa | Metody | Účel |
|
||||
| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| `/api/provider-models` | GET/POST/DELETE | CRUD pro vlastní modely na poskytovatele |
|
||||
| `/api/models/catalog` | GET | Agregovaný katalog všech modelů (chat, embedding, image, custom) seskupených podle poskytovatele |
|
||||
| `/api/settings/proxy` | GET/PUT/DELETE | Konfigurace hierarchické odchozí proxy ( `global/providers/combos/keys` ) |
|
||||
| `/api/settings/proxy/test` | POST | Ověřuje připojení proxy a vrací veřejnou IP adresu/latenci |
|
||||
| `/v1/providers/[provider]/chat/completions` | POST | Vyhrazené dokončování chatu pro jednotlivé poskytovatele s ověřováním modelu |
|
||||
| `/v1/providers/[provider]/embeddings` | POST | Vyhrazené vkládání pro jednotlivé poskytovatele s ověřováním modelu |
|
||||
| `/v1/providers/[provider]/images/generations` | POST | Vyhrazené generování obrázků pro každého poskytovatele s ověřováním modelu |
|
||||
| `/api/settings/ip-filter` | GET/PUT | Správa povolených/blokovaných IP adres |
|
||||
| `/api/settings/thinking-budget` | GET/PUT | Konfigurace rozpočtu tokenů zdůvodnění (průchozí/automatická/vlastní/adaptivní) |
|
||||
| `/api/settings/system-prompt` | GET/PUT | Globální vložení systémového promptu pro všechny požadavky |
|
||||
| `/api/sessions` | GET | Sledování a metriky aktivních relací |
|
||||
| `/api/rate-limits` | GET | Stav limitu sazby na účet |
|
||||
|
||||
---
|
||||
|
||||
@@ -512,38 +512,38 @@ K hlášenému využití je přidána vyrovnávací paměť o kapacitě 2000 tok
|
||||
|
||||
## 6. Podporované formáty
|
||||
|
||||
Formát | Směr | Identifikátor
|
||||
--- | --- | ---
|
||||
Dokončení chatu OpenAI | zdroj + cíl | `openai`
|
||||
API pro odpovědi OpenAI | zdroj + cíl | `openai-responses`
|
||||
Antropický Claude | zdroj + cíl | `claude`
|
||||
Google Gemini | zdroj + cíl | `gemini`
|
||||
Rozhraní příkazového řádku Google Gemini | pouze cíl | `gemini-cli`
|
||||
Antigravitace | zdroj + cíl | `antigravity`
|
||||
AWS Kiro | pouze cíl | `kiro`
|
||||
Kurzor | pouze cíl | `cursor`
|
||||
| Formát | Směr | Identifikátor |
|
||||
| ----------------------- | ----------- | ------------------ |
|
||||
| OpenAI Chat Completions | zdroj + cíl | `openai` |
|
||||
| OpenAI Responses API | zdroj + cíl | `openai-responses` |
|
||||
| Anthropic Claude | zdroj + cíl | `claude` |
|
||||
| Google Gemini | zdroj + cíl | `gemini` |
|
||||
| Google Gemini CLI | jen cíl | `gemini-cli` |
|
||||
| Antigravity | zdroj + cíl | `antigravity` |
|
||||
| AWS Kiro | jen cíl | `kiro` |
|
||||
| Cursor | jen cíl | `cursor` |
|
||||
|
||||
---
|
||||
|
||||
## 7. Podporovaní poskytovatelé
|
||||
|
||||
Poskytovatel | Metoda ověřování | Vykonavatel | Klíčové poznámky
|
||||
--- | --- | --- | ---
|
||||
Antropický Claude | Klíč API nebo OAuth | Výchozí | Používá hlavičku `x-api-key`
|
||||
Google Gemini | Klíč API nebo OAuth | Výchozí | Používá hlavičku `x-goog-api-key`
|
||||
Rozhraní příkazového řádku Google Gemini | OAuth | GeminiCLI | Používá koncový bod `streamGenerateContent`
|
||||
Antigravitace | OAuth | Antigravitace | Záložní více URL adres, vlastní analýza opakovaných pokusů
|
||||
OpenAI | Klíč API | Výchozí | Autorizace standardního nosiče
|
||||
Kodex | OAuth | Kodex | Vkládá systémové instrukce, řídí myšlení
|
||||
GitHub Copilot | OAuth + token Copilot | Github | Duální token, napodobování záhlaví VSCode
|
||||
Kiro (AWS) | AWS SSO OIDC nebo sociální sítě | Kiro | Analýza binárního EventStreamu
|
||||
IDE kurzoru | Autorizace kontrolního součtu | Kurzor | Kódování Protobuf, kontrolní součty SHA-256
|
||||
Qwen | OAuth | Výchozí | Standardní ověřování
|
||||
iFlow | OAuth (základní + nosič) | Výchozí | Duální hlavička pro autorizaci
|
||||
OpenRouter | Klíč API | Výchozí | Autorizace standardního nosiče
|
||||
GLM, Kimi, MiniMax | Klíč API | Výchozí | Kompatibilní s Claude, použijte `x-api-key`
|
||||
`openai-compatible-*` | Klíč API | Výchozí | Dynamické: jakýkoli koncový bod kompatibilní s OpenAI
|
||||
`anthropic-compatible-*` | Klíč API | Výchozí | Dynamický: jakýkoli koncový bod kompatibilní s Claude
|
||||
| Poskytovatel | Metoda ověřování | Vykonavatel | Klíčové poznámky |
|
||||
| ------------------------ | ------------------------ | ----------- | -------------------------------------------- |
|
||||
| Anthropic Claude | API klíč nebo OAuth | Výchozí | Používá hlavičku `x-api-key` |
|
||||
| Google Gemini | API klíč nebo OAuth | Výchozí | Používá hlavičku `x-goog-api-key` |
|
||||
| Google Gemini CLI | OAuth | GeminiCLI | Používá koncový bod `streamGenerateContent` |
|
||||
| Antigravity | OAuth | Antigravity | Záložní více URL, analýza opakovaných pokusů |
|
||||
| OpenAI | API klíč | Výchozí | Autorizace standardního nosiče |
|
||||
| Codex | OAuth | Codex | Vkládá systémové instrukce, řídí myšlení |
|
||||
| GitHub Copilot | OAuth + Copilot token | Github | Duální token, napodobování záhlaví VSCode |
|
||||
| Kiro (AWS) | AWS SSO OIDC nebo Social | Kiro | Analýza binárního EventStreamu |
|
||||
| Cursor IDE | Checksum auth | Cursor | Kódování Protobuf, kontrolní součty SHA-256 |
|
||||
| Qwen | OAuth | Výchozí | Standardní ověřování |
|
||||
| Qoder | OAuth (Basic + Bearer) | Výchozí | Duální hlavička pro autorizaci |
|
||||
| OpenRouter | API klíč | Výchozí | Autorizace standardního nosiče |
|
||||
| GLM, Kimi, MiniMax | API klíč | Výchozí | Kompatibilní s Claude, použijte `x-api-key` |
|
||||
| `openai-compatible-*` | API klíč | Výchozí | Dynamické: jakýkoli OpenAI kompatibilní |
|
||||
| `anthropic-compatible-*` | API klíč | Výchozí | Dynamické: jakýkoli Claude kompatibilní |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Vizuální průvodce všemi částmi ovládacího panelu OmniRoute.
|
||||
|
||||
## 🔌 Poskytovatelé
|
||||
|
||||
Spravujte připojení poskytovatelů AI: poskytovatelé OAuth (Claude Code, Codex, Gemini CLI), poskytovatelé klíčů API (Groq, DeepSeek, OpenRouter) a bezplatní poskytovatelé (iFlow, Qwen, Kiro). Účty Kiro zahrnují sledování zůstatku kreditů – zbývající kredity, celkový limit a datum obnovení jsou viditelné v Dashboard → Usage.
|
||||
Spravujte připojení poskytovatelů AI: poskytovatelé OAuth (Claude Code, Codex, Gemini CLI), poskytovatelé klíčů API (Groq, DeepSeek, OpenRouter) a bezplatní poskytovatelé (Qoder, Qwen, Kiro). Účty Kiro zahrnují sledování zůstatku kreditů – zbývající kredity, celkový limit a datum obnovení jsou viditelné v Dashboard → Usage.
|
||||
|
||||

|
||||
|
||||
@@ -46,13 +46,13 @@ Monitorování v reálném čase: dostupnost, paměť, verze, percentily latence
|
||||
|
||||
---
|
||||
|
||||
## 🎮 Modelové hřiště *(v2.0.9+)*
|
||||
## 🎮 Modelové hřiště _(v2.0.9+)_
|
||||
|
||||
Otestujte libovolný model přímo z řídicího panelu. Vyberte poskytovatele, model a koncový bod, pište výzvy pomocí editoru Monaco, streamujte odpovědi v reálném čase, přerušte stream a zobrazte metriky časování.
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Témata *(v2.0.5+)*
|
||||
## 🎨 Témata _(v2.0.5+)_
|
||||
|
||||
Přizpůsobitelná barevná témata pro celý dashboard. Vyberte si ze 7 přednastavených barev (korálová, modrá, červená, zelená, fialová, oranžová, azurová) nebo si vytvořte vlastní téma výběrem libovolné hexadecimální barvy. Podporuje světlý, tmavý a systémový režim.
|
||||
|
||||
@@ -81,7 +81,7 @@ Konfigurace nástrojů pro kódování s umělou inteligencí jedním kliknutím
|
||||
|
||||
---
|
||||
|
||||
## 🤖 Agenti CLI *(v2.0.11+)*
|
||||
## 🤖 Agenti CLI _(v2.0.11+)_
|
||||
|
||||
Ovládací panel pro vyhledávání a správu agentů CLI. Zobrazuje mřížku 14 vestavěných agentů (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) s:
|
||||
|
||||
@@ -92,7 +92,7 @@ Ovládací panel pro vyhledávání a správu agentů CLI. Zobrazuje mřížku 1
|
||||
|
||||
---
|
||||
|
||||
## 🖼️ Média *(v2.0.3+)*
|
||||
## 🖼️ Média _(v2.0.3+)_
|
||||
|
||||
Generujte obrázky, videa a hudbu z řídicího panelu. Podporuje OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open a MusicGen.
|
||||
|
||||
|
||||
+261
-455
File diff suppressed because it is too large
Load Diff
@@ -8,13 +8,13 @@ Běžné problémy a řešení pro OmniRoute.
|
||||
|
||||
## Rychlé opravy
|
||||
|
||||
Problém | Řešení
|
||||
--- | ---
|
||||
První přihlášení nefunguje | Nastavit `INITIAL_PASSWORD` v `.env` (bez pevně zakódovaného výchozího nastavení)
|
||||
Dashboard se otevírá na nesprávném portu | Nastavte `PORT=20128` a `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
|
||||
Žádné protokoly požadavků v sekci `logs/` | Nastavte `ENABLE_REQUEST_LOGS=true`
|
||||
PŘÍSTUP: povolení zamítnuto | Nastavením `DATA_DIR=/path/to/writable/dir` přepíšete `~/.omniroute`
|
||||
Strategie směrování se neukládá | Aktualizace na v1.4.11+ (oprava schématu Zod pro perzistenci nastavení)
|
||||
| Problém | Řešení |
|
||||
| ----------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| První přihlášení nefunguje | Nastavit `INITIAL_PASSWORD` v `.env` (bez pevně zakódovaného výchozího nastavení) |
|
||||
| Dashboard se otevírá na nesprávném portu | Nastavte `PORT=20128` a `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
|
||||
| Žádné protokoly požadavků v sekci `logs/` | Nastavte `ENABLE_REQUEST_LOGS=true` |
|
||||
| PŘÍSTUP: povolení zamítnuto | Nastavením `DATA_DIR=/path/to/writable/dir` přepíšete `~/.omniroute` |
|
||||
| Strategie směrování se neukládá | Aktualizace na v1.4.11+ (oprava schématu Zod pro perzistenci nastavení) |
|
||||
|
||||
---
|
||||
|
||||
@@ -97,7 +97,7 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,
|
||||
|
||||
1. Zkontrolujte statistiky využití v sekci Nástěnka → Využití
|
||||
2. Přepnout primární model na GLM/MiniMax
|
||||
3. Pro nekritické úlohy použijte bezplatnou úroveň (Gemini CLI, iFlow).
|
||||
3. Pro nekritické úlohy použijte bezplatnou úroveň (Gemini CLI, Qoder).
|
||||
4. Nastavení rozpočtů nákladů pro každý klíč API: Dashboard → API klíče → Rozpočet
|
||||
|
||||
---
|
||||
@@ -169,12 +169,12 @@ Pokud poskytovatel opakovaně přechází do stavu OTEVŘENO:
|
||||
|
||||
Pro ladění problémů s překladem formátu použijte **Dashboard → Translator** :
|
||||
|
||||
Režim | Kdy použít
|
||||
--- | ---
|
||||
**Dětské hřiště** | Porovnejte vstupní/výstupní formáty vedle sebe – vložte neúspěšný požadavek a podívejte se, jak se přeloží
|
||||
**Tester chatu** | Odesílejte živé zprávy a kontrolujte kompletní datovou část požadavků/odpovědí včetně záhlaví
|
||||
**Zkušební stolice** | Spusťte dávkové testy napříč kombinacemi formátů a zjistěte, které překlady jsou poškozené.
|
||||
**Živý monitor** | Sledujte tok požadavků v reálném čase a zachyťte občasné problémy s překladem
|
||||
| Režim | Kdy použít |
|
||||
| -------------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| **Dětské hřiště** | Porovnejte vstupní/výstupní formáty vedle sebe – vložte neúspěšný požadavek a podívejte se, jak se přeloží |
|
||||
| **Tester chatu** | Odesílejte živé zprávy a kontrolujte kompletní datovou část požadavků/odpovědí včetně záhlaví |
|
||||
| **Zkušební stolice** | Spusťte dávkové testy napříč kombinacemi formátů a zjistěte, které překlady jsou poškozené. |
|
||||
| **Živý monitor** | Sledujte tok požadavků v reálném čase a zachyťte občasné problémy s překladem |
|
||||
|
||||
### Běžné problémy s formátováním
|
||||
|
||||
@@ -230,9 +230,9 @@ Pokud chcete sdílenou slovní zásobu pro popis těchto selhání, můžete pou
|
||||
Myšlenka je jednoduchá:
|
||||
|
||||
1. Při vyšetřování špatné odpovědi zaznamenejte:
|
||||
- úkol a požadavek uživatele
|
||||
- Kombinace trasy nebo poskytovatele v OmniRoute
|
||||
- jakýkoli kontext RAG použitý v následných fázích (načtené dokumenty, volání nástrojů atd.)
|
||||
- úkol a požadavek uživatele
|
||||
- Kombinace trasy nebo poskytovatele v OmniRoute
|
||||
- jakýkoli kontext RAG použitý v následných fázích (načtené dokumenty, volání nástrojů atd.)
|
||||
2. Namapujte incident na jedno nebo dvě čísla z WFGY ProblemMap ( `No.1` … `No.16` ).
|
||||
3. Uložte číslo do vlastního řídicího panelu, runbooku nebo sledovače incidentů vedle protokolů OmniRoute.
|
||||
4. Pro rozhodnutí, zda je potřeba změnit RAG stack, retriever nebo směrovací strategii, použijte odpovídající stránku WFGY.
|
||||
|
||||
+115
-121
@@ -20,30 +20,30 @@ Kompletní průvodce konfigurací poskytovatelů, vytvářením kombinací, inte
|
||||
|
||||
## 💰 Přehled cen
|
||||
|
||||
Úroveň | Poskytovatel | Náklady | Obnovení kvóty | Nejlepší pro
|
||||
--- | --- | --- | --- | ---
|
||||
**💳 PŘEDPLATNÉ** | Claude Code (profesionál) | 20 dolarů měsíčně | 5 hodin + týdně | Již přihlášen/a k odběru
|
||||
| Kodex (Plus/Pro) | 20–200 USD/měsíc | 5 hodin + týdně | Uživatelé OpenAI
|
||||
| Rozhraní příkazového řádku Gemini | **UVOLNIT** | 180 tisíc měsíčně + 1 tisíc denně | Každý!
|
||||
| GitHub Copilot | 10–19 USD/měsíc | Měsíční | Uživatelé GitHubu
|
||||
**🔑 KLÍČ API** | Hluboké vyhledávání | Platba za použití | Žádný | Laciné uvažování
|
||||
| Groq | Platba za použití | Žádný | Ultrarychlá inference
|
||||
| xAI (Grok) | Platba za použití | Žádný | Grok 4 uvažování
|
||||
| Mistral | Platba za použití | Žádný | Modely hostované v EU
|
||||
| Zmatek | Platba za použití | Žádný | Rozšířené vyhledávání
|
||||
| Společně s umělou inteligencí | Platba za použití | Žádný | Modely s otevřeným zdrojovým kódem
|
||||
| Ohňostroj s umělou inteligencí | Platba za použití | Žádný | Rychlé snímky FLUX
|
||||
| Mozky | Platba za použití | Žádný | Rychlost v měřítku destičky
|
||||
| Soudržný | Platba za použití | Žádný | Příkaz R+ RAG
|
||||
| NVIDIA NIM | Platba za použití | Žádný | Podnikové modely
|
||||
**💰 LEVNÉ** | GLM-4.7 | 0,6 USD/1 milion | Denně v 10:00 | Záloha rozpočtu
|
||||
| MiniMax M2.1 | 0,2 USD/1 milion | 5hodinové válcování | Nejlevnější varianta
|
||||
| Kimi K2 | 9 dolarů měsíčně bez závazků | 10 milionů tokenů/měsíc | Předvídatelné náklady
|
||||
**🆓 ZDARMA** | iFlow | 0 dolarů | Neomezený | 8 modelů zdarma
|
||||
| Qwen | 0 dolarů | Neomezený | 3 modely zdarma
|
||||
| Kiro | 0 dolarů | Neomezený | Claude zdarma
|
||||
| Úroveň | Poskytovatel | Náklady | Obnovení kvóty | Nejlepší pro |
|
||||
| ----------------- | ----------------- | ---------------- | ------------------- | -------------------------- |
|
||||
| **💳 PŘEDPLATNÉ** | Claude Code (pro) | 20 USD měsíc | 5h + týdně | Již přihlášené |
|
||||
| | Kodex (Plus/Pro) | 20–200 USD/měsíc | 5h + týdně | Uživatele OpenAI |
|
||||
| | Gemini CLI | **ZDARMA** | 180K/mo + 1K/den | Každého! |
|
||||
| | GitHub Copilot | 10–19 USD/měsíc | Měsíční | Uživatele GitHubu |
|
||||
| **🔑 KLÍČ API** | DeepSeek | Dle užití | Žádné | Laciné uvažování |
|
||||
| | Groq | Dle užití | Žádné | Ultrarychlá inference |
|
||||
| | xAI (Grok) | Dle užití | Žádné | Grok 4 uvažování |
|
||||
| | Mistral | Dle užití | Žádné | Modely hostované v EU |
|
||||
| | Perplexity | Dle užití | Žádné | Rozšířené vyhledávání |
|
||||
| | Together AI | Dle užití | Žádné | Open Source modely |
|
||||
| | Fireworks AI | Dle užití | Žádné | Rychlé FLUX obrázky |
|
||||
| | Cerebras | Dle užití | Žádné | Rychlost destičkového čipu |
|
||||
| | Cohere | Dle užití | Žádné | Command R+ RAG |
|
||||
| | NVIDIA NIM | Dle užití | Žádné | Podnikové modely |
|
||||
| **💰 LEVNÉ** | GLM-4.7 | $0.6/1M | Denně 10:00 | Levná záloha |
|
||||
| | MiniMax M2.1 | $0.2/1M | 5hodinové válcování | Nejlevnější varianta |
|
||||
| | Kimi K2 | 9 USD měsíc | 10M tokens/měsíc | Předvídatelné náklady |
|
||||
| **🆓 ZDARMA** | Qoder | $0 | Neomezený | 8 modelů zdarma |
|
||||
| | Qwen | $0 | Neomezený | 3 modely zdarma |
|
||||
| | Kiro | $0 | Neomezený | Claude zdarma |
|
||||
|
||||
**💡 Tip pro profesionály:** Začněte s kombinací Gemini CLI (180 tisíc zdarma/měsíc) + iFlow (neomezeně zdarma) = 0 dolarů!
|
||||
**💡 Pro Tip:** Začněte s kombinací Gemini CLI (180K zdarma/měsíc) + Qoder (neomezeně zdarma) = $0!
|
||||
|
||||
---
|
||||
|
||||
@@ -193,10 +193,10 @@ Models:
|
||||
|
||||
### 🆓 Poskytovatelé ZDARMA
|
||||
|
||||
#### iFlow (8 modelů ZDARMA)
|
||||
#### Qoder (8 modelů ZDARMA)
|
||||
|
||||
```bash
|
||||
Dashboard → Connect iFlow → OAuth login → Unlimited usage
|
||||
Dashboard → Connect Qoder → OAuth login → Unlimited usage
|
||||
|
||||
Models: if/kimi-k2-thinking, if/qwen3-coder-plus, if/glm-4.7, if/minimax-m2, if/deepseek-r1
|
||||
```
|
||||
@@ -271,7 +271,7 @@ Upravit `~/.claude/config.json` :
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Codexu
|
||||
### Codex CLI
|
||||
|
||||
```bash
|
||||
export OPENAI_BASE_URL="http://localhost:20128"
|
||||
@@ -335,7 +335,7 @@ omniroute
|
||||
omniroute --port 3000
|
||||
```
|
||||
|
||||
Rozhraní příkazového řádku automaticky načte `.env` z adresáře `~/.omniroute/.env` nebo `./.env` .
|
||||
CLI automaticky načte `.env` z adresáře `~/.omniroute/.env` nebo `./.env` .
|
||||
|
||||
### Nasazení VPS
|
||||
|
||||
@@ -407,23 +407,23 @@ Informace o režimu integrovaném s hostitelem s binárními soubory CLI nalezne
|
||||
|
||||
### Proměnné prostředí
|
||||
|
||||
Proměnná | Výchozí | Popis
|
||||
--- | --- | ---
|
||||
`JWT_SECRET` | `omniroute-default-secret-change-me` | Tajný klíč podpisu JWT ( **změna v produkčním prostředí** )
|
||||
`INITIAL_PASSWORD` | `123456` | První přihlašovací heslo
|
||||
`DATA_DIR` | `~/.omniroute` | Datový adresář (db, využití, protokoly)
|
||||
`PORT` | výchozí nastavení rámce | Servisní port ( `20128` v příkladech)
|
||||
`HOSTNAME` | výchozí nastavení rámce | Vázat hostitele (Docker má výchozí hodnotu `0.0.0.0` )
|
||||
`NODE_ENV` | výchozí nastavení za běhu | Nastavení `production` pro nasazení
|
||||
`BASE_URL` | `http://localhost:20128` | Interní základní URL na straně serveru
|
||||
`CLOUD_URL` | `https://omniroute.dev` | Základní adresa URL koncového bodu synchronizace s cloudem
|
||||
`API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | Tajný klíč HMAC pro generované klíče API
|
||||
`REQUIRE_API_KEY` | `false` | Vynutit klíč rozhraní Bearer API na `/v1/*`
|
||||
`ENABLE_REQUEST_LOGS` | `false` | Povoluje protokolování požadavků/odpovědí
|
||||
`AUTH_COOKIE_SECURE` | `false` | Vynutit soubor cookie `Secure` ověřování (za reverzní proxy HTTPS)
|
||||
`OMNIROUTE_MEMORY_MB` | `512` | Limit haldy Node.js v MB
|
||||
`PROMPT_CACHE_MAX_SIZE` | `50` | Maximální počet položek mezipaměti výzev
|
||||
`SEMANTIC_CACHE_MAX_SIZE` | `100` | Maximální počet položek sémantické mezipaměti
|
||||
| Proměnná | Výchozí | Popis |
|
||||
| ------------------------- | ------------------------------------ | ------------------------------------------------------------------ |
|
||||
| `JWT_SECRET` | `omniroute-default-secret-change-me` | Tajný klíč podpisu JWT ( **změna v produkčním prostředí** ) |
|
||||
| `INITIAL_PASSWORD` | `123456` | První přihlašovací heslo |
|
||||
| `DATA_DIR` | `~/.omniroute` | Datový adresář (db, využití, protokoly) |
|
||||
| `PORT` | výchozí nastavení rámce | Servisní port ( `20128` v příkladech) |
|
||||
| `HOSTNAME` | výchozí nastavení rámce | Vázat hostitele (Docker má výchozí hodnotu `0.0.0.0` ) |
|
||||
| `NODE_ENV` | výchozí nastavení za běhu | Nastavení `production` pro nasazení |
|
||||
| `BASE_URL` | `http://localhost:20128` | Interní základní URL na straně serveru |
|
||||
| `CLOUD_URL` | `https://omniroute.dev` | Základní adresa URL koncového bodu synchronizace s cloudem |
|
||||
| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | Tajný klíč HMAC pro generované klíče API |
|
||||
| `REQUIRE_API_KEY` | `false` | Vynutit klíč rozhraní Bearer API na `/v1/*` |
|
||||
| `ENABLE_REQUEST_LOGS` | `false` | Povoluje protokolování požadavků/odpovědí |
|
||||
| `AUTH_COOKIE_SECURE` | `false` | Vynutit soubor cookie `Secure` ověřování (za reverzní proxy HTTPS) |
|
||||
| `OMNIROUTE_MEMORY_MB` | `512` | Limit haldy Node.js v MB |
|
||||
| `PROMPT_CACHE_MAX_SIZE` | `50` | Maximální počet položek mezipaměti výzev |
|
||||
| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Maximální počet položek sémantické mezipaměti |
|
||||
|
||||
Úplný přehled proměnných prostředí naleznete v souboru [README](../README.md) .
|
||||
|
||||
@@ -439,7 +439,7 @@ Proměnná | Výchozí | Popis
|
||||
|
||||
**Codex ( `cx/` )** — Plus/Pro: `cx/gpt-5.2-codex` , `cx/gpt-5.1-codex-max`
|
||||
|
||||
**Rozhraní příkazového řádku Gemini ( `gc/` )** — ZDARMA: `gc/gemini-3-flash-preview` , `gc/gemini-2.5-pro`
|
||||
**Gemini CLI ( `gc/` )** — ZDARMA: `gc/gemini-3-flash-preview` , `gc/gemini-2.5-pro`
|
||||
|
||||
**GitHub Copilot ( `gh/` )** : `gh/gpt-5` , `gh/claude-4.5-sonnet`
|
||||
|
||||
@@ -447,7 +447,7 @@ Proměnná | Výchozí | Popis
|
||||
|
||||
**MiniMax ( `minimax/` )** — 0,2 USD/1 milion: `minimax/MiniMax-M2.1`
|
||||
|
||||
**iFlow ( `if/` )** — ZDARMA: `if/kimi-k2-thinking` , `if/qwen3-coder-plus` , `if/deepseek-r1`
|
||||
**Qoder ( `if/` )** — ZDARMA: `if/kimi-k2-thinking` , `if/qwen3-coder-plus` , `if/deepseek-r1`
|
||||
|
||||
**Qwen ( `qw/` )** — ZDARMA: `qw/qwen3-coder-plus` , `qw/qwen3-coder-flash`
|
||||
|
||||
@@ -473,9 +473,6 @@ Proměnná | Výchozí | Popis
|
||||
|
||||
**NVIDIA NIM ( `nvidia/` )** : `nvidia/nvidia/llama-3.3-70b-instruct`
|
||||
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 🧩 Pokročilé funkce
|
||||
@@ -552,12 +549,12 @@ Vrátí modely seskupené podle poskytovatele s typy ( `chat` , `embedding` , `i
|
||||
|
||||
Přístup přes **Dashboard → Translator** . Ladění a vizualizace toho, jak OmniRoute překládá požadavky API mezi poskytovateli.
|
||||
|
||||
Režim | Účel
|
||||
--- | ---
|
||||
**Dětské hřiště** | Vyberte zdrojový/cílový formát, vložte požadavek a okamžitě si prohlédněte přeložený výstup
|
||||
**Tester chatu** | Odesílejte zprávy živého chatu přes proxy a kontrolujte celý cyklus požadavku/odpovědi
|
||||
**Zkušební stolice** | Spusťte dávkové testy napříč různými kombinacemi formátů pro ověření správnosti překladu
|
||||
**Živý monitor** | Sledujte překlady v reálném čase, jak požadavky procházejí proxy serverem
|
||||
| Režim | Účel |
|
||||
| -------------------- | ------------------------------------------------------------------------------------------- |
|
||||
| **Dětské hřiště** | Vyberte zdrojový/cílový formát, vložte požadavek a okamžitě si prohlédněte přeložený výstup |
|
||||
| **Tester chatu** | Odesílejte zprávy živého chatu přes proxy a kontrolujte celý cyklus požadavku/odpovědi |
|
||||
| **Zkušební stolice** | Spusťte dávkové testy napříč různými kombinacemi formátů pro ověření správnosti překladu |
|
||||
| **Živý monitor** | Sledujte překlady v reálném čase, jak požadavky procházejí proxy serverem |
|
||||
|
||||
**Případy použití:**
|
||||
|
||||
@@ -571,14 +568,14 @@ Režim | Účel
|
||||
|
||||
Konfigurace přes **Dashboard → Nastavení → Routing** .
|
||||
|
||||
Strategie | Popis
|
||||
--- | ---
|
||||
**Nejprve vyplňte** | Používá účty podle priority – primární účet zpracovává všechny požadavky, dokud není k dispozici.
|
||||
**Round Robin** | Cykluje mezi všemi účty s nastavitelným trvalým limitem (výchozí: 3 volání na účet)
|
||||
**P2C (Síla dvou možností)** | Vybere 2 náhodné účty a nasměruje je k tomu zdravějšímu – vyvažuje zátěž s povědomím o zdraví
|
||||
**Náhodný** | Náhodně vybere účet pro každý požadavek pomocí Fisher-Yatesova náhodného výběru.
|
||||
**Nejméně používané** | Směruje k účtu s nejstarším časovým razítkem `lastUsedAt` a rovnoměrně rozděluje provoz.
|
||||
**Optimalizované náklady** | Směruje k účtu s nejnižší prioritou a optimalizuje pro poskytovatele s nejnižšími náklady.
|
||||
| Strategie | Popis |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| **Nejprve vyplňte** | Používá účty podle priority – primární účet zpracovává všechny požadavky, dokud není k dispozici. |
|
||||
| **Round Robin** | Cykluje mezi všemi účty s nastavitelným trvalým limitem (výchozí: 3 volání na účet) |
|
||||
| **P2C (Síla dvou možností)** | Vybere 2 náhodné účty a nasměruje je k tomu zdravějšímu – vyvažuje zátěž s povědomím o zdraví |
|
||||
| **Náhodný** | Náhodně vybere účet pro každý požadavek pomocí Fisher-Yatesova náhodného výběru. |
|
||||
| **Nejméně používané** | Směruje k účtu s nejstarším časovým razítkem `lastUsedAt` a rovnoměrně rozděluje provoz. |
|
||||
| **Optimalizované náklady** | Směruje k účtu s nejnižší prioritou a optimalizuje pro poskytovatele s nejnižšími náklady. |
|
||||
|
||||
#### Aliasy zástupných znaků modelů
|
||||
|
||||
@@ -611,24 +608,21 @@ Konfigurace přes **Dashboard → Settings → Resilience** .
|
||||
OmniRoute implementuje odolnost na úrovni poskytovatele se čtyřmi komponentami:
|
||||
|
||||
1. **Profily poskytovatelů** – Konfigurace pro jednotlivé poskytovatele pro:
|
||||
|
||||
- Práh selhání (počet selhání před otevřením)
|
||||
- Doba zchlazení
|
||||
- Citlivost detekce limitu frekvence
|
||||
- Exponenciální backoff parametry
|
||||
- Práh selhání (počet selhání před otevřením)
|
||||
- Doba zchlazení
|
||||
- Citlivost detekce limitu frekvence
|
||||
- Exponenciální backoff parametry
|
||||
|
||||
2. **Upravitelné limity rychlosti** – Výchozí nastavení na úrovni systému konfigurovatelná na řídicím panelu:
|
||||
|
||||
- **Požadavky za minutu (RPM)** — Maximální počet požadavků za minutu na účet
|
||||
- **Minimální doba mezi požadavky** — Minimální mezera v milisekundách mezi požadavky
|
||||
- **Max. počet souběžných požadavků** — Maximální počet souběžných požadavků na účet
|
||||
- Klikněte na **Upravit** pro úpravu a poté **na Uložit** nebo **Zrušit** . Hodnoty se ukládají prostřednictvím rozhraní API pro odolnost.
|
||||
- **Požadavky za minutu (RPM)** — Maximální počet požadavků za minutu na účet
|
||||
- **Minimální doba mezi požadavky** — Minimální mezera v milisekundách mezi požadavky
|
||||
- **Max. počet souběžných požadavků** — Maximální počet souběžných požadavků na účet
|
||||
- Klikněte na **Upravit** pro úpravu a poté **na Uložit** nebo **Zrušit** . Hodnoty se ukládají prostřednictvím rozhraní API pro odolnost.
|
||||
|
||||
3. **Jistič** – Sleduje poruchy u jednotlivých poskytovatelů a automaticky rozpojuje obvod, když je dosaženo prahové hodnoty:
|
||||
|
||||
- **ZAVŘENO** (v pořádku) – Požadavky probíhají normálně.
|
||||
- **OTEVŘENO** — Poskytovatel je dočasně zablokován po opakovaných selháních
|
||||
- **HALF_OPEN** — Testování, zda se poskytovatel zotavil
|
||||
- **ZAVŘENO** (v pořádku) – Požadavky probíhají normálně.
|
||||
- **OTEVŘENO** — Poskytovatel je dočasně zablokován po opakovaných selháních
|
||||
- **HALF_OPEN** — Testování, zda se poskytovatel zotavil
|
||||
|
||||
4. **Zásady a uzamčené identifikátory** – Zobrazuje stav jističe a uzamčené identifikátory s možností vynuceného odemčení.
|
||||
|
||||
@@ -642,11 +636,11 @@ OmniRoute implementuje odolnost na úrovni poskytovatele se čtyřmi komponentam
|
||||
|
||||
Správa záloh databáze se provádí v **nabídce Ovládací panel → Nastavení → Systém a úložiště** .
|
||||
|
||||
Akce | Popis
|
||||
--- | ---
|
||||
**Exportovat databázi** | Stáhne aktuální databázi SQLite jako soubor `.sqlite`
|
||||
**Exportovat vše (.tar.gz)** | Stáhne kompletní zálohu včetně: databáze, nastavení, kombinací, připojení k poskytovatelům (bez přihlašovacích údajů) a metadat klíče API.
|
||||
**Importovat databázi** | Nahrajte soubor `.sqlite` , který nahradí aktuální databázi. Záloha před importem se vytvoří automaticky.
|
||||
| Akce | Popis |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **Exportovat databázi** | Stáhne aktuální databázi SQLite jako soubor `.sqlite` |
|
||||
| **Exportovat vše (.tar.gz)** | Stáhne kompletní zálohu včetně: databáze, nastavení, kombinací, připojení k poskytovatelům (bez přihlašovacích údajů) a metadat klíče API. |
|
||||
| **Importovat databázi** | Nahrajte soubor `.sqlite` , který nahradí aktuální databázi. Záloha před importem se vytvoří automaticky. |
|
||||
|
||||
```bash
|
||||
# API: Export database
|
||||
@@ -674,13 +668,13 @@ curl -X POST http://localhost:20128/api/db-backups/import \
|
||||
|
||||
Stránka nastavení je pro snadnou navigaci uspořádána do 5 záložek:
|
||||
|
||||
Záložka | Obsah
|
||||
--- | ---
|
||||
**Zabezpečení** | Nastavení přihlášení/hesla, řízení přístupu k IP adrese, autorizace API pro `/models` a blokování poskytovatelů
|
||||
**Směrování** | Globální strategie směrování (6 možností), aliasy zástupných znaků, záložní řetězce, kombinované výchozí hodnoty
|
||||
**Odolnost** | Profily poskytovatelů, upravitelné limity sazeb, stav jističů, zásady a uzamčené identifikátory
|
||||
**Umělá inteligence** | Konfigurace rozpočtu promyšleného projektu, globální vkládání promptu do systému, statistiky mezipaměti promptu
|
||||
**Moderní** | Globální konfigurace proxy (HTTP/SOCKS5)
|
||||
| Záložka | Obsah |
|
||||
| --------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| **Zabezpečení** | Nastavení přihlášení/hesla, řízení přístupu k IP adrese, autorizace API pro `/models` a blokování poskytovatelů |
|
||||
| **Směrování** | Globální strategie směrování (6 možností), aliasy zástupných znaků, záložní řetězce, kombinované výchozí hodnoty |
|
||||
| **Odolnost** | Profily poskytovatelů, upravitelné limity sazeb, stav jističů, zásady a uzamčené identifikátory |
|
||||
| **Umělá inteligence** | Konfigurace rozpočtu promyšleného projektu, globální vkládání promptu do systému, statistiky mezipaměti promptu |
|
||||
| **Moderní** | Globální konfigurace proxy (HTTP/SOCKS5) |
|
||||
|
||||
---
|
||||
|
||||
@@ -688,10 +682,10 @@ Záložka | Obsah
|
||||
|
||||
Přístup přes **Dashboard → Náklady** .
|
||||
|
||||
Záložka | Účel
|
||||
--- | ---
|
||||
**Rozpočet** | Nastavte limity útrat pro každý klíč API s denními/týdenními/měsíčními rozpočty a sledováním v reálném čase
|
||||
**Ceny** | Zobrazení a úprava cenových položek modelu – cena za 1000 vstupních/výstupních tokenů na poskytovatele
|
||||
| Záložka | Účel |
|
||||
| ------------ | ----------------------------------------------------------------------------------------------------------- |
|
||||
| **Rozpočet** | Nastavte limity útrat pro každý klíč API s denními/týdenními/měsíčními rozpočty a sledováním v reálném čase |
|
||||
| **Ceny** | Zobrazení a úprava cenových položek modelu – cena za 1000 vstupních/výstupních tokenů na poskytovatele |
|
||||
|
||||
```bash
|
||||
# API: Set a budget
|
||||
@@ -733,14 +727,14 @@ Podporované zvukové formáty: `mp3` , `wav` , `m4a` , `flac` , `ogg` , `webm`
|
||||
|
||||
Nastavte vyvažování jednotlivých kombinací v **nabídce Dashboard → Kombinace → Vytvořit/Upravit → Strategie** .
|
||||
|
||||
Strategie | Popis
|
||||
--- | ---
|
||||
**Round-Robin** | Postupně prochází modely
|
||||
**Přednost** | Vždy se pokusí o první model; vrací se pouze v případě chyby.
|
||||
**Náhodný** | Pro každý požadavek vybere náhodný model z komba
|
||||
**Vážené** | Trasy proporcionálně na základě přiřazených vah pro každý model
|
||||
**Nejméně používané** | Směruje k modelu s nejmenším počtem nedávných požadavků (používá kombinované metriky)
|
||||
**Optimalizované z hlediska nákladů** | Trasy k nejlevnějšímu dostupnému modelu (používá ceník)
|
||||
| Strategie | Popis |
|
||||
| ------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| **Round-Robin** | Postupně prochází modely |
|
||||
| **Přednost** | Vždy se pokusí o první model; vrací se pouze v případě chyby. |
|
||||
| **Náhodný** | Pro každý požadavek vybere náhodný model z komba |
|
||||
| **Vážené** | Trasy proporcionálně na základě přiřazených vah pro každý model |
|
||||
| **Nejméně používané** | Směruje k modelu s nejmenším počtem nedávných požadavků (používá kombinované metriky) |
|
||||
| **Optimalizované z hlediska nákladů** | Trasy k nejlevnějšímu dostupnému modelu (používá ceník) |
|
||||
|
||||
Globální výchozí hodnoty kombinací lze nastavit v **nabídce Dashboard → Settings → Routing → Combo Defaults** .
|
||||
|
||||
@@ -750,14 +744,14 @@ Globální výchozí hodnoty kombinací lze nastavit v **nabídce Dashboard →
|
||||
|
||||
Přístup přes **Dashboard → Stav** . Přehled stavu systému v reálném čase se 6 kartami:
|
||||
|
||||
Karta | Co to ukazuje
|
||||
--- | ---
|
||||
**Stav systému** | Doba provozuschopnosti, verze, využití paměti, datový adresář
|
||||
**Zdraví poskytovatelů** | Stav jističe podle dodavatele (Zapnuto/Vypnuto/Napůl vypnuto)
|
||||
**Limity sazeb** | Aktivní limit rychlosti cooldownů na účet se zbývajícím časem
|
||||
**Aktivní výluky** | Poskytovatelé dočasně blokovaní politikou uzamčení
|
||||
**Mezipaměť podpisů** | Statistiky mezipaměti pro deduplikaci (aktivní klíče, míra zásahů)
|
||||
**Telemetrie latence** | Agregace latence p50/p95/p99 na poskytovatele
|
||||
| Karta | Co to ukazuje |
|
||||
| ------------------------ | ------------------------------------------------------------------ |
|
||||
| **Stav systému** | Doba provozuschopnosti, verze, využití paměti, datový adresář |
|
||||
| **Zdraví poskytovatelů** | Stav jističe podle dodavatele (Zapnuto/Vypnuto/Napůl vypnuto) |
|
||||
| **Limity sazeb** | Aktivní limit rychlosti cooldownů na účet se zbývajícím časem |
|
||||
| **Aktivní výluky** | Poskytovatelé dočasně blokovaní politikou uzamčení |
|
||||
| **Mezipaměť podpisů** | Statistiky mezipaměti pro deduplikaci (aktivní klíče, míra zásahů) |
|
||||
| **Telemetrie latence** | Agregace latence p50/p95/p99 na poskytovatele |
|
||||
|
||||
**Tip pro profesionály:** Stránka Zdraví se automaticky obnovuje každých 10 sekund. Pomocí karty jističe můžete zjistit, kteří poskytovatelé mají problémy.
|
||||
|
||||
@@ -795,20 +789,20 @@ Výstup → `electron/dist-electron/`
|
||||
|
||||
### Klíčové vlastnosti
|
||||
|
||||
Funkce | Popis
|
||||
--- | ---
|
||||
**Připravenost serveru** | Před zobrazením okna se dotazuje server (žádná prázdná obrazovka)
|
||||
**Systémový zásobník** | Minimalizovat do zásobníku, změnit port, ukončit menu v zásobníku
|
||||
**Správa přístavů** | Změna portu serveru z panelu úloh (automatické restartování serveru)
|
||||
**Zásady zabezpečení obsahu** | Omezující CSP prostřednictvím záhlaví relace
|
||||
**Jedna instance** | V daném okamžiku může běžet pouze jedna instance aplikace
|
||||
**Offline režim** | Dodávaný server Next.js funguje bez internetu
|
||||
| Funkce | Popis |
|
||||
| ----------------------------- | -------------------------------------------------------------------- |
|
||||
| **Připravenost serveru** | Před zobrazením okna se dotazuje server (žádná prázdná obrazovka) |
|
||||
| **Systémový zásobník** | Minimalizovat do zásobníku, změnit port, ukončit menu v zásobníku |
|
||||
| **Správa přístavů** | Změna portu serveru z panelu úloh (automatické restartování serveru) |
|
||||
| **Zásady zabezpečení obsahu** | Omezující CSP prostřednictvím záhlaví relace |
|
||||
| **Jedna instance** | V daném okamžiku může běžet pouze jedna instance aplikace |
|
||||
| **Offline režim** | Dodávaný server Next.js funguje bez internetu |
|
||||
|
||||
### Proměnné prostředí
|
||||
|
||||
Proměnná | Výchozí | Popis
|
||||
--- | --- | ---
|
||||
`OMNIROUTE_PORT` | `20128` | Port serveru
|
||||
`OMNIROUTE_MEMORY_MB` | `512` | Limit haldy Node.js (64–16384 MB)
|
||||
| Proměnná | Výchozí | Popis |
|
||||
| --------------------- | ------- | --------------------------------- |
|
||||
| `OMNIROUTE_PORT` | `20128` | Port serveru |
|
||||
| `OMNIROUTE_MEMORY_MB` | `512` | Limit haldy Node.js (64–16384 MB) |
|
||||
|
||||
📖 Úplná dokumentace: [`electron/README.md`](../electron/README.md)
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
# OmniRoute — Guia de Deploy em VM com Cloudflare
|
||||
# Průvodce nasazením OmniRoute na VM s Cloudflare
|
||||
|
||||
Kompletní instalace a konfigurace OmniRoute u VM (VPS) s gerenciou přes Cloudflare.
|
||||
🌐 **Jazyky:** 🇺🇸 [English](VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](i18n/es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](i18n/fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](i18n/bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](i18n/he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](i18n/ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](i18n/cs/VM_DEPLOYMENT_GUIDE.md)
|
||||
|
||||
Kompletní průvodce instalací a konfigurací OmniRoute na virtuálním stroji (VPS) se správou domény prostřednictvím Cloudflare.
|
||||
|
||||
---
|
||||
|
||||
## Předpoklady
|
||||
|
||||
Položka | Mínimo | Doporučeno
|
||||
--- | --- | ---
|
||||
**Procesor** | 1 virtuální procesor | 2 vCPU
|
||||
**BERAN** | 1 GB | 2 GB
|
||||
**Disko** | 10GB SSD | 25GB SSD
|
||||
**TAK** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS
|
||||
**Domínio** | Registrován v Cloudflare | —
|
||||
**Přístavní dělník** | Docker Engine 24+ | Docker 27+
|
||||
| Položka | Minimální | Doporučeno |
|
||||
| ------------ | --------------------------- | ---------------- |
|
||||
| **Procesor** | 1 virtuální procesor | 2 vCPU |
|
||||
| **RAM** | 1 GB | 2 GB |
|
||||
| **Disk** | 10GB SSD | 25GB SSD |
|
||||
| **CPU** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
|
||||
| **Doména** | Zaregistrována v Cloudflare | — |
|
||||
| **Docker** | Docker Engine 24+ | Docker 27+ |
|
||||
|
||||
**Testados poskytovatelů** : Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
|
||||
**Testovaní poskytovatelé**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
|
||||
|
||||
---
|
||||
|
||||
@@ -23,12 +25,12 @@ Položka | Mínimo | Doporučeno
|
||||
|
||||
### 1.1 Vytvořit ihned
|
||||
|
||||
Žádný preferovaný poskytovatel seu VPS:
|
||||
Žádný preferovaný poskytovatel VPS:
|
||||
|
||||
- Vyberte si Ubuntu 24.04 LTS
|
||||
- Výběr nebo plano minimo (1 vCPU / 1 GB RAM)
|
||||
- Definujte sílu pro root nebo konfiguraci klíče SSH
|
||||
- Anote o **IP público** (např.: `203.0.113.10` )
|
||||
- Vyberte minimální plán (1 vCPU / 1 GB RAM)
|
||||
- Nastavte silné heslo pro root nebo konfiguraci SSH klíče
|
||||
- Poznamenejte si **veřejnou IP** (např.: `203.0.113.10`)
|
||||
|
||||
### 1.2 Připojení přes SSH
|
||||
|
||||
@@ -45,10 +47,10 @@ apt update && apt upgrade -y
|
||||
### 1.4 Instalace Dockeru
|
||||
|
||||
```bash
|
||||
# Instalar dependências
|
||||
# Nainstalovat závislosti
|
||||
apt install -y ca-certificates curl gnupg
|
||||
|
||||
# Adicionar repositório oficial do Docker
|
||||
# Přidat oficiální Docker repository
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
@@ -74,29 +76,29 @@ ufw allow 443/tcp # HTTPS
|
||||
ufw enable
|
||||
```
|
||||
|
||||
> **Dica** : Maximální zabezpečení, omezení jako porty 80 a 443 přístupů pro IP Cloudflare. Veja a seção [Segurança Avançada](#seguran%C3%A7a-avan%C3%A7ada) .
|
||||
> **Tip**: Pro maximální zabezpečení omezte porty 80 a 443 pouze na IP Cloudflare. Viz sekce [Pokročilé zabezpečení](#pokrocilé-zabezpečení).
|
||||
|
||||
---
|
||||
|
||||
## 2. Instalace OmniRoute
|
||||
|
||||
### 2.1 Criar diretório de configuração
|
||||
### 2.1 Vytvořit konfigurační adresář
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/omniroute
|
||||
```
|
||||
|
||||
### 2.2 Criar arquivo de variáveis de ambiente
|
||||
### 2.2 Vytvořit soubor s proměnnými prostředí
|
||||
|
||||
```bash
|
||||
cat > /opt/omniroute/.env << 'EOF'
|
||||
# === Segurança ===
|
||||
JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS
|
||||
INITIAL_PASSWORD=SuaSenhaSegura123!
|
||||
API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA
|
||||
STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA
|
||||
# === Bezpečnost ===
|
||||
JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
|
||||
INITIAL_PASSWORD=YourSecurePassword123!
|
||||
API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
|
||||
STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
|
||||
STORAGE_ENCRYPTION_KEY_VERSION=v1
|
||||
MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO
|
||||
MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
|
||||
|
||||
# === App ===
|
||||
PORT=20128
|
||||
@@ -108,9 +110,9 @@ ENABLE_REQUEST_LOGS=true
|
||||
AUTH_COOKIE_SECURE=false
|
||||
REQUIRE_API_KEY=false
|
||||
|
||||
# === Domain (altere para seu domínio) ===
|
||||
BASE_URL=https://llms.seudominio.com
|
||||
NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
|
||||
# === Doména (změňte na vaši doménu) ===
|
||||
BASE_URL=https://llms.vasedomena.com
|
||||
NEXT_PUBLIC_BASE_URL=https://llms.vasedomena.com
|
||||
|
||||
# === Cloud Sync (opcional) ===
|
||||
# CLOUD_URL=https://cloud.omniroute.online
|
||||
@@ -118,7 +120,7 @@ NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
|
||||
EOF
|
||||
```
|
||||
|
||||
> ⚠️ **DŮLEŽITÉ** : Gere chaves secretas únicas! Použijte `openssl rand -hex 32` para cada chave.
|
||||
> ⚠️ **DŮLEŽITÉ**: Vygenerujte jedinečné tajné klíče! Použijte `openssl rand -hex 32` pro každý klíč.
|
||||
|
||||
### 2.3 Spuštění kontejneru
|
||||
|
||||
@@ -147,19 +149,19 @@ Vývojový příklad: `[DB] SQLite database ready` a `listening on port 20128` .
|
||||
|
||||
## 3. Konfigurace nginx (reverzní proxy)
|
||||
|
||||
### 3.1 Gerar Certificado SSL (Cloudflare Origin)
|
||||
### 3.1 Vygenerovat SSL certifikát (Cloudflare Origin)
|
||||
|
||||
Cloudflare nic neřeší:
|
||||
|
||||
1. Používá **SSL/TLS → Origin Server**
|
||||
2. **Certifikát Clique Create**
|
||||
3. Deixe os padrões (15 ano, *.seudominio.com)
|
||||
2. Klikněte na **Vytvořit certifikát**
|
||||
3. Ponechte výchozí nastavení (15 let, \*.vasedomena.com)
|
||||
4. Zkopírujte nebo zkopírujte **certifikát původu** a **soukromý klíč**
|
||||
|
||||
```bash
|
||||
mkdir -p /etc/nginx/ssl
|
||||
|
||||
# Colar o certificado
|
||||
# Vložit certifikát
|
||||
nano /etc/nginx/ssl/origin.crt
|
||||
|
||||
# Colar a chave privada
|
||||
@@ -188,7 +190,7 @@ server {
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name llms.seudominio.com; # Altere para seu domínio
|
||||
server_name llms.vasedomena.com; # Změňte na vaši doménu
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/origin.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/origin.key;
|
||||
@@ -220,7 +222,7 @@ server {
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name llms.seudominio.com;
|
||||
server_name llms.vasedomena.com;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
NGINX
|
||||
@@ -245,11 +247,11 @@ nginx -t && systemctl reload nginx
|
||||
|
||||
### 4.1 Další DNS registr
|
||||
|
||||
No painel da Cloudflare → DNS:
|
||||
V dashboardu Cloudflare → DNS:
|
||||
|
||||
Typ | Jméno | Obsah | Proxy
|
||||
--- | --- | --- | ---
|
||||
A | `llms` | `203.0.113.10` (IP adresa virtuálního počítače) | ✅ Proxy
|
||||
| Typ | Jméno | Obsah | Proxy |
|
||||
| --- | ------ | ----------------------------------------------- | -------- |
|
||||
| A | `llms` | `203.0.113.10` (IP adresa virtuálního počítače) | ✅ Proxy |
|
||||
|
||||
### 4.2 Konfigurace SSL
|
||||
|
||||
@@ -257,7 +259,7 @@ Em **SSL/TLS → Přehled** :
|
||||
|
||||
- Režim: **Plný (Přísný)**
|
||||
|
||||
Em **SSL/TLS → Edge certifikáty** :
|
||||
V **SSL/TLS → Edge Certificates**:
|
||||
|
||||
- Vždy používat HTTPS: ✅ Zapnuto
|
||||
- Minimální verze TLS: TLS 1.2
|
||||
@@ -266,7 +268,7 @@ Em **SSL/TLS → Edge certifikáty** :
|
||||
### 4.3 Testar
|
||||
|
||||
```bash
|
||||
curl -sI https://llms.seudominio.com/health
|
||||
curl -sI https://llms.vasedomena.com/health
|
||||
# Deve retornar HTTP/2 200
|
||||
```
|
||||
|
||||
@@ -289,14 +291,14 @@ docker run -d --name omniroute --restart unless-stopped \
|
||||
### Verzovní protokoly
|
||||
|
||||
```bash
|
||||
docker logs -f omniroute # Stream em tempo real
|
||||
docker logs -f omniroute # Živý stream
|
||||
docker logs omniroute --tail 50 # Últimas 50 linhas
|
||||
```
|
||||
|
||||
### Ruční zálohování banky
|
||||
|
||||
```bash
|
||||
# Copiar dados do volume para o host
|
||||
# Kopírovat data z volume do hostitele
|
||||
docker cp omniroute:/app/data ./backup-$(date +%F)
|
||||
|
||||
# Ou comprimir todo o volume
|
||||
@@ -321,7 +323,7 @@ docker start omniroute
|
||||
|
||||
```bash
|
||||
cat > /etc/nginx/cloudflare-ips.conf << 'CF'
|
||||
# Cloudflare IPv4 ranges — atualizar periodicamente
|
||||
# Cloudflare IPv4 ranges — aktualizovat pravidelně
|
||||
# https://www.cloudflare.com/ips-v4/
|
||||
set_real_ip_from 173.245.48.0/20;
|
||||
set_real_ip_from 103.21.244.0/22;
|
||||
@@ -342,7 +344,7 @@ real_ip_header CF-Connecting-IP;
|
||||
CF
|
||||
```
|
||||
|
||||
Přidat `nginx.conf` dentro do bloco `http {}` :
|
||||
Přidat do `nginx.conf` do bloku `http {}`:
|
||||
|
||||
```nginx
|
||||
include /etc/nginx/cloudflare-ips.conf;
|
||||
@@ -362,7 +364,7 @@ fail2ban-client status sshd
|
||||
### Bloquear accesso direto na port do Docker
|
||||
|
||||
```bash
|
||||
# Impedir acesso externo direto à porta 20128
|
||||
# Zamezit přímému externímu přístupu k portu 20128
|
||||
iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
|
||||
iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
|
||||
|
||||
@@ -389,11 +391,11 @@ Dokumenty jsou kompletní pro [omnirouteCloud/README.md](../omnirouteCloud/READM
|
||||
|
||||
---
|
||||
|
||||
## Resumo de Portas
|
||||
## Přehled portů
|
||||
|
||||
Porta | Služba | Přístup
|
||||
--- | --- | ---
|
||||
22 | SSH | Veřejné (s fail2ban)
|
||||
80 | nginx HTTP | Přesměrování → HTTPS
|
||||
443 | nginx HTTPS | Prostřednictvím proxy serveru Cloudflare
|
||||
20128 | OmniRoute | Někdy na localhostu (přes nginx)
|
||||
| Port | Služba | Přístup |
|
||||
| ----- | ----------- | ---------------------------------------- |
|
||||
| 22 | SSH | Veřejné (s fail2ban) |
|
||||
| 80 | nginx HTTP | Přesměrování → HTTPS |
|
||||
| 443 | nginx HTTPS | Prostřednictvím proxy serveru Cloudflare |
|
||||
| 20128 | OmniRoute | Někdy na localhostu (přes nginx) |
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Vícejazyčná dokumentace</title>
|
||||
<style>
|
||||
/* From extension vscode.github */
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.vscode-dark img[src$=\#gh-light-mode-only],
|
||||
.vscode-light img[src$=\#gh-dark-mode-only],
|
||||
.vscode-high-contrast:not(.vscode-high-contrast-light) img[src$=\#gh-light-mode-only],
|
||||
.vscode-high-contrast-light img[src$=\#gh-dark-mode-only] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/markdown.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/highlight.css">
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe WPC', 'Segoe UI', system-ui, 'Ubuntu', 'Droid Sans', sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.task-list-item {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.task-list-item-checkbox {
|
||||
margin-left: -20px;
|
||||
vertical-align: middle;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
:root {
|
||||
--color-note: #0969da;
|
||||
--color-tip: #1a7f37;
|
||||
--color-warning: #9a6700;
|
||||
--color-severe: #bc4c00;
|
||||
--color-caution: #d1242f;
|
||||
--color-important: #8250df;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-note: #2f81f7;
|
||||
--color-tip: #3fb950;
|
||||
--color-warning: #d29922;
|
||||
--color-severe: #db6d28;
|
||||
--color-caution: #f85149;
|
||||
--color-important: #a371f7;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
.markdown-alert {
|
||||
padding: 0.5rem 1rem;
|
||||
margin-bottom: 16px;
|
||||
color: inherit;
|
||||
border-left: .25em solid #888;
|
||||
}
|
||||
|
||||
.markdown-alert>:first-child {
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
.markdown-alert>:last-child {
|
||||
margin-bottom: 0
|
||||
}
|
||||
|
||||
.markdown-alert .markdown-alert-title {
|
||||
display: flex;
|
||||
font-weight: 500;
|
||||
align-items: center;
|
||||
line-height: 1
|
||||
}
|
||||
|
||||
.markdown-alert .markdown-alert-title .octicon {
|
||||
margin-right: 0.5rem;
|
||||
display: inline-block;
|
||||
overflow: visible !important;
|
||||
vertical-align: text-bottom;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.markdown-alert.markdown-alert-note {
|
||||
border-left-color: var(--color-note);
|
||||
}
|
||||
|
||||
.markdown-alert.markdown-alert-note .markdown-alert-title {
|
||||
color: var(--color-note);
|
||||
}
|
||||
|
||||
.markdown-alert.markdown-alert-important {
|
||||
border-left-color: var(--color-important);
|
||||
}
|
||||
|
||||
.markdown-alert.markdown-alert-important .markdown-alert-title {
|
||||
color: var(--color-important);
|
||||
}
|
||||
|
||||
.markdown-alert.markdown-alert-warning {
|
||||
border-left-color: var(--color-warning);
|
||||
}
|
||||
|
||||
.markdown-alert.markdown-alert-warning .markdown-alert-title {
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.markdown-alert.markdown-alert-tip {
|
||||
border-left-color: var(--color-tip);
|
||||
}
|
||||
|
||||
.markdown-alert.markdown-alert-tip .markdown-alert-title {
|
||||
color: var(--color-tip);
|
||||
}
|
||||
|
||||
.markdown-alert.markdown-alert-caution {
|
||||
border-left-color: var(--color-caution);
|
||||
}
|
||||
|
||||
.markdown-alert.markdown-alert-caution .markdown-alert-title {
|
||||
color: var(--color-caution);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body class="vscode-body vscode-light">
|
||||
<h1 id="vícejazyčná-dokumentace">Vícejazyčná dokumentace</h1>
|
||||
<p>Tento adresář obsahuje strojově asistované překlady založené na anglické dokumentaci.</p>
|
||||
<ul>
|
||||
<li><strong>API_REFERENCE.md</strong> : 🇺🇸 <a href="../API_REFERENCE.html">Česky</a> | 🇧🇷 <a href="./pt-BR/API_REFERENCE.html">Português (Brazílie)</a> | 🇪🇸 <a href="./es/API_REFERENCE.html">Español</a> | 🇫🇷 <a href="./fr/API_REFERENCE.html">Français</a> | 🇮🇹 <a href="./it/API_REFERENCE.html">Italiano</a> | 🇷🇺 <a href="./ru/API_REFERENCE.html">Русский</a> | 🇨🇳<a href="./zh-CN/API_REFERENCE.html">中文 (简体)</a> | 🇩🇪 <a href="./de/API_REFERENCE.html">Deutsch</a> | 🇮🇳 <a href="./in/API_REFERENCE.html">हिन्दी</a> | 🇹🇭 <a href="./th/API_REFERENCE.html">ไทย</a> | 🇺🇦 <a href="./uk-UA/API_REFERENCE.html">Українська</a> | 🇸🇦 <a href="./ar/API_REFERENCE.html">العربية</a> | 🇯🇵<a href="./ja/API_REFERENCE.html">日本語</a>| 🇻🇳 <a href="./vi/API_REFERENCE.html">Tiếng Việt</a> | 🇧🇬 <a href="./bg/API_REFERENCE.html">Български</a> | 🇩🇰 <a href="./da/API_REFERENCE.html">Dánsko</a> | 🇫🇮 <a href="./fi/API_REFERENCE.html">Suomi</a> | 🇮🇱 <a href="./he/API_REFERENCE.html">עברית</a> | 🇭🇺 <a href="./hu/API_REFERENCE.html">maďarština</a> | 🇮🇩 <a href="./id/API_REFERENCE.html">Bahasa Indonésie</a> | 🇰🇷 <a href="./ko/API_REFERENCE.html">한국어</a> | 🇲🇾 <a href="./ms/API_REFERENCE.html">Bahasa Melayu</a> | 🇳🇱 <a href="./nl/API_REFERENCE.html">Nizozemsko</a> | 🇳🇴 <a href="./no/API_REFERENCE.html">Norsk</a> | 🇵🇹 <a href="./pt/API_REFERENCE.html">Português (Portugalsko)</a> | 🇷🇴 <a href="./ro/API_REFERENCE.html">Română</a> | 🇵🇱 <a href="./pl/API_REFERENCE.html">Polski</a> | 🇸🇰 <a href="./sk/API_REFERENCE.html">Slovenčina</a> | 🇸🇪 <a href="./sv/API_REFERENCE.html">Svenska</a> | 🇵🇭 <a href="./phi/API_REFERENCE.html">Filipínec</a></li>
|
||||
<li><strong><a href="http://ARCHITECTURE.html">ARCHITECTURE.md</a></strong> : 🇺🇸 <a href="../ARCHITECTURE.html">anglicky</a> | 🇧🇷 <a href="./pt-BR/ARCHITECTURE.html">Português (Brazílie)</a> | 🇪🇸 <a href="./es/ARCHITECTURE.html">Español</a> | 🇫🇷 <a href="./fr/ARCHITECTURE.html">Français</a> | 🇮🇹 <a href="./it/ARCHITECTURE.html">Italiano</a> | 🇷🇺 <a href="./ru/ARCHITECTURE.html">Русский</a> | 🇨🇳<a href="./zh-CN/ARCHITECTURE.html">中文 (简体)</a> | 🇩🇪 <a href="./de/ARCHITECTURE.html">Deutsch</a> | 🇮🇳 <a href="./in/ARCHITECTURE.html">हिन्दी</a> | 🇹🇭 <a href="./th/ARCHITECTURE.html">ไทย</a> | 🇺🇦 <a href="./uk-UA/ARCHITECTURE.html">Українська</a> | 🇸🇦 <a href="./ar/ARCHITECTURE.html">العربية</a> | 🇯🇵<a href="./ja/ARCHITECTURE.html">日本語</a>| 🇻🇳 <a href="./vi/ARCHITECTURE.html">Tiếng Việt</a> | 🇧🇬 <a href="./bg/ARCHITECTURE.html">Български</a> | 🇩🇰 <a href="./da/ARCHITECTURE.html">Dánsko</a> | 🇫🇮 <a href="./fi/ARCHITECTURE.html">Suomi</a> | 🇮🇱 <a href="./he/ARCHITECTURE.html">עברית</a> | 🇭🇺 <a href="./hu/ARCHITECTURE.html">maďarština</a> | 🇮🇩 <a href="./id/ARCHITECTURE.html">Bahasa Indonésie</a> | 🇰🇷 <a href="./ko/ARCHITECTURE.html">한국어</a> | 🇲🇾 <a href="./ms/ARCHITECTURE.html">Bahasa Melayu</a> | 🇳🇱 <a href="./nl/ARCHITECTURE.html">Nizozemsko</a> | 🇳🇴 <a href="./no/ARCHITECTURE.html">Norsk</a> | 🇵🇹 <a href="./pt/ARCHITECTURE.html">Português (Portugalsko)</a> | 🇷🇴 <a href="./ro/ARCHITECTURE.html">Română</a> | 🇵🇱 <a href="./pl/ARCHITECTURE.html">Polski</a> | 🇸🇰 <a href="./sk/ARCHITECTURE.html">Slovenčina</a> | 🇸🇪 <a href="./sv/ARCHITECTURE.html">Svenska</a> | 🇵🇭 <a href="./phi/ARCHITECTURE.html">Filipínec</a></li>
|
||||
<li><strong>CODEBASE_DOCUMENTATION.md</strong> : 🇺🇸 <a href="../CODEBASE_DOCUMENTATION.html">anglicky</a> | 🇧🇷 <a href="./pt-BR/CODEBASE_DOCUMENTATION.html">Português (Brazílie)</a> | 🇪🇸 <a href="./es/CODEBASE_DOCUMENTATION.html">Español</a> | 🇫🇷 <a href="./fr/CODEBASE_DOCUMENTATION.html">Français</a> | 🇮🇹 <a href="./it/CODEBASE_DOCUMENTATION.html">Italiano</a> | 🇷🇺 <a href="./ru/CODEBASE_DOCUMENTATION.html">Русский</a> | 🇨🇳<a href="./zh-CN/CODEBASE_DOCUMENTATION.html">中文 (简体)</a> | 🇩🇪 <a href="./de/CODEBASE_DOCUMENTATION.html">Deutsch</a> | 🇮🇳 <a href="./in/CODEBASE_DOCUMENTATION.html">हिन्दी</a> | 🇹🇭 <a href="./th/CODEBASE_DOCUMENTATION.html">ไทย</a> | 🇺🇦 <a href="./uk-UA/CODEBASE_DOCUMENTATION.html">Українська</a> | 🇸🇦 <a href="./ar/CODEBASE_DOCUMENTATION.html">العربية</a> | 🇯🇵<a href="./ja/CODEBASE_DOCUMENTATION.html">日本語</a>| 🇻🇳 <a href="./vi/CODEBASE_DOCUMENTATION.html">Tiếng Việt</a> | 🇧🇬 <a href="./bg/CODEBASE_DOCUMENTATION.html">Български</a> | 🇩🇰 <a href="./da/CODEBASE_DOCUMENTATION.html">Dánsko</a> | 🇫🇮 <a href="./fi/CODEBASE_DOCUMENTATION.html">Suomi</a> | 🇮🇱 <a href="./he/CODEBASE_DOCUMENTATION.html">עברית</a> | 🇭🇺 <a href="./hu/CODEBASE_DOCUMENTATION.html">maďarština</a> | 🇮🇩 <a href="./id/CODEBASE_DOCUMENTATION.html">Bahasa Indonésie</a> | 🇰🇷 <a href="./ko/CODEBASE_DOCUMENTATION.html">한국어</a> | 🇲🇾 <a href="./ms/CODEBASE_DOCUMENTATION.html">Bahasa Melayu</a> | 🇳🇱 <a href="./nl/CODEBASE_DOCUMENTATION.html">Nizozemsko</a> | 🇳🇴 <a href="./no/CODEBASE_DOCUMENTATION.html">Norsk</a> | 🇵🇹 <a href="./pt/CODEBASE_DOCUMENTATION.html">Português (Portugalsko)</a> | 🇷🇴 <a href="./ro/CODEBASE_DOCUMENTATION.html">Română</a> | 🇵🇱 <a href="./pl/CODEBASE_DOCUMENTATION.html">Polski</a> | 🇸🇰 <a href="./sk/CODEBASE_DOCUMENTATION.html">Slovenčina</a> | 🇸🇪 <a href="./sv/CODEBASE_DOCUMENTATION.html">Svenska</a> | 🇵🇭 <a href="./phi/CODEBASE_DOCUMENTATION.html">Filipínec</a></li>
|
||||
<li><strong><a href="http://FEATURES.html">FEATURES.md</a></strong> : 🇺🇸 <a href="../FEATURES.html">anglicky</a> | 🇧🇷 <a href="./pt-BR/FEATURES.html">Português (Brazílie)</a> | 🇪🇸 <a href="./es/FEATURES.html">Español</a> | 🇫🇷 <a href="./fr/FEATURES.html">Français</a> | 🇮🇹 <a href="./it/FEATURES.html">Italiano</a> | 🇷🇺 <a href="./ru/FEATURES.html">Русский</a> | 🇨🇳<a href="./zh-CN/FEATURES.html">中文 (简体)</a> | 🇩🇪 <a href="./de/FEATURES.html">Deutsch</a> | 🇮🇳 <a href="./in/FEATURES.html">हिन्दी</a> | 🇹🇭 <a href="./th/FEATURES.html">ไทย</a> | 🇺🇦 <a href="./uk-UA/FEATURES.html">Українська</a> | 🇸🇦 <a href="./ar/FEATURES.html">العربية</a> | 🇯🇵<a href="./ja/FEATURES.html">日本語</a>| 🇻🇳 <a href="./vi/FEATURES.html">Tiếng Việt</a> | 🇧🇬 <a href="./bg/FEATURES.html">Български</a> | 🇩🇰 <a href="./da/FEATURES.html">Dánsko</a> | 🇫🇮 <a href="./fi/FEATURES.html">Suomi</a> | 🇮🇱 <a href="./he/FEATURES.html">עברית</a> | 🇭🇺 <a href="./hu/FEATURES.html">maďarština</a> | 🇮🇩 <a href="./id/FEATURES.html">Bahasa Indonésie</a> | 🇰🇷 <a href="./ko/FEATURES.html">한국어</a> | 🇲🇾 <a href="./ms/FEATURES.html">Bahasa Melayu</a> | 🇳🇱 <a href="./nl/FEATURES.html">Nizozemsko</a> | 🇳🇴 <a href="./no/FEATURES.html">Norsk</a> | 🇵🇹 <a href="./pt/FEATURES.html">Português (Portugalsko)</a> | 🇷🇴 <a href="./ro/FEATURES.html">Română</a> | 🇵🇱 <a href="./pl/FEATURES.html">Polski</a> | 🇸🇰 <a href="./sk/FEATURES.html">Slovenčina</a> | 🇸🇪 <a href="./sv/FEATURES.html">Svenska</a> | 🇵🇭 <a href="./phi/FEATURES.html">Filipínec</a></li>
|
||||
<li><strong><a href="http://TOUBLESHOOTING.html">TOUBLESHOOTING.md</a></strong> : 🇺🇸 <a href="../TROUBLESHOOTING.html">anglicky</a> | 🇧🇷 <a href="./pt-BR/TROUBLESHOOTING.html">Português (Brazílie)</a> | 🇪🇸 <a href="./es/TROUBLESHOOTING.html">Español</a> | 🇫🇷 <a href="./fr/TROUBLESHOOTING.html">Français</a> | 🇮🇹 <a href="./it/TROUBLESHOOTING.html">Italiano</a> | 🇷🇺 <a href="./ru/TROUBLESHOOTING.html">Русский</a> | 🇨🇳<a href="./zh-CN/TROUBLESHOOTING.html">中文 (简体)</a> | 🇩🇪 <a href="./de/TROUBLESHOOTING.html">Deutsch</a> | 🇮🇳 <a href="./in/TROUBLESHOOTING.html">हिन्दी</a> | 🇹🇭 <a href="./th/TROUBLESHOOTING.html">ไทย</a> | 🇺🇦 <a href="./uk-UA/TROUBLESHOOTING.html">Українська</a> | 🇸🇦 <a href="./ar/TROUBLESHOOTING.html">العربية</a> | 🇯🇵<a href="./ja/TROUBLESHOOTING.html">日本語</a>| 🇻🇳 <a href="./vi/TROUBLESHOOTING.html">Tiếng Việt</a> | 🇧🇬 <a href="./bg/TROUBLESHOOTING.html">Български</a> | 🇩🇰 <a href="./da/TROUBLESHOOTING.html">Dánsko</a> | 🇫🇮 <a href="./fi/TROUBLESHOOTING.html">Suomi</a> | 🇮🇱 <a href="./he/TROUBLESHOOTING.html">עברית</a> | 🇭🇺 <a href="./hu/TROUBLESHOOTING.html">maďarština</a> | 🇮🇩 <a href="./id/TROUBLESHOOTING.html">Bahasa Indonésie</a> | 🇰🇷 <a href="./ko/TROUBLESHOOTING.html">한국어</a> | 🇲🇾 <a href="./ms/TROUBLESHOOTING.html">Bahasa Melayu</a> | 🇳🇱 <a href="./nl/TROUBLESHOOTING.html">Nizozemsko</a> | 🇳🇴 <a href="./no/TROUBLESHOOTING.html">Norsk</a> | 🇵🇹 <a href="./pt/TROUBLESHOOTING.html">Português (Portugalsko)</a> | 🇷🇴 <a href="./ro/TROUBLESHOOTING.html">Română</a> | 🇵🇱 <a href="./pl/TROUBLESHOOTING.html">Polski</a> | 🇸🇰 <a href="./sk/TROUBLESHOOTING.html">Slovenčina</a> | 🇸🇪 <a href="./sv/TROUBLESHOOTING.html">Svenska</a> | 🇵🇭 <a href="./phi/TROUBLESHOOTING.html">Filipínec</a></li>
|
||||
<li><strong>USER_GUIDE.md</strong> : 🇺🇸 <a href="../USER_GUIDE.html">anglicky</a> | 🇧🇷 <a href="./pt-BR/USER_GUIDE.html">Português (Brazílie)</a> | 🇪🇸 <a href="./es/USER_GUIDE.html">Español</a> | 🇫🇷 <a href="./fr/USER_GUIDE.html">Français</a> | 🇮🇹 <a href="./it/USER_GUIDE.html">Italiano</a> | 🇷🇺 <a href="./ru/USER_GUIDE.html">Русский</a> | 🇨🇳<a href="./zh-CN/USER_GUIDE.html">中文 (简体)</a> | 🇩🇪 <a href="./de/USER_GUIDE.html">Deutsch</a> | 🇮🇳 <a href="./in/USER_GUIDE.html">हिन्दी</a> | 🇹🇭 <a href="./th/USER_GUIDE.html">ไทย</a> | 🇺🇦 <a href="./uk-UA/USER_GUIDE.html">Українська</a> | 🇸🇦 <a href="./ar/USER_GUIDE.html">العربية</a> | 🇯🇵<a href="./ja/USER_GUIDE.html">日本語</a>| 🇻🇳 <a href="./vi/USER_GUIDE.html">Tiếng Việt</a> | 🇧🇬 <a href="./bg/USER_GUIDE.html">Български</a> | 🇩🇰 <a href="./da/USER_GUIDE.html">Dánsko</a> | 🇫🇮 <a href="./fi/USER_GUIDE.html">Suomi</a> | 🇮🇱 <a href="./he/USER_GUIDE.html">עברית</a> | 🇭🇺 <a href="./hu/USER_GUIDE.html">maďarština</a> | 🇮🇩 <a href="./id/USER_GUIDE.html">Bahasa Indonésie</a> | 🇰🇷 <a href="./ko/USER_GUIDE.html">한국어</a> | 🇲🇾 <a href="./ms/USER_GUIDE.html">Bahasa Melayu</a> | 🇳🇱 <a href="./nl/USER_GUIDE.html">Nizozemsko</a> | 🇳🇴 <a href="./no/USER_GUIDE.html">Norsk</a> | 🇵🇹 <a href="./pt/USER_GUIDE.html">Português (Portugalsko)</a> | 🇷🇴 <a href="./ro/USER_GUIDE.html">Română</a> | 🇵🇱 <a href="./pl/USER_GUIDE.html">Polski</a> | 🇸🇰 <a href="./sk/USER_GUIDE.html">Slovenčina</a> | 🇸🇪 <a href="./sv/USER_GUIDE.html">Svenska</a> | 🇵🇭 <a href="./phi/USER_GUIDE.html">Filipínec</a></li>
|
||||
</ul>
|
||||
<h2 id="nedávná-poznámka-zásady-limitů-pro-účty-codex">Nedávná poznámka: Zásady limitů pro účty Codex</h2>
|
||||
<p>Dokumentace nyní zahrnuje chování zásad kvót na úrovni účtu Codex:</p>
|
||||
<ul>
|
||||
<li>Přepínání pro jednotlivé účty: <code>5h</code> a <code>Weekly</code> (ZAP/VYP).</li>
|
||||
<li>Zásady prahových hodnot: povolené okno dosahující >=90 % označuje účet jako nezpůsobilý k výběru.</li>
|
||||
<li>Automatická rotace: provoz se přesune na další způsobilý účet Codex.</li>
|
||||
<li>Automatické opětovné použití: účet se opět stane způsobilým po úspěšném <code>resetAt</code> poskytovatele.</li>
|
||||
</ul>
|
||||
<p>Vygenerováno 26. února 2026.</p>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -90,7 +90,7 @@ flowchart LR
|
||||
end
|
||||
|
||||
subgraph Upstreams[Upstream Providers]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/iFlow/GitHub/Kiro/Cursor/Antigravity]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
|
||||
P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
|
||||
P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
|
||||
end
|
||||
@@ -224,7 +224,7 @@ Domain layer modules:
|
||||
OAuth provider modules (12 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`, `iflow.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.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`
|
||||
- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
|
||||
|
||||
## 3) Persistence Layer
|
||||
@@ -597,7 +597,7 @@ Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/
|
||||
|
||||
| Executor | Provider(s) | Special Handling |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
|
||||
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, iFlow, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
|
||||
| `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 |
|
||||
@@ -621,7 +621,7 @@ 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 |
|
||||
| iFlow | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
|
||||
| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
|
||||
| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
@@ -271,7 +271,7 @@ Business logic that supports the handlers and executors.
|
||||
| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
|
||||
| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
|
||||
| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
|
||||
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, iFlow, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
|
||||
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
|
||||
| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
|
||||
| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
|
||||
| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
|
||||
@@ -543,7 +543,7 @@ A 2000-token buffer is added to reported usage to prevent clients from hitting c
|
||||
| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
|
||||
| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
|
||||
| Qwen | OAuth | Default | Standard auth |
|
||||
| iFlow | OAuth (Basic + Bearer) | Default | Dual auth header |
|
||||
| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
|
||||
| OpenRouter | API key | Default | Standard Bearer auth |
|
||||
| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
|
||||
| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
|
||||
|
||||
@@ -12,7 +12,7 @@ Visual guide to every section of the OmniRoute dashboard.
|
||||
|
||||
## 🔌 Providers
|
||||
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
|
||||

|
||||
|
||||
@@ -67,7 +67,7 @@ Customizable color themes for the entire dashboard. Choose from 7 preset colors
|
||||
Comprehensive settings panel with tabs:
|
||||
|
||||
- **General** — System storage, backup management (export/import database)
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
|
||||
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
|
||||
- **Routing** — Model aliases, background task degradation
|
||||
- **Resilience** — Rate limit persistence, circuit breaker tuning
|
||||
|
||||
+1125
-694
File diff suppressed because it is too large
Load Diff
@@ -101,7 +101,7 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,
|
||||
|
||||
1. Check usage stats in Dashboard → Usage
|
||||
2. Switch primary model to GLM/MiniMax
|
||||
3. Use free tier (Gemini CLI, iFlow) for non-critical tasks
|
||||
3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
|
||||
4. Set cost budgets per API key: Dashboard → API Keys → Budget
|
||||
|
||||
---
|
||||
|
||||
+127
-11
@@ -1,11 +1,11 @@
|
||||
🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
|
||||
# User Guide (Dansk)
|
||||
|
||||
🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
|
||||
|
||||
> 🇺🇸 [English](../../USER_GUIDE.md)
|
||||
|
||||
---
|
||||
|
||||
# User Guide
|
||||
|
||||
🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md)
|
||||
|
||||
Complete guide for configuring providers, creating combos, integrating CLI tools, and deploying OmniRoute.
|
||||
|
||||
---
|
||||
@@ -43,11 +43,11 @@ Complete guide for configuring providers, creating combos, integrating CLI tools
|
||||
| **💰 CHEAP** | GLM-4.7 | $0.6/1M | Daily 10AM | Budget backup |
|
||||
| | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option |
|
||||
| | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost |
|
||||
| **🆓 FREE** | iFlow | $0 | Unlimited | 8 models free |
|
||||
| **🆓 FREE** | Qoder | $0 | Unlimited | 8 models free |
|
||||
| | Qwen | $0 | Unlimited | 3 models free |
|
||||
| | Kiro | $0 | Unlimited | Claude free |
|
||||
|
||||
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + iFlow (unlimited free) combo = $0 cost!
|
||||
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + Qoder (unlimited free) combo = $0 cost!
|
||||
|
||||
---
|
||||
|
||||
@@ -197,10 +197,10 @@ Models:
|
||||
|
||||
### 🆓 FREE Providers
|
||||
|
||||
#### iFlow (8 FREE models)
|
||||
#### Qoder (8 FREE models)
|
||||
|
||||
```bash
|
||||
Dashboard → Connect iFlow → OAuth login → Unlimited usage
|
||||
Dashboard → Connect Qoder → OAuth login → Unlimited usage
|
||||
|
||||
Models: if/kimi-k2-thinking, if/qwen3-coder-plus, if/glm-4.7, if/minimax-m2, if/deepseek-r1
|
||||
```
|
||||
@@ -409,6 +409,106 @@ docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-dat
|
||||
|
||||
For host-integrated mode with CLI binaries, see the Docker section in the main docs.
|
||||
|
||||
### Void Linux (xbps-src)
|
||||
|
||||
Void Linux users can package and install OmniRoute natively using the `xbps-src` cross-compilation framework. This automates the Node.js standalone build along with the required `better-sqlite3` native bindings.
|
||||
|
||||
<details>
|
||||
<summary><b>View xbps-src template</b></summary>
|
||||
|
||||
```bash
|
||||
# Template file for 'omniroute'
|
||||
pkgname=omniroute
|
||||
version=3.2.4
|
||||
revision=1
|
||||
hostmakedepends="nodejs python3 make"
|
||||
depends="openssl"
|
||||
short_desc="Universal AI gateway with smart routing for multiple LLM providers"
|
||||
maintainer="zenobit <zenobit@disroot.org>"
|
||||
license="MIT"
|
||||
homepage="https://github.com/diegosouzapw/OmniRoute"
|
||||
distfiles="https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz"
|
||||
checksum=009400afee90a9f32599d8fe734145cfd84098140b7287990183dde45ae2245b
|
||||
system_accounts="_omniroute"
|
||||
omniroute_homedir="/var/lib/omniroute"
|
||||
export NODE_ENV=production
|
||||
export npm_config_engine_strict=false
|
||||
export npm_config_loglevel=error
|
||||
export npm_config_fund=false
|
||||
export npm_config_audit=false
|
||||
|
||||
do_build() {
|
||||
# Determine target CPU arch for node-gyp
|
||||
local _gyp_arch
|
||||
case "$XBPS_TARGET_MACHINE" in
|
||||
aarch64*) _gyp_arch=arm64 ;;
|
||||
armv7*|armv6*) _gyp_arch=arm ;;
|
||||
i686*) _gyp_arch=ia32 ;;
|
||||
*) _gyp_arch=x64 ;;
|
||||
esac
|
||||
|
||||
# 1) Install all deps – skip scripts
|
||||
NODE_ENV=development npm ci --ignore-scripts
|
||||
|
||||
# 2) Build the Next.js standalone bundle
|
||||
npm run build
|
||||
|
||||
# 3) Copy static assets into standalone
|
||||
cp -r .next/static .next/standalone/.next/static
|
||||
[ -d public ] && cp -r public .next/standalone/public || true
|
||||
|
||||
# 4) Compile better-sqlite3 native binding
|
||||
local _node_gyp=/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js
|
||||
(cd node_modules/better-sqlite3 && node "$_node_gyp" rebuild --arch="$_gyp_arch")
|
||||
|
||||
# 5) Place the compiled binding into the standalone bundle
|
||||
local _bs3_release=.next/standalone/node_modules/better-sqlite3/build/Release
|
||||
mkdir -p "$_bs3_release"
|
||||
cp node_modules/better-sqlite3/build/Release/better_sqlite3.node "$_bs3_release/"
|
||||
|
||||
# 6) Remove arch-specific sharp bundles
|
||||
rm -rf .next/standalone/node_modules/@img
|
||||
|
||||
# 7) Copy pino runtime deps omitted by Next.js static analysis:
|
||||
for _mod in pino-abstract-transport split2 process-warning; do
|
||||
cp -r "node_modules/$_mod" .next/standalone/node_modules/
|
||||
done
|
||||
}
|
||||
|
||||
do_check() {
|
||||
npm run test:unit
|
||||
}
|
||||
|
||||
do_install() {
|
||||
vmkdir usr/lib/omniroute/.next
|
||||
vcopy .next/standalone/. usr/lib/omniroute/.next/standalone
|
||||
|
||||
# Prevent removal of empty Next.js app router dirs by the post-install hook
|
||||
for _d in \
|
||||
.next/standalone/.next/server/app/dashboard \
|
||||
.next/standalone/.next/server/app/dashboard/settings \
|
||||
.next/standalone/.next/server/app/dashboard/providers; do
|
||||
touch "${DESTDIR}/usr/lib/omniroute/${_d}/.keep"
|
||||
done
|
||||
|
||||
cat > "${WRKDIR}/omniroute" <<'EOF'
|
||||
#!/bin/sh
|
||||
export PORT="${PORT:-20128}"
|
||||
export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}"
|
||||
export LOG_TO_FILE="${LOG_TO_FILE:-false}"
|
||||
mkdir -p "${DATA_DIR}"
|
||||
exec node /usr/lib/omniroute/.next/standalone/server.js "$@"
|
||||
EOF
|
||||
vbin "${WRKDIR}/omniroute"
|
||||
}
|
||||
|
||||
post_install() {
|
||||
vlicense LICENSE
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
@@ -450,7 +550,7 @@ For the full environment variable reference, see the [README](../README.md).
|
||||
|
||||
**MiniMax (`minimax/`)** — $0.2/1M: `minimax/MiniMax-M2.1`
|
||||
|
||||
**iFlow (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
|
||||
**Qoder (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
|
||||
|
||||
**Qwen (`qw/`)** — FREE: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`
|
||||
|
||||
@@ -582,6 +682,22 @@ Configure via **Dashboard → Settings → Routing**.
|
||||
| **Least Used** | Routes to the account with the oldest `lastUsedAt` timestamp, distributing traffic evenly |
|
||||
| **Cost Optimized** | Routes to the account with the lowest priority value, optimizing for lowest-cost providers |
|
||||
|
||||
#### External Sticky Session Header
|
||||
|
||||
For external session affinity (for example, Claude Code/Codex agents behind reverse proxies), send:
|
||||
|
||||
```http
|
||||
X-Session-Id: your-session-key
|
||||
```
|
||||
|
||||
OmniRoute also accepts `x_session_id` and returns the effective session key in `X-OmniRoute-Session-Id`.
|
||||
|
||||
If you use Nginx and send underscore-form headers, enable:
|
||||
|
||||
```nginx
|
||||
underscores_in_headers on;
|
||||
```
|
||||
|
||||
#### Wildcard Model Aliases
|
||||
|
||||
Create wildcard patterns to remap model names:
|
||||
@@ -766,7 +882,7 @@ Access via **Dashboard → Health**. Real-time system health overview with 6 car
|
||||
|
||||
OmniRoute is available as a native desktop application for Windows, macOS, and Linux.
|
||||
|
||||
### Installation
|
||||
### Installer
|
||||
|
||||
```bash
|
||||
# From the electron directory:
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
# OmniRoute — Dashboard Features Gallery (Dansk)
|
||||
|
||||
🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
|
||||
|
||||
---
|
||||
|
||||
Visual guide to every section of the OmniRoute dashboard.
|
||||
|
||||
---
|
||||
|
||||
## 🔌 Providers
|
||||
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🎨 Combos
|
||||
|
||||
Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 📊 Analytics
|
||||
|
||||
Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🏥 System Health
|
||||
|
||||
Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🔧 Translator Playground
|
||||
|
||||
Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🎮 Model Playground _(v2.0.9+)_
|
||||
|
||||
Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Themes _(v2.0.5+)_
|
||||
|
||||
Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Settings
|
||||
|
||||
Comprehensive settings panel with tabs:
|
||||
|
||||
- **General** — System storage, backup management (export/import database)
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
|
||||
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
|
||||
- **Routing** — Model aliases, background task degradation
|
||||
- **Resilience** — Rate limit persistence, circuit breaker tuning, auto-disable banned accounts, provider expiration monitoring
|
||||
- **Advanced** — Configuration overrides, configuration audit trail, fallback degradation mode
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🔧 CLI Tools
|
||||
|
||||
One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🤖 CLI Agents _(v2.0.11+)_
|
||||
|
||||
Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
|
||||
|
||||
- **Installation status** — Installed / Not Found with version detection
|
||||
- **Protocol badges** — stdio, HTTP, etc.
|
||||
- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
|
||||
- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
|
||||
|
||||
---
|
||||
|
||||
## 🖼️ 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.
|
||||
|
||||
---
|
||||
|
||||
## 📝 Request Logs
|
||||
|
||||
Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🌐 API Endpoint
|
||||
|
||||
Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloudflare Quick Tunnel integration and cloud proxy support for remote access.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🔑 API Key Management
|
||||
|
||||
Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Audit Log
|
||||
|
||||
Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ Desktop Application
|
||||
|
||||
Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
|
||||
|
||||
Key features:
|
||||
|
||||
- Server readiness polling (no blank screen on cold start)
|
||||
- System tray with port management
|
||||
- Content Security Policy
|
||||
- Single-instance lock
|
||||
- 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+)
|
||||
|
||||
📖 See [`electron/README.md`](../electron/README.md) for full documentation.
|
||||
@@ -90,7 +90,7 @@ flowchart LR
|
||||
end
|
||||
|
||||
subgraph Upstreams[Upstream Providers]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/iFlow/GitHub/Kiro/Cursor/Antigravity]
|
||||
P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
|
||||
P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
|
||||
P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
|
||||
end
|
||||
@@ -224,7 +224,7 @@ Domain layer modules:
|
||||
OAuth provider modules (12 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`, `iflow.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.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`
|
||||
- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
|
||||
|
||||
## 3) Persistence Layer
|
||||
@@ -597,7 +597,7 @@ Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/
|
||||
|
||||
| Executor | Provider(s) | Special Handling |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
|
||||
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, iFlow, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
|
||||
| `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 |
|
||||
@@ -621,7 +621,7 @@ 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 |
|
||||
| iFlow | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
|
||||
| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
|
||||
| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
@@ -271,7 +271,7 @@ Business logic that supports the handlers and executors.
|
||||
| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
|
||||
| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
|
||||
| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
|
||||
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, iFlow, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
|
||||
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
|
||||
| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
|
||||
| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
|
||||
| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
|
||||
@@ -543,7 +543,7 @@ A 2000-token buffer is added to reported usage to prevent clients from hitting c
|
||||
| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
|
||||
| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
|
||||
| Qwen | OAuth | Default | Standard auth |
|
||||
| iFlow | OAuth (Basic + Bearer) | Default | Dual auth header |
|
||||
| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
|
||||
| OpenRouter | API key | Default | Standard Bearer auth |
|
||||
| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
|
||||
| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
|
||||
|
||||
@@ -12,7 +12,7 @@ Visual guide to every section of the OmniRoute dashboard.
|
||||
|
||||
## 🔌 Providers
|
||||
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
|
||||
|
||||

|
||||
|
||||
@@ -67,7 +67,7 @@ Customizable color themes for the entire dashboard. Choose from 7 preset colors
|
||||
Comprehensive settings panel with tabs:
|
||||
|
||||
- **General** — System storage, backup management (export/import database)
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility
|
||||
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
|
||||
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
|
||||
- **Routing** — Model aliases, background task degradation
|
||||
- **Resilience** — Rate limit persistence, circuit breaker tuning
|
||||
|
||||
+1131
-704
File diff suppressed because it is too large
Load Diff
@@ -101,7 +101,7 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,
|
||||
|
||||
1. Check usage stats in Dashboard → Usage
|
||||
2. Switch primary model to GLM/MiniMax
|
||||
3. Use free tier (Gemini CLI, iFlow) for non-critical tasks
|
||||
3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
|
||||
4. Set cost budgets per API key: Dashboard → API Keys → Budget
|
||||
|
||||
---
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user