Compare commits
434 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fb9f72fc90 | |||
| 30558764ba | |||
| b38351a470 | |||
| 597a0f21e0 | |||
| 9b4a5523cc | |||
| 70a4d38d04 | |||
| dbe17b4b16 | |||
| ee4df2806f | |||
| afc0bc9323 | |||
| e071393eb5 | |||
| 6f9fec658f | |||
| 9227964cb6 | |||
| cf6056cede | |||
| 4397612349 | |||
| cf3719a663 | |||
| 77bf35d728 | |||
| e7addec0a1 | |||
| 243d61d95f | |||
| 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 |
@@ -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
|
||||
@@ -11,6 +11,8 @@ Bump version, finalize CHANGELOG, commit, open a **PR to main** and wait for use
|
||||
> Always use: `npm version patch --no-git-tag-version`
|
||||
> The threshold rule: when `y` reaches 10, bump to `2.(x+1).0` — e.g. `2.1.10` → `2.2.0`.
|
||||
|
||||
> **🔴 SINGLE BRANCH RULE**: The `release/vX.Y.Z` branch is the **ONLY** development branch for the entire release cycle. ALL work — bug fixes, feature implementations, PR integrations, issue resolutions — MUST be committed directly on this branch. Never create separate `fix/`, `feat/`, or topic branches. When running `/resolve-issues`, `/implement-features`, or `/review-prs`, always work on the current release branch.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Two-Phase Flow
|
||||
@@ -96,7 +98,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
|
||||
@@ -165,24 +178,17 @@ Inform the user:
|
||||
|
||||
> Run these steps only AFTER the user has merged the PR.
|
||||
|
||||
### 11. Pull main and create tag
|
||||
### 11. Create Git Tag and GitHub Release (MANDATORY)
|
||||
|
||||
// turbo
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
git pull origin main
|
||||
git tag -a v2.x.y -m "Release v2.x.y"
|
||||
```
|
||||
|
||||
### 12. Push tag to GitHub
|
||||
|
||||
```bash
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
git tag -a "v$VERSION" -m "Release v$VERSION"
|
||||
git push origin --tags
|
||||
```
|
||||
|
||||
### 13. Create GitHub release
|
||||
|
||||
```bash
|
||||
gh release create v2.x.y --title "v2.x.y — summary" --notes "..."
|
||||
gh release create "v$VERSION" --title "v$VERSION" --notes "OmniRoute v$VERSION Release" --target main
|
||||
```
|
||||
|
||||
### 14. 🐳 Trigger Docker Hub build (MANDATORY — keep npm and Docker in sync)
|
||||
|
||||
@@ -6,7 +6,9 @@ description: Analyze open feature request issues, implement viable ones on dedic
|
||||
|
||||
## Overview
|
||||
|
||||
Fetches open feature request issues, analyzes each against the current codebase, implements viable ones on dedicated branches, and responds to authors with results. Does NOT merge to main — leaves branches for author validation.
|
||||
Fetches open feature request issues, analyzes each against the current codebase, implements viable ones **on the current release branch** (`release/vX.Y.Z`), and responds to authors with results. Does NOT merge to main — the release branch is later merged via PR.
|
||||
|
||||
> **BRANCH RULE**: All work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `feat/` branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5.
|
||||
|
||||
## Steps
|
||||
|
||||
@@ -16,15 +18,48 @@ Fetches open feature request issues, analyzes each against the current codebase,
|
||||
|
||||
- Run: `git -C <project_root> remote get-url origin` to extract owner/repo
|
||||
|
||||
### 2. Fetch Open Feature Request Issues
|
||||
### 2. Ensure Release Branch Exists
|
||||
|
||||
// turbo
|
||||
|
||||
- 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
|
||||
Before doing any work, ensure you are on the current release branch:
|
||||
|
||||
### 3. Analyze Each Feature Request
|
||||
```bash
|
||||
# Check current branch
|
||||
git branch --show-current
|
||||
|
||||
# If on main, determine next version and create the release branch
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)")
|
||||
git checkout -b release/v$NEXT
|
||||
npm version patch --no-git-tag-version
|
||||
npm install
|
||||
```
|
||||
|
||||
If already on a `release/vX.Y.Z` branch, continue working there.
|
||||
|
||||
### 3. Fetch Open Feature Request Issues
|
||||
|
||||
// turbo-all
|
||||
|
||||
**⚠️ 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 3a — 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 3b — Fetch full metadata & conversations for each Issue** (one call per issue):
|
||||
|
||||
- For each issue number from step 3a, 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.
|
||||
|
||||
### 4. Analyze Each Feature Request
|
||||
|
||||
For each feature request issue, perform a **two-level analysis**:
|
||||
|
||||
@@ -46,21 +81,16 @@ Ask yourself:
|
||||
|
||||
#### Level 2 — Implementation (only for VIABLE features)
|
||||
|
||||
> **⚠️ ALL implementation happens on the release branch.**
|
||||
|
||||
1. **Research** — Read all related source files to understand the current architecture
|
||||
2. **Design** — Plan the implementation, filling gaps in the original request
|
||||
3. **Create branch** — Name format: `feat/issue-<NUMBER>-<short-slug>`
|
||||
```bash
|
||||
git checkout main
|
||||
git pull origin main
|
||||
git checkout -b feat/issue-<NUMBER>-<short-slug>
|
||||
```
|
||||
4. **Implement** — Build the complete solution following project patterns
|
||||
5. **Build** — Run `npm run build` to verify compilation
|
||||
6. **Commit** — Commit with: `feat: <description> (#<NUMBER>)`
|
||||
7. **Push** — Push the branch: `git push -u origin feat/issue-<NUMBER>-<short-slug>`
|
||||
8. **Return to main** — `git checkout main`
|
||||
3. **Implement** — Build the complete solution following project patterns, **on the release branch**
|
||||
4. **Build** — Run `npm run build` to verify compilation
|
||||
5. **Commit** — Commit with: `feat: <description> (#<NUMBER>)`
|
||||
6. **Continue** — Move to the next feature (do not switch branches)
|
||||
|
||||
### 4. Respond to Authors
|
||||
### 5. Respond to Authors
|
||||
|
||||
#### For VIABLE (implemented) features:
|
||||
|
||||
@@ -70,9 +100,9 @@ Post a comment on the issue:
|
||||
````markdown
|
||||
## ✅ Feature Implemented!
|
||||
|
||||
Hi @<author>! We've analyzed your request and implemented it on a dedicated branch.
|
||||
Hi @<author>! We've analyzed your request and implemented it.
|
||||
|
||||
**Branch:** `feat/issue-<NUMBER>-<short-slug>`
|
||||
**Branch:** `release/vX.Y.Z` (upcoming release)
|
||||
|
||||
### What was implemented:
|
||||
|
||||
@@ -82,31 +112,24 @@ Hi @<author>! We've analyzed your request and implemented it on a dedicated bran
|
||||
|
||||
```bash
|
||||
git fetch origin
|
||||
git checkout feat/issue-<NUMBER>-<short-slug>
|
||||
git checkout release/vX.Y.Z
|
||||
npm install && npm run dev
|
||||
```
|
||||
````
|
||||
|
||||
### Next steps:
|
||||
|
||||
1. **Test it** — Please verify it works as you expected
|
||||
2. **Want to improve it?** — You're welcome to contribute! Just:
|
||||
```bash
|
||||
git checkout feat/issue-<NUMBER>-<short-slug>
|
||||
# Make your improvements
|
||||
git add -A && git commit -m "improve: <your changes>"
|
||||
git push origin feat/issue-<NUMBER>-<short-slug>
|
||||
```
|
||||
Then open a Pull Request from your branch to `main` 🎉
|
||||
2. **Want to improve it?** — Feel free to open a follow-up PR targeting `release/vX.Y.Z`
|
||||
3. **Not quite right?** — Let us know in this issue what needs to change
|
||||
|
||||
Looking forward to your feedback! 🚀
|
||||
|
||||
```
|
||||
This will be included in the next release. Looking forward to your feedback! 🚀
|
||||
````
|
||||
|
||||
#### For NEEDS MORE INFO:
|
||||
|
||||
// turbo
|
||||
Post a comment asking for specific missing details needed to implement, e.g.:
|
||||
|
||||
- "Could you describe the exact behavior when X happens?"
|
||||
- "Which API endpoints should be affected?"
|
||||
- "Should this apply to all providers or only specific ones?"
|
||||
@@ -114,18 +137,28 @@ Post a comment asking for specific missing details needed to implement, e.g.:
|
||||
Add the context of WHY you need each piece of information.
|
||||
|
||||
#### For NOT VIABLE:
|
||||
|
||||
// turbo
|
||||
Post a polite comment explaining why the feature doesn't fit at this time:
|
||||
|
||||
- If the idea is decent but timing is wrong: "This is an interesting idea, but it doesn't align with our current priorities. Feel free to open a new issue with more details if you'd like us to reconsider."
|
||||
- If fundamentally flawed: Explain the technical or architectural reasons why it won't work, suggest alternatives if possible.
|
||||
- Close the issue after posting the comment.
|
||||
|
||||
### 5. Summary Report
|
||||
### 6. Finalize & Push
|
||||
|
||||
After implementing all viable features:
|
||||
|
||||
1. **Update CHANGELOG.md** on the release branch with all new feature entries
|
||||
2. Push the release branch: `git push origin release/vX.Y.Z`
|
||||
3. Run `/generate-release` workflow Phase 1 steps 7–10 (tests → commit → push → open PR to main → wait for user)
|
||||
|
||||
### 7. Summary Report
|
||||
|
||||
Present a summary report to the user via `notify_user`:
|
||||
|
||||
| Issue | Title | Verdict | Branch / Action |
|
||||
|---|---|---|---|
|
||||
| #N | Title | ✅ Implemented | `feat/issue-N-slug` |
|
||||
| #N | Title | ❓ Needs Info | Comment posted |
|
||||
| #N | Title | ❌ Not Viable | Closed with explanation |
|
||||
```
|
||||
| Issue | Title | Verdict | Action |
|
||||
| ----- | ----- | -------------- | ----------------------- |
|
||||
| #N | Title | ✅ Implemented | Committed on release/vX |
|
||||
| #N | Title | ❓ Needs Info | Comment posted |
|
||||
| #N | Title | ❌ Not Viable | Closed with explanation |
|
||||
|
||||
@@ -6,7 +6,9 @@ description: Fetch all open GitHub issues, analyze bugs, resolve what's possible
|
||||
|
||||
## Overview
|
||||
|
||||
This workflow fetches all open issues from the project's GitHub repository, classifies them, analyzes bugs, resolves what can be fixed, and triages issues with insufficient information. **It does NOT merge or release automatically** — it creates a PR and waits for user validation before merging.
|
||||
This workflow fetches all open issues from the project's GitHub repository, classifies them, analyzes bugs, resolves what can be fixed, and triages issues with insufficient information. **All fixes are committed on the current release branch** (`release/vX.Y.Z`). It does NOT merge or release automatically — the release branch is later merged via PR to main.
|
||||
|
||||
> **BRANCH RULE**: All work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `fix/` branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5.
|
||||
|
||||
## Steps
|
||||
|
||||
@@ -17,15 +19,45 @@ This workflow fetches all open issues from the project's GitHub repository, clas
|
||||
- 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 Issues
|
||||
### 2. Ensure Release Branch Exists
|
||||
|
||||
// turbo
|
||||
|
||||
- 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)
|
||||
Before doing any work, ensure you are on the current release branch:
|
||||
|
||||
### 3. Classify Each Issue
|
||||
```bash
|
||||
# Check current branch
|
||||
git branch --show-current
|
||||
|
||||
# If on main, determine next version and create the release branch
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)")
|
||||
git checkout -b release/v$NEXT
|
||||
npm version patch --no-git-tag-version
|
||||
npm install
|
||||
```
|
||||
|
||||
If already on a `release/vX.Y.Z` branch, continue working there.
|
||||
|
||||
### 3. Fetch All Open Issues
|
||||
|
||||
// turbo-all
|
||||
|
||||
**⚠️ 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 3a — 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 3b — Fetch full metadata for each Issue** (one call per issue):
|
||||
|
||||
- For each issue number from step 3a, 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).
|
||||
|
||||
### 4. Classify Each Issue
|
||||
|
||||
For each issue, determine its type:
|
||||
|
||||
@@ -36,9 +68,9 @@ For each issue, determine its type:
|
||||
|
||||
Focus ONLY on **Bugs** for resolution. Feature requests and questions should be skipped with a note in the final report.
|
||||
|
||||
### 4. Analyze Each Bug — For each bug issue:
|
||||
### 5. Analyze Each Bug — For each bug issue:
|
||||
|
||||
#### 4a. Check Information Sufficiency
|
||||
#### 5a. Check Information Sufficiency
|
||||
|
||||
Verify the issue contains enough information to reproduce and fix:
|
||||
|
||||
@@ -47,7 +79,7 @@ Verify the issue contains enough information to reproduce and fix:
|
||||
- [ ] Error messages or logs
|
||||
- [ ] Expected vs actual behavior
|
||||
|
||||
#### 4b. If Information Is INSUFFICIENT
|
||||
#### 5b. If Information Is INSUFFICIENT
|
||||
|
||||
Call the `/issue-triage` workflow (located at `~/.gemini/antigravity/global_workflows/issue-triage.md`):
|
||||
// turbo
|
||||
@@ -56,18 +88,19 @@ Call the `/issue-triage` workflow (located at `~/.gemini/antigravity/global_work
|
||||
- Add `needs-info` label using `gh issue edit`
|
||||
- Mark this issue as **DEFERRED** and move to the next one
|
||||
|
||||
#### 4c. If Information Is SUFFICIENT
|
||||
#### 5c. If Information Is SUFFICIENT
|
||||
|
||||
Proceed with resolution:
|
||||
Proceed with resolution **on the release branch**:
|
||||
|
||||
1. **Create a fix branch** — `git checkout -b fix/issue-<NUMBER>-<short-description>`
|
||||
2. **Research** — Search the codebase for files related to the issue
|
||||
3. **Root Cause** — Identify the root cause by reading the relevant source files
|
||||
4. **Implement Fix** — Apply the fix following existing code patterns and conventions
|
||||
5. **Test** — Build the project and run tests to verify the fix
|
||||
6. **Commit** — Commit with message format: `fix: <description> (#<issue_number>)`
|
||||
1. **Research** — Search the codebase for files related to the issue
|
||||
2. **Root Cause** — Identify the root cause by reading the relevant source files
|
||||
3. **Implement Fix** — Apply the fix following existing code patterns and conventions
|
||||
4. **Test** — Build the project and run tests to verify the fix
|
||||
5. **Commit** — Commit with message format: `fix: <description> (#<issue_number>)`
|
||||
|
||||
### 5. Generate Report & Wait for Validation
|
||||
> **⚠️ Do NOT create a separate branch.** All commits go directly on the release branch.
|
||||
|
||||
### 6. Generate Report & Wait for Validation
|
||||
|
||||
Present a summary report to the user via `notify_user` with `BlockedOnUser: true`:
|
||||
|
||||
@@ -80,41 +113,37 @@ Present a summary report to the user via `notify_user` with `BlockedOnUser: true
|
||||
> **⚠️ IMPORTANT**: Do NOT commit, close issues, or generate releases at this step.
|
||||
> Wait for the user to review the changes and respond with **OK** before proceeding.
|
||||
|
||||
- If the user says **OK** or approves → Proceed to step 6
|
||||
- If the user says **OK** or approves → Proceed to step 7
|
||||
- If the user requests changes → Apply the requested adjustments first, then present the report again
|
||||
- If the user rejects → Revert the changes and stop
|
||||
|
||||
### 6. Commit & Push Fix Branch (only after user approval)
|
||||
### 7. Commit & Push (only after user approval)
|
||||
|
||||
After the user validates:
|
||||
|
||||
- Commit each fix individually with message format: `fix: <description> (#<issue_number>)`
|
||||
- Push the fix branch: `git push origin fix/issue-<NUMBER>-<short-description>`
|
||||
- Create a PR: `gh pr create --title "fix: <description> (#<issue_number>)" --body "<details>" --base main`
|
||||
- Commit each fix individually on the release branch with message format: `fix: <description> (#<issue_number>)`
|
||||
- Push the release branch: `git push origin release/vX.Y.Z`
|
||||
- **Update CHANGELOG.md** with all new bug fix entries
|
||||
|
||||
### 7. 🛑 WAIT — Notify User & Await PR Verification
|
||||
### 8. 🛑 WAIT — Notify User & Await Verification
|
||||
|
||||
**This is a mandatory stop point.** Use `notify_user` with `BlockedOnUser: true`:
|
||||
|
||||
- Inform the user that the PR was created and is **awaiting their verification**
|
||||
- Include the PR number, URL, and a summary of what was changed
|
||||
- Inform the user that fixes have been **committed and pushed to the release branch**
|
||||
- Include summary of fixes, test status, and files changed
|
||||
- **DO NOT merge, close issues, generate releases, or deploy until the user confirms**
|
||||
|
||||
Wait for the user to respond:
|
||||
|
||||
- **User confirms** → Proceed to step 8
|
||||
- **User confirms** → Proceed to step 9
|
||||
- **User requests changes** → Apply changes, push to the same branch, notify again
|
||||
- **User rejects** → Close the PR and stop
|
||||
- **User rejects** → Revert and stop
|
||||
|
||||
### 8. Merge, Close Issues & Release (only after user confirms PR)
|
||||
### 9. Close Issues & Finalize (only after user confirms)
|
||||
|
||||
After the user confirms the PR:
|
||||
After the user confirms:
|
||||
|
||||
1. **Merge** the PR: `gh pr merge <NUMBER> --merge --repo <owner>/<repo>` or via local merge
|
||||
2. **Close** resolved issues with a comment: `gh issue close <NUMBER> --repo <owner>/<repo> --comment "Fixed in <commit_hash>. The fix will be included in the next release."`
|
||||
3. **Switch to main**: `git checkout main && git pull`
|
||||
4. Run the `/update-docs` workflow (at `~/.gemini/antigravity/global_workflows/update-docs.md`) to update CHANGELOG and README
|
||||
5. Run the `/generate-release` workflow (at `.agents/workflows/generate-release.md`) to bump version, tag, and publish
|
||||
6. Deploy to local VPS: `ssh root@192.168.0.15 "npm install -g omniroute@<VERSION> && pm2 restart omniroute"`
|
||||
1. **Close** resolved issues with a comment: `gh issue close <NUMBER> --repo <owner>/<repo> --comment "Fixed in release/vX.Y.Z. The fix will be included in the next release."`
|
||||
2. Run `/generate-release` workflow Phase 1 steps 7–10 (tests → commit → push → open PR to main → wait for user)
|
||||
|
||||
If NO fixes were committed, skip this step and just present the report.
|
||||
|
||||
@@ -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
|
||||
@@ -6,7 +6,9 @@ description: Analyze open Pull Requests from the project's GitHub repository, ge
|
||||
|
||||
## Overview
|
||||
|
||||
This workflow fetches all open PRs from the project's GitHub repository, performs a critical analysis of each one, generates a detailed report, and waits for user approval before proceeding with implementation. **All improvements are committed on top of the PR branch** and the user must verify before merge.
|
||||
This workflow fetches all open PRs from the project's GitHub repository, performs a critical analysis of each one, generates a detailed report, and waits for user approval before proceeding with implementation. **All improvements are committed on the current release branch** (`release/vX.Y.Z`).
|
||||
|
||||
> **BRANCH RULE**: All work MUST happen on the current `release/vX.Y.Z` branch. Never create separate feature or fix branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5.
|
||||
|
||||
## Steps
|
||||
|
||||
@@ -16,55 +18,94 @@ This workflow fetches all open PRs from the project's GitHub repository, perform
|
||||
// turbo
|
||||
- Run: `git -C <project_root> remote get-url origin` to extract the owner/repo
|
||||
|
||||
### 2. Fetch Open Pull Requests
|
||||
### 2. Ensure Release Branch Exists
|
||||
|
||||
// turbo
|
||||
|
||||
- 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>`
|
||||
Before doing any work, ensure you are on the current release branch:
|
||||
|
||||
```bash
|
||||
# Check current branch
|
||||
git branch --show-current
|
||||
|
||||
# If on main, determine next version and create the release branch
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
# Bump patch: e.g. 3.3.11 → 3.3.12
|
||||
NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)")
|
||||
git checkout -b release/v$NEXT
|
||||
npm version patch --no-git-tag-version
|
||||
npm install
|
||||
```
|
||||
|
||||
If already on a `release/vX.Y.Z` branch, continue working there.
|
||||
|
||||
### 3. Fetch Open Pull Requests
|
||||
|
||||
// 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 3a — 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 3b — Fetch full metadata for each PR** (one call per PR):
|
||||
|
||||
- For each PR number from step 3a, 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 3c — 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`.
|
||||
|
||||
- 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)
|
||||
|
||||
### 3. Analyze Each PR — For each open PR, perform the following analysis:
|
||||
**Verification**: Confirm the count of PRs analyzed matches the count from step 3a before proceeding.
|
||||
|
||||
#### 3a. Feature Assessment
|
||||
### 4. Analyze Each PR — For each open PR, perform the following analysis:
|
||||
|
||||
#### 4a. Feature Assessment
|
||||
|
||||
- **Does it make sense?** Evaluate if the feature fills a real gap or solves a valid problem
|
||||
- **Alignment** — Check if it aligns with the project's architecture and roadmap
|
||||
- **Complexity** — Assess if the scope is reasonable or if it should be split
|
||||
|
||||
#### 3b. Code Quality Review
|
||||
#### 4b. Code Quality Review
|
||||
|
||||
- Check for code duplication
|
||||
- Evaluate error handling patterns (consistent with existing codebase?)
|
||||
- Check naming conventions and code style
|
||||
- Verify TypeScript types (any `any` usage, missing types?)
|
||||
|
||||
#### 3c. Security Review
|
||||
#### 4c. Security Review
|
||||
|
||||
- Check for missing authentication/authorization on new endpoints
|
||||
- Check for injection vulnerabilities (URL params, SQL, XSS)
|
||||
- Verify input validation on all user-controlled data
|
||||
- Check for hardcoded secrets or credentials
|
||||
|
||||
#### 3d. Architecture Review
|
||||
#### 4d. Architecture Review
|
||||
|
||||
- Does the change follow existing patterns?
|
||||
- Are there any breaking changes to public APIs?
|
||||
- Is the database schema affected? Migration needed?
|
||||
- Impact on performance (N+1 queries, missing indexes?)
|
||||
|
||||
#### 3e. Test Coverage
|
||||
#### 4e. Test Coverage
|
||||
|
||||
- Does the PR include tests?
|
||||
- Are edge cases covered?
|
||||
- Would existing tests break?
|
||||
|
||||
#### 3f. Cross-Layer (Global) Analysis
|
||||
#### 4f. Cross-Layer (Global) Analysis
|
||||
|
||||
Perform a **global impact assessment** to verify whether the PR changes are complete across all layers of the application:
|
||||
|
||||
@@ -79,7 +120,7 @@ Perform a **global impact assessment** to verify whether the PR changes are comp
|
||||
- **Cross-cutting concerns**: Check shared layers (types, DTOs, validation schemas, routes, middleware) for completeness
|
||||
- **Document gaps** — If missing layers are detected, list them as **IMPORTANT** issues in the report with concrete suggestions for what should be added
|
||||
|
||||
### 4. Generate Report — Create a markdown report for each PR including:
|
||||
### 5. Generate Report — Create a markdown report for each PR including:
|
||||
|
||||
- **PR Summary** — What it does, files affected, commit count
|
||||
- **Improvements/Benefits** — Numbered list with impact level (HIGH/MEDIUM/LOW)
|
||||
@@ -88,45 +129,35 @@ Perform a **global impact assessment** to verify whether the PR changes are comp
|
||||
- **Verdict** — Ready to merge? With mandatory vs optional fixes
|
||||
- **Next Steps** — What will happen if approved
|
||||
|
||||
### 5. Present to User
|
||||
### 6. Present to User
|
||||
|
||||
- Show the report via `notify_user` with `BlockedOnUser: true`
|
||||
- Wait for user decision:
|
||||
- **Approved** → Proceed to step 6
|
||||
- **Approved** → Proceed to step 7
|
||||
- **Approved with changes** → Implement the fixes and corrections before merging
|
||||
- **Rejected** → Close the PR or leave a review comment
|
||||
|
||||
### 6. Implementation (if approved)
|
||||
### 7. Implementation (if approved)
|
||||
|
||||
- Checkout the PR branch: `gh pr checkout <NUMBER>`
|
||||
- Implement any required fixes identified in the analysis
|
||||
- If the Cross-Layer Analysis (3f) identified missing frontend/backend counterparts, implement them
|
||||
- **Commit improvements on top of the PR branch** with descriptive commit messages
|
||||
> **⚠️ ALL work happens on the release branch, NOT the PR branch.**
|
||||
|
||||
- Cherry-pick or merge the PR's changes into the current release branch:
|
||||
|
||||
```bash
|
||||
# Option A: Merge PR branch into release branch
|
||||
git merge --no-ff <pr-branch> -m "Merge PR #<NUMBER>: <title>"
|
||||
|
||||
# Option B: Cherry-pick if cleaner
|
||||
git cherry-pick <commit-hash>
|
||||
```
|
||||
|
||||
- Implement any required fixes identified in the analysis **on the release branch**
|
||||
- If the Cross-Layer Analysis (4f) identified missing frontend/backend counterparts, implement them
|
||||
- Run the project's test suite to verify nothing breaks
|
||||
// turbo
|
||||
- Run: `npm test` or equivalent test command
|
||||
- Build the project to verify compilation
|
||||
// turbo
|
||||
- Run: `npm run build` or equivalent build command
|
||||
- Push the updated branch: `git push origin <branch-name>`
|
||||
|
||||
### 7. 🛑 WAIT — Notify User & Await PR Verification
|
||||
|
||||
**This is a mandatory stop point.** Use `notify_user` with `BlockedOnUser: true`:
|
||||
|
||||
- Inform the user that the PR has been **improved and pushed**, and is **awaiting their verification**
|
||||
- Include:
|
||||
- PR number and URL
|
||||
- Summary of improvements/fixes applied
|
||||
- Build/test status
|
||||
- List of files changed
|
||||
- **DO NOT merge, generate releases, or deploy until the user confirms**
|
||||
|
||||
Wait for the user to respond:
|
||||
|
||||
- **User confirms** → Proceed to step 8
|
||||
- **User requests more changes** → Apply changes, push to the same branch, notify again
|
||||
- **User rejects** → Leave a review comment and stop
|
||||
- Commit improvements with descriptive messages
|
||||
- Push the release branch: `git push origin release/vX.Y.Z`
|
||||
|
||||
### 8. Thank the Contributor
|
||||
|
||||
@@ -134,16 +165,21 @@ Wait for the user to respond:
|
||||
- The message should:
|
||||
- Thank the author by name/username for their contribution
|
||||
- Briefly mention what the PR accomplishes and any improvements applied
|
||||
- Note it will be included in the upcoming release
|
||||
- Be friendly, professional, and encouraging
|
||||
- Example: _"Thanks @author for this great contribution! 🎉 The [feature/fix] is now merged and will be part of the next release. We appreciate your effort!"_
|
||||
- Example: _"Thanks @author for this great contribution! 🎉 The [feature/fix] has been integrated into the release/vX.Y.Z branch and will be part of the next release. We appreciate your effort!"_
|
||||
|
||||
### 9. Merge & Release (only after user confirms PR)
|
||||
### 9. Close the Original PR
|
||||
|
||||
After the user confirms the PR:
|
||||
- Close the original PR with a comment explaining it was integrated into the release branch:
|
||||
```bash
|
||||
gh pr close <NUMBER> --repo <owner>/<repo> --comment "Integrated into release/vX.Y.Z. Will be released as part of v3.X.Y. Thank you!"
|
||||
```
|
||||
|
||||
1. **Merge** the PR into main (local merge with `--no-ff` or via `gh pr merge`)
|
||||
2. **Push** to main: `git push origin main`
|
||||
3. **Clean up** the feature branch: `git branch -d <branch-name>`
|
||||
4. **Update CHANGELOG.md** with the new feature/fix
|
||||
5. Run the `/generate-release` workflow (at `.agents/workflows/generate-release.md`) to bump version, tag, and publish
|
||||
6. Deploy to local VPS: `ssh root@192.168.0.15 "npm install -g omniroute@<VERSION> && pm2 restart omniroute"`
|
||||
### 10. Continue or Finalize
|
||||
|
||||
After processing all approved PRs:
|
||||
|
||||
- If more PRs remain, go back to step 7
|
||||
- When all PRs are processed, **update CHANGELOG.md** on the release branch with all new entries
|
||||
- Run `/generate-release` workflow Phase 1 steps 7–10 (tests → commit → push → open PR to main → wait for user)
|
||||
|
||||
+5
-3
@@ -21,6 +21,7 @@ STORAGE_ENCRYPTION_KEY_VERSION=v1
|
||||
LOG_RETENTION_DAYS=90
|
||||
SQLITE_MAX_SIZE_MB=2048
|
||||
SQLITE_CLEAN_LEGACY_FILES=true
|
||||
DISABLE_SQLITE_AUTO_BACKUP=false
|
||||
|
||||
# Recommended runtime variables
|
||||
# Canonical/base port (keeps backward compatibility)
|
||||
@@ -40,6 +41,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 +129,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 +143,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,9 @@ vscode-extension/
|
||||
*.sqlite-shm
|
||||
*.sqlite-wal
|
||||
*.sqlite-journal
|
||||
|
||||
# Compiled npm-package build artifact (not source, should not be in git)
|
||||
/app
|
||||
|
||||
# IDEA
|
||||
.idea/
|
||||
@@ -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/`)
|
||||
|
||||
|
||||
+1150
-10
File diff suppressed because it is too large
Load Diff
+19
-1
@@ -41,6 +41,17 @@ Key variables for development:
|
||||
| `INITIAL_PASSWORD` | `123456` | First login password |
|
||||
| `ENABLE_REQUEST_LOGS` | `false` | Enable debug request logs |
|
||||
|
||||
### Dashboard Settings
|
||||
|
||||
The dashboard provides UI toggles for features that can also be configured via environment variables:
|
||||
|
||||
| Setting Location | Toggle | Description |
|
||||
| ------------------- | ------------------ | ------------------------------ |
|
||||
| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
|
||||
| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
|
||||
|
||||
These settings are stored in the database and persist across restarts, overriding env var defaults when set.
|
||||
|
||||
### Running Locally
|
||||
|
||||
```bash
|
||||
@@ -114,6 +125,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 +135,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**
|
||||
|
||||
@@ -26,15 +26,42 @@ _Your universal API proxy — one endpoint, 44+ providers, zero downtime. Now wi
|
||||
|
||||
---
|
||||
|
||||
## Breaking Change: Unified Logging Upgrade
|
||||
|
||||
> [!WARNING]
|
||||
> **This release changes both the on-disk request log layout and the logging environment variables.**
|
||||
>
|
||||
> If you are upgrading an existing instance:
|
||||
>
|
||||
> - Request logs now live in `DATA_DIR/call_logs/YYYY-MM-DD/` as **one JSON artifact per request**.
|
||||
> - The old `DATA_DIR/logs/` session folders and `DATA_DIR/log.txt` summary file are removed.
|
||||
> - On the first startup after upgrading, OmniRoute creates a safety backup at `DATA_DIR/log_archives/*.zip` before removing the deprecated request log layout.
|
||||
> - Legacy logging env vars such as `LOG_TO_FILE`, `LOG_FILE_PATH`, `LOG_MAX_FILE_SIZE`, `LOG_RETENTION_DAYS`, `LOG_LEVEL`, `LOG_FORMAT`, `ENABLE_REQUEST_LOGS`, `CALL_LOGS_MAX`, `CALL_LOG_PAYLOAD_MODE`, and `PROXY_LOG_MAX_ENTRIES` are no longer supported.
|
||||
> - Use the new env model instead:
|
||||
> - `APP_LOG_TO_FILE`
|
||||
> - `APP_LOG_FILE_PATH`
|
||||
> - `APP_LOG_MAX_FILE_SIZE`
|
||||
> - `APP_LOG_RETENTION_DAYS`
|
||||
> - `APP_LOG_LEVEL`
|
||||
> - `APP_LOG_FORMAT`
|
||||
> - `CALL_LOG_RETENTION_DAYS`
|
||||
>
|
||||
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
|
||||
|
||||
---
|
||||
|
||||
## 🆕 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 refreshes model lists for 16 providers on startup — configurable via `MODEL_SYNC_INTERVAL_HOURS` |
|
||||
| 🔄 **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` |
|
||||
@@ -196,7 +223,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.
|
||||
|
||||
---
|
||||
|
||||
@@ -222,7 +249,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
|
||||
```
|
||||
@@ -255,7 +282,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
|
||||
@@ -289,7 +316,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)
|
||||
@@ -341,7 +368,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>
|
||||
|
||||
@@ -353,7 +380,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
|
||||
@@ -406,7 +433,7 @@ Installing, configuring, and maintaining an AI proxy across different environmen
|
||||
- **Electron Desktop App** — Native app for Windows/macOS/Linux with system tray, auto-start, offline mode
|
||||
- **Split-Port Mode** — API and Dashboard on separate ports for advanced scenarios (reverse proxy, container networking)
|
||||
- **Cloud Sync** — Config synchronization across devices via Cloudflare Workers
|
||||
- **DB Backups** — Automatic backup, restore, export and import of all settings
|
||||
- **DB Backups** — Automatic backup, restore, export and import of all settings, with `DISABLE_SQLITE_AUTO_BACKUP` for externally managed backups
|
||||
|
||||
</details>
|
||||
|
||||
@@ -730,7 +757,7 @@ 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 |
|
||||
@@ -831,6 +858,113 @@ npm install
|
||||
PORT=20128 DASHBOARD_PORT=20129 NEXT_PUBLIC_BASE_URL=http://localhost:20129 npm run dev
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><b>Void Linux (`xbps-src` template)</b></summary>
|
||||
|
||||
For Void Linux users, you can build a native package using `xbps-src`. Save this block as `srcpkgs/omniroute/template`:
|
||||
|
||||
```bash
|
||||
# Template file for 'omniroute'
|
||||
pkgname=omniroute
|
||||
version=3.4.1
|
||||
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 (no network in do_build, native modules
|
||||
# compiled separately below; better-sqlite3 is serverExternalPackage so
|
||||
# Next.js does not execute it during next build)
|
||||
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 for the target architecture.
|
||||
# Use node-gyp directly so CC/CXX from xbps-src cross-toolchain are used
|
||||
# without npm altering them.
|
||||
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 – upstream sets images.unoptimized=true
|
||||
# so sharp is not used at runtime; x64 .so files would break aarch64 strip
|
||||
rm -rf .next/standalone/node_modules/@img
|
||||
|
||||
# 7) Copy pino runtime deps omitted by Next.js static analysis:
|
||||
# pino-abstract-transport – required by pino's worker thread
|
||||
# split2 – dep of pino-abstract-transport
|
||||
# process-warning – dep of pino itself
|
||||
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>
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Docker
|
||||
@@ -873,6 +1007,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 |
|
||||
@@ -939,7 +1111,7 @@ 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 |
|
||||
@@ -954,7 +1126,7 @@ When minimized, OmniRoute lives in your system tray with quick actions:
|
||||
```
|
||||
# 🆓 Ultimate Free Stack 2026 — 11 Providers, $0 Forever
|
||||
Kiro (kr/) → Claude Sonnet/Haiku UNLIMITED
|
||||
iFlow (if/) → kimi-k2-thinking, qwen3-coder-plus, deepseek-r1 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
|
||||
@@ -984,7 +1156,7 @@ Cerebras (cerebras/) → Llama/Qwen world-fastest — 1M tok/day
|
||||
| `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 |
|
||||
| ------------------ | ------ | ------------- | --------------- |
|
||||
@@ -1083,7 +1255,7 @@ Available free: `qwen3-235b-a22b-instruct-2507` (Qwen3 235B!), `llama-3.1-70b-in
|
||||
>
|
||||
> ```
|
||||
> Kiro (kr/) → Claude Sonnet/Haiku UNLIMITED
|
||||
> iFlow (if/) → kimi-k2-thinking, qwen3-coder-plus, deepseek-r1 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
|
||||
@@ -1178,6 +1350,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 |
|
||||
|
||||
@@ -1208,34 +1383,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
|
||||
|
||||
@@ -1487,6 +1674,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>
|
||||
@@ -1529,11 +1718,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:
|
||||
@@ -1731,7 +1920,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**
|
||||
|
||||
@@ -1753,7 +1942,9 @@ opencode
|
||||
|
||||
**No request logs**
|
||||
|
||||
- Set `ENABLE_REQUEST_LOGS=true` in `.env`
|
||||
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
|
||||
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
|
||||
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
|
||||
|
||||
**Connection test shows "Invalid" for OpenAI-compatible providers**
|
||||
|
||||
|
||||
+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 校验确保不会接受畸形数据。
|
||||
+2
-4
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
---
|
||||
|
||||
+161
-28
@@ -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,128 @@ 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 |
|
||||
| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
|
||||
| `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 +549,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 +597,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 +646,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 +694,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:
|
||||
@@ -637,11 +769,11 @@ OmniRoute implements provider-level resilience with four components:
|
||||
|
||||
Manage database backups in **Dashboard → Settings → System & Storage**.
|
||||
|
||||
| Action | Description |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
|
||||
| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
|
||||
| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
|
||||
| Action | Description |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
|
||||
| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
|
||||
| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
|
||||
|
||||
```bash
|
||||
# API: Export database
|
||||
@@ -667,10 +799,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 | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
+1301
-723
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 | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
+1278
-708
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.
|
||||
|
||||
|
||||
+80
-150
@@ -18,6 +18,35 @@ _Váš univerzální API proxy – jeden endpoint, více než 44 poskytovatelů,
|
||||
|
||||
---
|
||||
|
||||
### 🆕 What's New in v3.0.0
|
||||
|
||||
| Area | Change |
|
||||
| ------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| 🔒 **CodeQL Security** | Fixed 10+ CodeQL alerts: polynomial-redos, insecure-randomness, shell-injection |
|
||||
| ✅ **Route Validation** | All 176 API routes validated with Zod schemas + `validateBody()` |
|
||||
| 🐛 **omniModel Tag Leak** | Internal `<omniModel>` tags no longer leak to clients in SSE streams (#585) |
|
||||
| 🔑 **Registered Keys API** | Auto-provision API keys via `POST /api/v1/registered-keys` with quota enforcement |
|
||||
| 👁️ **Scoped API Key Reveal** 🆕 | Opt-in recovery of API keys via `ALLOW_API_KEY_REVEAL` |
|
||||
| 🎨 **Provider Icons** | 130+ provider logos via `@lobehub/icons` (SVG) with PNG fallback |
|
||||
| 🔄 **Model Auto-Sync** | 24h scheduler refreshes model lists for 16 providers |
|
||||
| 🌐 **OpenCode Zen/Go** | Two new providers: free tier + subscription tier |
|
||||
| 🔧 **926 Tests** | Full test suite passes with 0 failures |
|
||||
|
||||
### 🆕 What's New in v3.0.0
|
||||
|
||||
| Area | Change |
|
||||
| -------------------------- | --------------------------------------------------------------------------------- |
|
||||
| 🔒 **CodeQL Security** | Fixed 10+ CodeQL alerts: polynomial-redos, insecure-randomness, shell-injection |
|
||||
| ✅ **Route Validation** | All 176 API routes validated with Zod schemas + `validateBody()` |
|
||||
| 🐛 **omniModel Tag Leak** | Internal `<omniModel>` tags no longer leak to clients in SSE streams (#585) |
|
||||
| 🔑 **Registered Keys API** | Auto-provision API keys via `POST /api/v1/registered-keys` with quota enforcement |
|
||||
| 🎨 **Provider Icons** | 130+ provider logos via `@lobehub/icons` (SVG) with PNG fallback |
|
||||
| 🔄 **Model Auto-Sync** | 24h scheduler refreshes model lists for 16 providers |
|
||||
| 🌐 **OpenCode Zen/Go** | Two new providers: free tier + subscription tier |
|
||||
| 🔧 **926 Tests** | Full test suite passes with 0 failures |
|
||||
|
||||
---
|
||||
|
||||
## 🖼️ Hlavní ovládací panel
|
||||
|
||||
<div align="center"> <img src="./docs/screenshots/MainOmniRoute.png" alt="Řídicí panel OmniRoute" width="800"> </div>
|
||||
@@ -58,9 +87,9 @@ _Připojte libovolný nástroj IDE nebo CLI s umělou inteligencí přes OmniRou
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" width="110"> <a href="https://github.com/anomalyco/opencode"><img src="./public/providers/opencode.svg" alt="OpenCode" width="48"><br><b>OpenCode</b></a><br> <sub>⭐ 106 tisíc</sub> </td>
|
||||
<td align="center" width="110"> <a href="https://github.com/openai/codex"><img src="./public/providers/codex.png" alt="CLI Codexu" width="48"><br><b>CLI Codexu</b></a><br> <sub>⭐ 60,8 tisíc</sub> </td>
|
||||
<td align="center" width="110"> <a href="https://github.com/openai/codex"><img src="./public/providers/codex.png" alt="Codex CLI" width="48"><br><b>Codex CLI</b></a><br> <sub>⭐ 60,8 tisíc</sub> </td>
|
||||
<td align="center" width="110"> <a href="https://github.com/anthropics/claude-code"><img src="./public/providers/claude.png" alt="Claude Code" width="48"><br><b>Claude Code</b></a><br> <sub>⭐ 67,3 tisíc</sub> </td>
|
||||
<td align="center" width="110"> <a href="https://github.com/google-gemini/gemini-cli"><img src="./public/providers/gemini-cli.png" alt="Rozhraní příkazového řádku Gemini" width="48"><br> <b>Rozhraní příkazového řádku Gemini</b></a><br> <sub>⭐ 94,7 tisíc</sub> </td>
|
||||
<td align="center" width="110"> <a href="https://github.com/google-gemini/gemini-cli"><img src="./public/providers/gemini-cli.png" alt="Gemini CLI" width="48"><br> <b>Gemini CLI</b></a><br> <sub>⭐ 94,7 tisíc</sub> </td>
|
||||
<td align="center" width="110"> <a href="https://github.com/Kilo-Org/kilocode"><img src="./public/providers/kilocode.png" alt="Kilo kód" width="48"><br><b>Kilo kód</b></a><br> <sub>⭐ 15,5 tisíc</sub> </td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -106,7 +135,7 @@ Při otevírání problému spusťte příkaz system-info a přiložte vygenerov
|
||||
npm run system-info
|
||||
```
|
||||
|
||||
Tím se vygeneruje soubor `system-info.txt` s verzí Node.js, verzí OmniRoute, podrobnostmi o operačním systému, nainstalovanými nástroji CLI (iflow, gemini, claude, codex, antigravity, droid atd.), stavem Dockeru/PM2 a systémovými balíčky – vše, co potřebujeme k rychlé reprodukci vašeho problému. Soubor přiložte přímo k vašemu problému na GitHubu.
|
||||
Tím se vygeneruje soubor `system-info.txt` s verzí Node.js, verzí OmniRoute, podrobnostmi o operačním systému, nainstalovanými nástroji CLI (qoder, gemini, claude, codex, antigravity, droid atd.), stavem Dockeru/PM2 a systémovými balíčky – vše, co potřebujeme k rychlé reprodukci vašeho problému. Soubor přiložte přímo k vašemu problému na GitHubu.
|
||||
|
||||
---
|
||||
|
||||
@@ -132,7 +161,7 @@ Tím se vygeneruje soubor `system-info.txt` s verzí Node.js, verzí OmniRoute,
|
||||
│ ↓ 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
|
||||
```
|
||||
@@ -165,7 +194,7 @@ OpenAI používá jeden formát, Claude (Anthropic) jiný a Gemini ještě třet
|
||||
|
||||
**Jak to OmniRoute řeší:**
|
||||
|
||||
- **Sjednocený koncový bod** — Jeden `http://localhost:20128/v1` slouží jako proxy pro všech 44+ poskytovatelů.
|
||||
- **Sjednocený koncový bod** — Jeden `http://localhost:20128/v1` slouží jako proxy pro všech 67+ poskytovatelů.
|
||||
- **Překlad formátu** — Automatický a transparentní: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
|
||||
- **Sanitizace odpovědí** — Odstraňuje nestandardní pole ( `x_groq` , `usage_breakdown` , `service_tier` ), která porušují OpenAI SDK v1.83+
|
||||
- **Normalizace rolí** — Převádí `developer` → `system` pro poskytovatele bez OpenAI; `system` → `user` pro GLM/ERNIE
|
||||
@@ -197,7 +226,7 @@ Ne každý si může dovolit zaplatit 20–200 dolarů měsíčně za předplatn
|
||||
|
||||
**Jak to OmniRoute řeší:**
|
||||
|
||||
- **Vestavění poskytovatelé bezplatné úrovně** — Nativní podpora pro 100% bezplatné poskytovatele: iFlow (5 neomezených modelů přes OAuth: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2), Qwen (4 neomezené modely: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model), Kiro (Claude + AWS Builder ID zdarma), Gemini CLI (180 tisíc tokenů/měsíc zdarma)
|
||||
- **Vestavění poskytovatelé bezplatné úrovně** — Nativní podpora pro 100% bezplatné poskytovatele: Qoder (5 neomezených modelů přes OAuth: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2), Qwen (4 neomezené modely: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model), Kiro (Claude + AWS Builder ID zdarma), Gemini CLI (180 tisíc tokenů/měsíc zdarma)
|
||||
- **Ollama Cloud** — Cloudově hostované modely Ollama na `api.ollama.com` s bezplatnou úrovní „Light usage“; použijte prefix `ollamacloud/<model>`
|
||||
- **Kombinace pouze zdarma** — Chain `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 0 $/měsíc s nulovými prostoji
|
||||
- **NVIDIA NIM Free Access** — ~40 RPM developerský přístup k více než 70 modelům na build.nvidia.com (přechod z kreditů na čisté limity rychlosti)
|
||||
@@ -257,7 +286,7 @@ Claude Code, Codex, Gemini CLI, Copilot – všechny používají OAuth 2.0 s to
|
||||
**Jak to OmniRoute řeší:**
|
||||
|
||||
- **Automatická aktualizace tokenů** – Tokeny OAuth se obnovují na pozadí před vypršením platnosti.
|
||||
- **Vestavěný OAuth 2.0 (PKCE)** – Automatický tok pro Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
|
||||
- **Vestavěný OAuth 2.0 (PKCE)** – Automatický tok pro Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, Qoder
|
||||
- **Multi-Account OAuth** — Více účtů na poskytovatele prostřednictvím extrakce tokenů JWT/ID
|
||||
- **OAuth LAN/Remote Fix** — Detekce privátní IP adresy pro `redirect_uri` + manuální režim URL pro vzdálené servery
|
||||
- **OAuth Behind Nginx** — Používá `window.location.origin` pro kompatibilitu s reverzní proxy
|
||||
@@ -610,7 +639,7 @@ Outcome: deep fallback depth for deadline-critical workloads
|
||||
| Krok | Akce | Poskytovatelé odemčeni |
|
||||
| ---- | -------------------------------------------------------------- | ----------------------------------------------------------------- |
|
||||
| 1 | Připojení **Kiro** (AWS Builder ID OAuth) | Claude Sonnet 4.5, Haiku 4.5 – **neomezeně** |
|
||||
| 2 | Připojení k **iFlow** (Google OAuth) | kimi-k2-myšlení, qwen3-coder-plus, deepseek-r1... — **neomezeně** |
|
||||
| 2 | Připojení k **Qoder** (Google OAuth) | kimi-k2-myšlení, qwen3-coder-plus, deepseek-r1... — **neomezeně** |
|
||||
| 3 | Připojení **Qwen** (kód zařízení) | qwen3-coder-plus, qwen3-coder-flash... — **neomezeně** |
|
||||
| 4 | Připojení **rozhraní příkazového řádku Gemini** (Google OAuth) | gemini-3-flash, gemini-2.5-pro — **180 000 GBP/měsíc zdarma** |
|
||||
| 5 | `/dashboard/combos` → Šablona **Free Stack (0 $)** | Automatické zařazení všech bezplatných poskytovatelů do routingu |
|
||||
@@ -799,29 +828,29 @@ Po minimalizaci se OmniRoute nachází v systémové liště a nabízí rychlé
|
||||
|
||||
## 💰 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** | NVIDIA NIM | **ZDARMA** (vývoj navždy) | ~40 ot./min | 70+ otevřených modelů |
|
||||
| Mozky | **ZDARMA** (1 milion tok/den) | 60 000 otáček za minutu / 30 ot./min | Nejrychlejší na světě |
|
||||
| Groq | **ZDARMA** (30 ot./min.) | 14,4 tisíc otáček za minutu | Ultrarychlá lama/gema |
|
||||
| DeepSeek V3.2 | 0,27/1,10 USD za 1 milion | Žádný | Nejlepší zdůvodnění ceny a kvality |
|
||||
| xAI Grok-4 Rychlý | **0,20/0,50 USD za 1 milion** 🆕 | Žádný | Nejrychlejší + volání nástroje, ultranízké |
|
||||
| xAI Grok-4 (standardní) | 0,20/1,50 USD za 1 milion 🆕 | Žádný | Vlajková loď Reasoning od xAI |
|
||||
| Mistral | Zkušební verze zdarma + placené | Omezená sazba | Evropská umělá inteligence |
|
||||
| OpenRouter | Platba za použití | Žádný | Více než 100 modelů agregováno. |
|
||||
| **💰 LEVNÉ** | GLM-5 (přes Z.AI) 🆕 | 0,5 USD/1 milion | Denně v 10:00 | Výstup 128 tisíc obrazových bodů, nejnovější vlajková loď |
|
||||
| GLM-4.7 | 0,6 USD/1 milion | Denně v 10:00 | Záloha rozpočtu |
|
||||
| MiniMax M2.5 🆕 | Vstup 0,3 USD/1 milion | 5hodinové válcování | Úvaha + agentní úkoly |
|
||||
| MiniMax M2.1 | 0,2 USD/1 milion | 5hodinové válcování | Nejlevnější varianta |
|
||||
| Kimi K2.5 (Moonshot API) 🆕 | Platba za použití | Žádný | Přímý přístup k Moonshot API |
|
||||
| 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ý | 5 modelů neomezeně |
|
||||
| Qwen | **0 dolarů** | Neomezený | 4 modely neomezeně |
|
||||
| Kiro | **0 dolarů** | Neomezený | Claude Sonnet/Haiku (tvorce AWS) |
|
||||
| Ú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 |
|
||||
| Gemini CLI | **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** | NVIDIA NIM | **ZDARMA** (vývoj navždy) | ~40 ot./min | 70+ otevřených modelů |
|
||||
| Mozky | **ZDARMA** (1 milion tok/den) | 60 000 otáček za minutu / 30 ot./min | Nejrychlejší na světě |
|
||||
| Groq | **ZDARMA** (30 ot./min.) | 14,4 tisíc otáček za minutu | Ultrarychlá lama/gema |
|
||||
| DeepSeek V3.2 | 0,27/1,10 USD za 1 milion | Žádný | Nejlepší zdůvodnění ceny a kvality |
|
||||
| xAI Grok-4 Rychlý | **0,20/0,50 USD za 1 milion** 🆕 | Žádný | Nejrychlejší + volání nástroje, ultranízké |
|
||||
| xAI Grok-4 (standardní) | 0,20/1,50 USD za 1 milion 🆕 | Žádný | Vlajková loď Reasoning od xAI |
|
||||
| Mistral | Zkušební verze zdarma + placené | Omezená sazba | Evropská umělá inteligence |
|
||||
| OpenRouter | Platba za použití | Žádný | Více než 100 modelů agregováno. |
|
||||
| **💰 LEVNÉ** | GLM-5 (přes Z.AI) 🆕 | 0,5 USD/1 milion | Denně v 10:00 | Výstup 128 tisíc obrazových bodů, nejnovější vlajková loď |
|
||||
| GLM-4.7 | 0,6 USD/1 milion | Denně v 10:00 | Záloha rozpočtu |
|
||||
| MiniMax M2.5 🆕 | Vstup 0,3 USD/1 milion | 5hodinové válcování | Úvaha + agentní úkoly |
|
||||
| MiniMax M2.1 | 0,2 USD/1 milion | 5hodinové válcování | Nejlevnější varianta |
|
||||
| Kimi K2.5 (Moonshot API) 🆕 | Platba za použití | Žádný | Přímý přístup k Moonshot API |
|
||||
| Kimi K2 | 9 dolarů měsíčně bez závazků | 10 milionů tokenů/měsíc | Předvídatelné náklady |
|
||||
| **🆓 ZDARMA** | Qoder | **0 dolarů** | Neomezený | 5 modelů neomezeně |
|
||||
| Qwen | **0 dolarů** | Neomezený | 4 modely neomezeně |
|
||||
| Kiro | **0 dolarů** | Neomezený | Claude Sonnet/Haiku (tvorce AWS) |
|
||||
|
||||
> 🆕 **Přidány nové modely (březen 2026):** řada Grok-4 Fast za 0,20 USD/0,50 USD/M (benchmarkováno na 1143 ms – o 30 % rychlejší než Gemini 2.5 Flash), GLM-5 přes Z.AI s výstupem 128K, uvažování MiniMax M2.5, aktualizované ceny DeepSeek V3.2, Kimi K2.5 přes Moonshot Direct API.
|
||||
|
||||
@@ -830,7 +859,7 @@ Po minimalizaci se OmniRoute nachází v systémové liště a nabízí rychlé
|
||||
```
|
||||
# 🆓 Ultimate Free Stack 2026 — 11 Providers, $0 Forever
|
||||
Kiro (kr/) → Claude Sonnet/Haiku UNLIMITED
|
||||
iFlow (if/) → kimi-k2-thinking, qwen3-coder-plus, deepseek-r1 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
|
||||
@@ -860,7 +889,7 @@ Cerebras (cerebras/) → Llama/Qwen world-fastest — 1M tok/day
|
||||
| `claude-haiku-4.5` | `kr/` | **Neomezený** | Žádný hlášený denní limit |
|
||||
| `claude-opus-4.6` | `kr/` | **Neomezený** | Nejnovější opus od Kira |
|
||||
|
||||
### 🟢 MODELY IFLOW (Bezplatné OAuth — bez nutnosti platit kreditní kartou)
|
||||
### 🟢 MODELY QODER (Bezplatné OAuth — bez nutnosti platit kreditní kartou)
|
||||
|
||||
| Model | Předpona | Omezit | Limit rychlosti |
|
||||
| ------------------ | -------- | ------------- | ------------------- |
|
||||
@@ -914,7 +943,7 @@ K dispozici zdarma: `llama-3.3-70b-versatile` , `gemma2-9b-it` , `mixtral-8x7b`
|
||||
>
|
||||
> ```
|
||||
> Kiro (Claude, unlimited)
|
||||
> → iFlow (5 models, unlimited)
|
||||
> → Qoder (5 models, unlimited)
|
||||
> → Qwen (4 models, unlimited)
|
||||
> → Gemini CLI (180K/mo)
|
||||
> → Cerebras (1M tok/day)
|
||||
@@ -951,31 +980,6 @@ Pak v `/dashboard/media` → záložka **Přepis** : nahrajte libovolný zvukov
|
||||
|
||||
OmniRoute v2.0 je navržen jako operační platforma, nikoli pouze jako proxy pro relé.
|
||||
|
||||
### 🆕 Nové — Vylepšení inspirovaná ClawRouterem (březen 2026)
|
||||
|
||||
| Funkce | Co to dělá |
|
||||
| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| ⚡ **Grok-4 Rychlá rodina** | Modely xAI za 0,20 USD/0,50 USD/M – v benchmarku 1143 ms (o 30 % rychlejší než Gemini 2.5 Flash) |
|
||||
| 🧠 **GLM-5 přes Z.AI** | 128 tisíc výstupních dat, 0,5 USD/1 milion USD – nejnovější vlajková loď rodiny GLM |
|
||||
| 🔮 **MiniMax M2.5** | Úvaha + agentní úkoly za 0,30 USD/1 milion – významný upgrade oproti M2.1 |
|
||||
| 🎯 **Příznak volání nástroje pro každý model** | `toolCalling: true/false` v registru — AutoCombo přeskakuje modely, které nepodporují nástroje. |
|
||||
| 🌍 **Detekce vícejazyčného záměru** | Klíčová slova PT/ZH/ES/AR v bodování AutoCombo – lepší výběr modelu pro neanglický obsah |
|
||||
| 📊 **Záložní metody řízené benchmarkem** | Skutečná latence p95 z živých požadavků poskytuje kombinované skóre – AutoCombo se učí ze skutečných dat |
|
||||
| 🔁 **Požádat o deduplikaci** | Okno pro deduplikaci na základě hashování obsahu – bezpečné pro více agentů, zabraňuje duplicitním platbám |
|
||||
| 🔌 **Strategie pro zásuvné routery** | Rozšiřitelné rozhraní `RouterStrategy` – přidejte si vlastní logiku směrování jako pluginy |
|
||||
|
||||
### 🚀 Předchozí verze v2.0.9+ — Hřiště, otisky prstů v CLI a ACP
|
||||
|
||||
| Funkce | Co to dělá |
|
||||
| ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 🎮 **Modelové hřiště** | Stránka řídicího panelu pro přímé testování libovolného modelu – selektory poskytovatele/modelu/koncového bodu, editor Monaco, streamování, přerušení, načasování |
|
||||
| 🔏 **Porovnávání otisků prstů v CLI** | Řazení hlaviček/těl serveru podle poskytovatele tak, aby odpovídalo nativním podpisům CLI – přepínání pro jednotlivé poskytovatele v Nastavení > Zabezpečení. **Vaše IP adresa proxy serveru je zachována.** |
|
||||
| 🤝 **Podpora ACP (Agent Client Protocol)** | Vyhledávání agentů CLI (Codex, Claude, Goose, Gemini CLI, OpenClaw + 9 dalších), generátor procesů, koncový bod `/api/acp/agents` |
|
||||
| 🤖 **Řídicí panel agentů ACP** | Ladění › Stránka Agenti — mřížka 14 agentů se stavem instalace, verzí a formulářem pro vlastní agenta pro libovolný nástroj CLI. Uživatelé **OpenCode** získají tlačítko „Stáhnout opencode.json“, které automaticky vygeneruje konfiguraci připravenou k použití se všemi dostupnými modely. |
|
||||
| 🔧 **Směrování `apiFormat` pro vlastní model** | Vlastní modely s `apiFormat: "responses"` nyní správně směrují do překladače Responses API. |
|
||||
| 🏢 **Izolace pracovního prostoru Codexu** | Více pracovních prostorů Codexu na jeden e-mail – OAuth správně odděluje připojení podle ID pracovního prostoru |
|
||||
| 🔄 **Automatická aktualizace elektronů** | Desktopová aplikace kontroluje aktualizace + automaticky se instaluje po restartu |
|
||||
|
||||
### 🤖 Operace s agenty a protokoly (v2.0)
|
||||
|
||||
| Funkce | Co to dělá |
|
||||
@@ -1045,6 +1049,7 @@ OmniRoute v2.0 je navržen jako operační platforma, nikoli pouze jako proxy pr
|
||||
| Funkce | Co to dělá |
|
||||
| ----------------------------------- | ---------------------------------------------------------------------- |
|
||||
| 📝 **Žádost + protokolování proxy** | Úplné protokolování požadavků/odpovědí a proxy |
|
||||
| 📉 **Streamed Detailed Logs** 🆕 | Reconstructs SSE payload streams cleanly into the UI |
|
||||
| 📋 **Sjednocený panel protokolů** | Zobrazení požadavků, proxy, auditu a konzole na jedné stránce |
|
||||
| 🔍 **Vyžádat si telemetrii** | Latence p50/p95/p99 a trasování požadavků |
|
||||
| 🏥 **Panel zdraví** | Doba provozuschopnosti, stavy jističů, uzamčení, statistiky mezipaměti |
|
||||
@@ -1064,6 +1069,9 @@ OmniRoute v2.0 je navržen jako operační platforma, nikoli pouze jako proxy pr
|
||||
| 🎮 **Modelové hřiště** | Otestujte libovolného poskytovatele/model/koncový bod z řídicího panelu |
|
||||
| 🔏 **Přepínač otisků prstů v příkazovém řádku** | Porovnávání otisků prstů podle poskytovatele v Nastavení > Zabezpečení |
|
||||
| 🌐 **i18n (30 jazyků)** | Plná jazyková podpora dashboardu a dokumentace s psaním zprava doleva |
|
||||
| 🧹 **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 |
|
||||
| 📂 **Adresář vlastních dat** | Přepsání `DATA_DIR` pro umístění úložiště |
|
||||
|
||||
### Hluboký pohled na funkce
|
||||
@@ -1353,11 +1361,11 @@ Models:
|
||||
<summary><b>🆓 BEZPLATNÍ poskytovatelé (nouzové zálohování)</b></summary>
|
||||
</details>
|
||||
|
||||
### iFlow (5 BEZPLATNÝCH modelů přes OAuth)
|
||||
### Qoder (5 BEZPLATNÝCH modelů přes OAuth)
|
||||
|
||||
```bash
|
||||
Dashboard → Connect iFlow
|
||||
→ iFlow OAuth login
|
||||
Dashboard → Connect Qoder
|
||||
→ Qoder OAuth login
|
||||
→ Unlimited usage
|
||||
|
||||
Models:
|
||||
@@ -1439,7 +1447,7 @@ Settings → Models → Advanced:
|
||||
|
||||
Pro konfiguraci jedním kliknutím použijte stránku **Nástroje CLI** na řídicím panelu nebo ručně upravte soubor `~/.claude/settings.json` .
|
||||
|
||||
### CLI Codexu
|
||||
### Codex CLI
|
||||
|
||||
```bash
|
||||
export OPENAI_BASE_URL="http://localhost:20128"
|
||||
@@ -1552,7 +1560,7 @@ opencode
|
||||
|
||||
- Zkontrolujte statistiky využití v sekci Nástěnka → Náklady
|
||||
- Přepnout primární model na GLM/MiniMax
|
||||
- Pro nekritické úlohy použijte bezplatnou úroveň (Gemini CLI, iFlow).
|
||||
- Pro nekritické úlohy použijte bezplatnou úroveň (Gemini CLI, Qoder).
|
||||
|
||||
**Porty řídicího panelu/API jsou nesprávné**
|
||||
|
||||
@@ -1585,7 +1593,6 @@ opencode
|
||||
### 🔐 OAuth na vzdáleném serveru
|
||||
|
||||
<a name="oauth-on-a-remote-server"></a>
|
||||
<a name="oauth-em-servidor-remoto"></a>
|
||||
|
||||
> **⚠️ Důležité pro uživatele, kteří provozují OmniRoute na VPS, Dockeru nebo jakémkoli vzdáleném serveru**
|
||||
|
||||
@@ -1676,94 +1683,17 @@ Pokud si teď nechcete nastavovat vlastní přihlašovací údaje, můžete stá
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary><b>🇧🇷 Versão em Português</b></summary>
|
||||
</details>
|
||||
#### Dočasné řešení (bez vlastních přihlašovacích údajů)
|
||||
|
||||
#### Pokud používáte OAuth pro Antigravity / Gemini CLI?
|
||||
Chcete-li získat přístup k přihlašovacím údajům bez vlastní konfigurace, můžete použít následující postup:
|
||||
|
||||
Ověřeno **Antigravity** a **Gemini CLI** pomocí **Google OAuth 2.0** pro autenticitu. O Google exige que a `redirect_uri` usada no fluxo OAuth seja **exatamente** uma das URIs pre-cadastradas no Google Cloud Console to use.
|
||||
1. OmniRoute otevře URL autorizace Google
|
||||
2. Po autorizaci se Google pokusí přesměrovat na `localhost` (což selže na vzdáleném serveru)
|
||||
3. **Zkopírujte celou URL adresu** z adresního řádku prohlížeče
|
||||
4. Vložte tuto URL adresu do pole zobrazeného v modálním okně připojení OmniRoute
|
||||
5. Klikněte na **„Připojit"**
|
||||
|
||||
Jako credenciais OAuth embutidas no OmniRoute estão cadastradas **apenas para `localhost`** . Quando você acessa o OmniRoute em um servidor remote (ex: `https://omniroute.meuservidor.com` ), o Google rejeita a autenticação com:
|
||||
|
||||
```
|
||||
Error 400: redirect_uri_mismatch
|
||||
```
|
||||
|
||||
#### Řešení: Nakonfigurujte souas próprias credenciais OAuth
|
||||
|
||||
Você precisa criar um **OAuth 2.0 Client ID** no Google Cloud Console com a URI do seu server.
|
||||
|
||||
#### Přejít na přejezd
|
||||
|
||||
**1. Přístup ke službě Google Cloud Console**
|
||||
|
||||
Abra: [https://console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
|
||||
|
||||
**2. Crie um novo OAuth 2.0 Client ID**
|
||||
|
||||
- Klikněte na **„+ Vytvořit přihlašovací údaje“** → **„ID klienta OAuth“**
|
||||
- Typ aplikace: **"Webová aplikace"**
|
||||
- Název: escolha qualquer nome (např.: `OmniRoute Remote` )
|
||||
|
||||
**3. Adicione jako autorizované URI pro přesměrování**
|
||||
|
||||
Žádné pole **"URI autorizovaného přesměrování"** , adicione:
|
||||
|
||||
```
|
||||
https://seu-servidor.com/callback
|
||||
```
|
||||
|
||||
> Substitua `seu-servidor.com` pelo domínio ou IP do seu servidor (včetně portu se necessário, např.: `http://45.33.32.156:20128/callback` ).
|
||||
|
||||
**4. Uložte a kopii jako credenciais**
|
||||
|
||||
Após criar, o Google Mostrará o **Client ID** eo **Client Secret** .
|
||||
|
||||
**5. Nakonfigurujte jako variáveis de ambiente**
|
||||
|
||||
No seu `.env` (ou nas variáveis de ambiente do Docker):
|
||||
|
||||
```bash
|
||||
# Para Antigravity:
|
||||
ANTIGRAVITY_OAUTH_CLIENT_ID=seu-client-id.apps.googleusercontent.com
|
||||
ANTIGRAVITY_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
|
||||
|
||||
# Para Gemini CLI:
|
||||
GEMINI_OAUTH_CLIENT_ID=seu-client-id.apps.googleusercontent.com
|
||||
GEMINI_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
|
||||
GEMINI_CLI_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
|
||||
```
|
||||
|
||||
**6. Reinicie o OmniRoute**
|
||||
|
||||
```bash
|
||||
# Se usando npm:
|
||||
npm run dev
|
||||
|
||||
# Se usando Docker:
|
||||
docker restart omniroute
|
||||
```
|
||||
|
||||
**7. Připojte se znovu**
|
||||
|
||||
Řídicí panel → Poskytovatelé → Antigravity (nebo Gemini CLI) → OAuth
|
||||
|
||||
Agora nebo Google redirecionará corretamente para `https://seu-servidor.com/callback` ea autenticação funcionará.
|
||||
|
||||
---
|
||||
|
||||
#### Řešení temporário (sem configurar credenciais próprias)
|
||||
|
||||
Chcete-li získat přístup k kriterii pověření, můžete použít adresu **URL** :
|
||||
|
||||
1. O OmniRoute abrirá a URL autorização Google
|
||||
2. Após você autorizar, nebo Google tentará redirecionar para `localhost` (que falha no servidor remoto)
|
||||
3. **Zkopírujte úplnou** adresu URL prohlížeče do svého prohlížeče (mesmo que a pagina não carregue)
|
||||
4. Cole essa URL no campo que aparece no modal de conexão do OmniRoute
|
||||
5. Klikněte na **„Připojit se“**
|
||||
|
||||
> Toto řešení funguje na základě autorizačního kódu na adrese URL a nezávislého přesměrování přesměrování nebo jiného.
|
||||
> Toto řešení funguje, protože autorizační kód v URL adrese je platný bez ohledu na načtení přesměrovací stránky.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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 | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
+1266
-697
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 | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user