# Environment Variables Reference (Tiếng Việt)
🌐 **Languages:** 🇺🇸 [English](../../../../reference/ENVIRONMENT.md) · 🇪🇹 [am](../../../am/docs/reference/ENVIRONMENT.md) · 🇸🇦 [ar](../../../ar/docs/reference/ENVIRONMENT.md) · 🇦🇿 [az](../../../az/docs/reference/ENVIRONMENT.md) · 🇧🇬 [bg](../../../bg/docs/reference/ENVIRONMENT.md) · 🇧🇩 [bn](../../../bn/docs/reference/ENVIRONMENT.md) · 🇧🇦 [bs](../../../bs/docs/reference/ENVIRONMENT.md) · 🇨🇿 [cs](../../../cs/docs/reference/ENVIRONMENT.md) · 🇩🇰 [da](../../../da/docs/reference/ENVIRONMENT.md) · 🇩🇪 [de](../../../de/docs/reference/ENVIRONMENT.md) · 🇬🇷 [el](../../../el/docs/reference/ENVIRONMENT.md) · 🇪🇸 [es](../../../es/docs/reference/ENVIRONMENT.md) · 🇪🇪 [et](../../../et/docs/reference/ENVIRONMENT.md) · 🇮🇷 [fa](../../../fa/docs/reference/ENVIRONMENT.md) · 🇫🇮 [fi](../../../fi/docs/reference/ENVIRONMENT.md) · 🇫🇷 [fr](../../../fr/docs/reference/ENVIRONMENT.md) · 🇮🇪 [ga](../../../ga/docs/reference/ENVIRONMENT.md) · 🇮🇳 [gu](../../../gu/docs/reference/ENVIRONMENT.md) · 🇳🇬 [ha](../../../ha/docs/reference/ENVIRONMENT.md) · 🇮🇱 [he](../../../he/docs/reference/ENVIRONMENT.md) · 🇮🇳 [hi](../../../hi/docs/reference/ENVIRONMENT.md) · 🇭🇷 [hr](../../../hr/docs/reference/ENVIRONMENT.md) · 🇭🇺 [hu](../../../hu/docs/reference/ENVIRONMENT.md) · 🇦🇲 [hy](../../../hy/docs/reference/ENVIRONMENT.md) · 🇮🇩 [id](../../../id/docs/reference/ENVIRONMENT.md) · 🇳🇬 [ig](../../../ig/docs/reference/ENVIRONMENT.md) · 🇮🇹 [it](../../../it/docs/reference/ENVIRONMENT.md) · 🇯🇵 [ja](../../../ja/docs/reference/ENVIRONMENT.md) · 🇬🇪 [ka](../../../ka/docs/reference/ENVIRONMENT.md) · 🇰🇭 [km](../../../km/docs/reference/ENVIRONMENT.md) · 🇮🇳 [kn](../../../kn/docs/reference/ENVIRONMENT.md) · 🇰🇷 [ko](../../../ko/docs/reference/ENVIRONMENT.md) · 🇱🇹 [lt](../../../lt/docs/reference/ENVIRONMENT.md) · 🇱🇻 [lv](../../../lv/docs/reference/ENVIRONMENT.md) · 🇮🇳 [ml](../../../ml/docs/reference/ENVIRONMENT.md) · 🇮🇳 [mr](../../../mr/docs/reference/ENVIRONMENT.md) · 🇲🇾 [ms](../../../ms/docs/reference/ENVIRONMENT.md) · 🇲🇹 [mt](../../../mt/docs/reference/ENVIRONMENT.md) · 🇲🇲 [my](../../../my/docs/reference/ENVIRONMENT.md) · 🇳🇵 [ne](../../../ne/docs/reference/ENVIRONMENT.md) · 🇳🇱 [nl](../../../nl/docs/reference/ENVIRONMENT.md) · 🇳🇴 [no](../../../no/docs/reference/ENVIRONMENT.md) · 🇮🇳 [or](../../../or/docs/reference/ENVIRONMENT.md) · 🇮🇳 [pa](../../../pa/docs/reference/ENVIRONMENT.md) · 🇵🇭 [phi](../../../phi/docs/reference/ENVIRONMENT.md) · 🇵🇱 [pl](../../../pl/docs/reference/ENVIRONMENT.md) · 🇵🇹 [pt](../../../pt/docs/reference/ENVIRONMENT.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/reference/ENVIRONMENT.md) · 🇷🇴 [ro](../../../ro/docs/reference/ENVIRONMENT.md) · 🇷🇺 [ru](../../../ru/docs/reference/ENVIRONMENT.md) · 🇱🇰 [si](../../../si/docs/reference/ENVIRONMENT.md) · 🇸🇰 [sk](../../../sk/docs/reference/ENVIRONMENT.md) · 🇸🇮 [sl](../../../sl/docs/reference/ENVIRONMENT.md) · 🇷🇸 [sr](../../../sr/docs/reference/ENVIRONMENT.md) · 🇸🇪 [sv](../../../sv/docs/reference/ENVIRONMENT.md) · 🇰🇪 [sw](../../../sw/docs/reference/ENVIRONMENT.md) · 🇮🇳 [ta](../../../ta/docs/reference/ENVIRONMENT.md) · 🇮🇳 [te](../../../te/docs/reference/ENVIRONMENT.md) · 🇹🇭 [th](../../../th/docs/reference/ENVIRONMENT.md) · 🇹🇷 [tr](../../../tr/docs/reference/ENVIRONMENT.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/reference/ENVIRONMENT.md) · 🇵🇰 [ur](../../../ur/docs/reference/ENVIRONMENT.md) · 🇺🇿 [uz](../../../uz/docs/reference/ENVIRONMENT.md) · 🇳🇬 [yo](../../../yo/docs/reference/ENVIRONMENT.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/reference/ENVIRONMENT.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/reference/ENVIRONMENT.md)
---
> Tài liệu tham chiếu đầy đủ cho mọi biến môi trường được OmniRoute nhận diện.
> Để xem mẫu khởi động nhanh, hãy tham khảo [`.env.example`](../../.env.example).
> [!IMPORTANT]
> Mọi biến được ghi lại tại đây cũng phải xuất hiện trong `.env.example`, và
> mọi biến trong `.env.example` cũng phải xuất hiện tại đây. `npm run check:env-doc-sync`
> thực thi việc kiểm tra này khi commit và trong CI. Để chủ đích bỏ qua một biến, hãy thêm biến đó vào
> danh sách cho phép trong `scripts/check/check-env-doc-sync.mjs`.
---
## Mục lục
- [1. Bí mật bắt buộc](#1-required-secrets)
- [2. Lưu trữ & cơ sở dữ liệu](#2-storage--database)
- [3. Mạng & cổng](#3-network--ports)
- [4. Bảo mật & xác thực](#4-security--authentication)
- [5. Làm sạch dữ liệu đầu vào & bảo vệ PII](#5-input-sanitization--pii-protection)
- [6. Chính sách công cụ & định tuyến](#6-tool--routing-policies)
- [7. URL & đồng bộ hóa đám mây](#7-urls--cloud-sync)
- [8. Proxy đi](#8-outbound-proxy)
- [9. Tích hợp công cụ CLI](#9-cli-tool-integration)
- [10. Tích hợp tác tử nội bộ & MCP](#10-internal-agent--mcp-integrations)
- [11. Thông tin xác thực của nhà cung cấp OAuth](#11-oauth-provider-credentials)
- [12. Ghi đè User-Agent của nhà cung cấp](#12-provider-user-agent-overrides)
- [13. Khả năng tương thích dấu vân tay CLI](#13-cli-fingerprint-compatibility)
- [14. Nhà cung cấp khóa API](#14-api-key-providers)
- [15. Cài đặt thời gian chờ](#15-timeout-settings)
- [16. Ghi nhật ký](#16-logging)
- [17. Tối ưu hóa bộ nhớ](#17-memory-optimization)
- [18. Đồng bộ hóa giá](#18-pricing-sync)
- [19. Đồng bộ hóa mô hình (phát triển)](#19-model-sync-dev)
- [20. Cài đặt dành riêng cho nhà cung cấp](#20-provider-specific-settings)
- [21. Tình trạng proxy](#21-proxy-health)
- [22. Gỡ lỗi](#22-debugging)
- [23. Tích hợp GitHub](#23-github-integration)
- [24. Sandbox kỹ năng (v3.8.0+)](#24-skills-sandbox-v380)
- [27. Nguồn cấp Radar (tự lưu trữ)](#27-radar-feed-self-hosting)
- [Các kịch bản triển khai](#deployment-scenarios)
- [Kiểm tra: Các biến đã bị loại bỏ / không còn được sử dụng](#audit-removed--dead-variables)
---
## 1. Các bí mật bắt buộc
Các bí mật chưa được đặt và được đánh dấu **Có** sẽ được tự động tạo trong lần chạy đầu tiên (`JWT_SECRET`, `API_KEY_SECRET`) và được lưu vào `server.env` trong thư mục dữ liệu; hãy đặt chúng một cách tường minh khi thư mục đó là tạm thời. Ngoại lệ là `OMNIROUTE_WS_BRIDGE_SECRET`: nó không được lưu bền vào `server.env` — các entrypoint của máy chủ tạo một giá trị tạm thời cho mỗi lần khởi động mà chỉ cầu nối trong cùng tiến trình mới có thể dùng, vì vậy các client cầu nối bên ngoài cần đặt nó một cách tường minh.
| Biến | Bắt buộc | Mặc định | Tệp nguồn | Mô tả |
| ---------------------------- | ------------------- | ----------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `JWT_SECRET` | **Có** | _(không có)_ | `src/lib/auth` | Ký/xác minh tất cả cookie phiên của bảng điều khiển (JWT). Tạo bằng `openssl rand -base64 48`. |
| `API_KEY_SECRET` | **Có** | _(không có)_ | `src/lib/db/apiKeys.ts` | Khóa mã hóa AES cho các giá trị khóa API khi lưu trữ trong SQLite. Tạo bằng `openssl rand -hex 32`. |
| `INITIAL_PASSWORD` | Không | _(chưa đặt)_ | `src/lib/auth/managementPassword.ts` | Đặt mật khẩu bảng điều khiển khi khởi động khi chưa có mật khẩu nào được lưu; sẽ bị bỏ qua sau khi một mật khẩu đã được lưu. Các bản cài đặt bằng npm và từ mã nguồn sao chép `.env.example` thành `.env`, vì vậy chúng khởi động với giá trị giữ chỗ công khai đã biết `CHANGEME`: hãy thay thế nó trước lần khởi động đầu tiên, hoặc đặt `INITIAL_PASSWORD=` (rỗng) trong `.env` đó để tạo mật khẩu trong trình hướng dẫn thiết lập ban đầu (onboarding) ở lần truy cập đầu tiên, giống như một giá trị chưa đặt (mặc định của ảnh Docker) vẫn làm. Thay đổi mật khẩu đã lưu trong Bảng điều khiển → Cài đặt → Bảo mật, hoặc chạy `omniroute reset-password` (`node bin/reset-password.mjs` trong bản checkout mã nguồn) với `DATA_DIR` được đặt thành thư mục dữ liệu của máy chủ. |
| `OMNIROUTE_WS_BRIDGE_SECRET` | **Có** (production) | _(chưa đặt)_ | `src/app/api/internal/codex-responses-ws/route.ts` | Bí mật chia sẻ cho cầu nối WebSocket Codex Responses nội bộ. Xác thực các yêu cầu cầu nối giữa relay WS của Electron/trình duyệt và OmniRoute. ⚠️ **BẮT BUỘC trong môi trường production — khi chưa đặt, tất cả yêu cầu cầu nối WS đều bị từ chối.** Tạo bằng `openssl rand -base64 32`. |
| `OMNIROUTE_SW_BUILD_ID` | Không | _(git SHA)_ | `next.config.mjs`, `scripts/build/assembleStandalone.mjs` | Id chống cache service worker tường minh cho vỏ PWA (#11779); đứng đầu tiên trong chuỗi phân giải. |
| `SOURCE_VERSION` | Không | _(chưa đặt)_ | `next.config.mjs`, `scripts/build/assembleStandalone.mjs` | Thứ hai trong chuỗi — được các trình build PaaS (ví dụ kiểu Heroku) đặt thành commit được triển khai. |
| `NEXT_PUBLIC_SW_BUILD_ID` | Không | _(được suy ra)_ | `src/shared/components/PwaRegister.tsx` | Giá trị công khai tại thời điểm build mà client dùng để đăng ký `/sw.js?v=…`; được suy ra từ hai giá trị ở trên, sau đó là git SHA. |
| `OMNIROUTE_PEER_STAMP_TOKEN` | Không (tự động) | _(tự động mỗi lần khởi động)_ | `src/server/authz/policies/management.ts` | Bí mật riêng cho từng tiến trình chứng minh dấu peer-IP đáng tin cậy đến từ máy chủ HTTP của chính OmniRoute (`scripts/dev/peer-stamp.mjs`). Middleware authz chỉ tin cậy tính cục bộ của yêu cầu (việc giới hạn loopback/LAN đối với các tuyến LOCAL_ONLY) khi dấu mang token này. Được tự động tạo mỗi lần khởi động — hãy để chưa đặt; chỉ ghim nó cho các thiết lập đa tiến trình phải chia sẻ dấu. |
| `OMNIROUTE_TRUSTED_PROXIES` | Không | _(chưa đặt)_ | `scripts/dev/peer-stamp.mjs` | Danh sách IP hoặc dải CIDR phân tách bằng dấu phẩy của các reverse proxy mà danh sách cho phép/từ chối IP có thể tin cậy đối với `X-Forwarded-For` / `X-Real-IP` của chúng, bên cạnh loopback, địa chỉ mạng riêng và các edge Cloudflare, vốn luôn được tin cậy. Chỉ cần thiết cho một proxy trên bất kỳ địa chỉ công khai nào khác; nếu không, địa chỉ của chính proxy đó là thứ bộ lọc đánh giá. Bộ giới hạn tần suất theo từng client của relay (`/api/v1/relay/chat/completions`) dựa trên cùng địa chỉ client đã phân giải, không bao giờ chỉ dựa vào các header chuyển tiếp. |
### Các lệnh tạo
```bash
# Tạo cả bốn bí mật cùng một lúc:
echo "JWT_SECRET=$(openssl rand -base64 48)"
echo "API_KEY_SECRET=$(openssl rand -hex 32)"
echo "INITIAL_PASSWORD=$(openssl rand -base64 16)"
echo "OMNIROUTE_WS_BRIDGE_SECRET=$(openssl rand -base64 32)"
```
> [!CAUTION]
> Không bao giờ commit các tệp `.env` chứa bí mật thật vào hệ thống quản lý phiên bản. `.gitignore` đã loại trừ `.env`, nhưng hãy kiểm tra trước khi push.
---
## 2. Lưu trữ & Cơ sở dữ liệu
OmniRoute sử dụng **SQLite** (thông qua `better-sqlite3`) cho toàn bộ việc lưu trữ bền vững. Các biến này kiểm soát vị trí dữ liệu, mã hóa và vòng đời.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------------ | ----------------------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DATA_DIR` | `~/.omniroute/` | `src/lib/db/core.ts` | Thư mục gốc cho cơ sở dữ liệu SQLite, các bản sao lưu và tệp dữ liệu. Ghi đè khi dùng Docker volume hoặc đường dẫn tùy chỉnh. |
| `OMNIROUTE_ALLOW_DEFAULT_DATA_DIR` | _(chưa đặt)_ | `src/lib/dataPaths.ts` | Lối thoát cho cơ chế bảo vệ DATA_DIR của test/eval (#10428). Các bài kiểm thử và probe eval/print của Node (`-e`/`--eval`/`-p`/`--print`, bao gồm cả dạng `--eval=`/`--print=`) không có `DATA_DIR` sẽ được chuyển hướng đến một thư mục tạm dùng một lần để chúng không thể mở cơ sở dữ liệu thật của người vận hành; đặt thành `1` để chọn quay lại dùng thư mục thật. |
| `OMNIROUTE_BUILD_SHA` | _(chưa đặt)_ | `src/lib/monitoring/buildSha.ts` | Git SHA của artifact đang chạy. Được đóng dấu bởi `npm run build:release`; có thể tiêm vào các container được phát hành không kèm sentinel `dist/BUILD_SHA`. Hiển thị dưới dạng `system.buildSha` trên `/api/monitoring/health`. |
| `OMNIROUTE_RELEASE_REF` | `origin/main` | `scripts/build/buildProvenance.ts` | Ref mà cổng kiểm tra nguồn gốc pack-artifact dùng để đối chiếu SHA của bản build (#10427). |
| `OMNIROUTE_ALLOW_CANARY_BUILD` | _(chưa đặt)_ | `scripts/build/buildProvenance.ts` | Đặt thành `1` để cho phép đóng gói một bản build có SHA không nằm trên nhánh phát hành, ghi nhận nó như một canary có chủ đích thay vì làm cổng kiểm tra thất bại (#10427). |
| `OMNIROUTE_SMOKE_API_KEY` | _(chưa đặt)_ | `scripts/ops/deploy-canary.mjs` | Khóa API cho probe smoke của triển khai canary, được gửi dưới dạng `Authorization: Bearer` trên `/v1/chat/completions`. Chỉ được sử dụng bởi script triển khai (#10429), không bao giờ bởi server. Không liên quan đến các biến `OMNIROUTE_SMOKE_*` của bộ smoke harness CLI opt-in (`RUN_CLI_SMOKE=1`, `OMNIROUTE_SMOKE_BASE_URL/MODEL/API_KEY_ENV/TARGETS/TIMEOUT_MS` trong `tests/integration/upstream-cli-smoke.int.test.ts`) — xem [Tích hợp CLI → Lượt smoke thật](../guides/CLI-INTEGRATIONS.md). |
| `OMNIROUTE_BUILDING` | _(chưa đặt)_ | `src/lib/buildPhase.ts` | Tín hiệu giai đoạn build (#10060): được đặt thành `1` bởi `scripts/build/build-next-isolated.mjs` và được kế thừa bởi mọi build worker được tạo ra để tầng DB trả về một stub no-op thay vì tải addon better-sqlite3 native (vốn sẽ hủy worker khi thoát). Không bao giờ đặt cho server đang chạy. |
| `OMNIROUTE_SKIP_NATIVE_DEP_CHECK` | `0` | `scripts/check/check-native-deps.mjs` | Đặt thành `1` để bỏ qua bước kiểm tra prebuild tùy chọn cho các phụ thuộc native đối với các cây vendored đặc thù. Điều này không làm cho một phụ thuộc bị thiếu trở nên build được; chỉ sử dụng khi các phụ thuộc native được cung cấp ngoài luồng. |
| `OMNIROUTE_DATA_DIR` | _(chưa đặt)_ | `open-sse/executors/promptql/threadSticky.ts` | **Bí danh dự phòng** cho `DATA_DIR`, chỉ được kiểm tra khi `DATA_DIR` chưa được đặt. Được dùng để xác định vị trí cache phiên thread-sticky trên đĩa của PromptQL executor (`
/promptql-thread-sessions.json`); nếu cả hai biến đều không được đặt, cache chỉ tồn tại trong bộ nhớ (không được lưu lại qua các lần khởi động lại). |
| `OMNIROUTE_PLUGINS_DIR` | _(chưa đặt)_ | `src/lib/plugins/scanner.ts` | Thư mục mà **bộ quét plugin runtime** đọc — và cũng là thư mục gốc mà trình quản lý plugin cài đặt vào — ghi đè giá trị mặc định dẫn xuất từ thư mục home (#11827). Trỏ nó đến cây plugin được bind-mount trong Docker/K8s thay vì di chuyển HOME chỉ để thay đổi đường dẫn quét (HOME cũng chi phối mọi hành vi tương đối theo home khác). Chưa đặt = `~/.omniroute/plugins`, hoặc `/tmp/.omniroute/plugins` khi tiến trình không export home nào cả — tình trạng không phát hiện âm thầm mà biến này loại bỏ. Thư mục đã phân giải được ghi log một lần khi khởi động dưới dạng `scanner.dir_resolved` cùng với đầu vào được chọn. Chỉ phía server: các plugin lệnh CLI giữ biến riêng `OMNIROUTE_PLUGIN_PATH` (phần 9). |
| `STORAGE_ENCRYPTION_KEY` | _(trống = tắt)_ | `src/lib/db/encryption.ts` | Khóa AES để mã hóa toàn bộ cơ sở dữ liệu SQLite khi lưu trữ. Tạo bằng `openssl rand -hex 32`. |
| `STORAGE_ENCRYPTION_KEY_VERSION` | `v1` | `scripts/build/bootstrap-env.mjs`, `electron/main.js` | Nhãn phiên bản cho khóa mã hóa. Tăng giá trị này khi thực hiện xoay vòng khóa để hỗ trợ giải mã các bản sao lưu cũ. |
| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | `src/lib/db/backup.ts` | Khi đặt thành `true`, bỏ qua các bản sao lưu tệp SQLite định kỳ/trước khi ghi (lưu/xóa bảng giá models.dev, ghi cài đặt). Các bản sao lưu thủ công và trước khi khôi phục vẫn chạy. Nó **không** tắt bản snapshot an toàn bền vững bắt buộc của trình chạy migration hoặc cơ chế bảo vệ migration hàng loạt đối với một DB liên tục hiện có. Các bản sao lưu không thủ công bị giới hạn tối đa một lần mỗi 60 phút. Dashboard **Cài đặt → Lưu trữ** có thể tắt sao lưu tự động định kỳ một cách độc lập. |
| `OMNIROUTE_SQLITE_SLOW_MS` | _(chưa đặt/tắt)_ | `src/lib/db/adapters/slowDiagnostics.ts` | Đơn vị mili giây; giá trị dưới 1 hoặc không phải số thì vẫn tắt; cảnh báo tối đa một lần mỗi 10 giây; dòng log chỉ chứa driver, operation và elapsedMs. |
| `OMNIROUTE_CRYPT_KEY` | _(chưa đặt)_ | `src/lib/db/encryption.ts` | **Bí danh cũ (legacy)** của `STORAGE_ENCRYPTION_KEY`. Được chấp nhận làm phương án dự phòng khi biến chính không tồn tại. |
| `OMNIROUTE_API_KEY_BASE64` | _(chưa đặt)_ | `src/lib/db/encryption.ts` | **Bí danh cũ (legacy)** (dạng mã hóa Base64) được chấp nhận làm phương án dự phòng. Được giải mã tự động trước khi sử dụng. |
| `OMNIROUTE_DB_HEALTHCHECK_INTERVAL_MS` | _(chưa đặt)_ | `src/lib/db/core.ts` | Ghi đè khoảng thời gian healthcheck SQLite định kỳ (ms). Khi không đặt, giá trị mặc định được suy ra từ `NODE_ENV`. |
| `OMNIROUTE_WAL_TRUNCATE_INTERVAL_MS` | _(đã xóa)_ | `src/lib/db/walMaintenance.ts` | **Đã xóa.** Một `wal_checkpoint(TRUNCATE)` trực tiếp theo chu kỳ có thể làm mất hiệu lực ánh xạ wal-index dùng chung và khiến tiến trình bị crash với SIGBUS (#13973), vì vậy trình lập lịch không còn tồn tại nữa. Biến này không còn tác dụng: giá trị dương sẽ ghi một cảnh báo deprecation một lần duy nhất, còn `0` hoặc không đặt thì im lặng. WAL được duy trì bởi các checkpoint PASSIVE (bên dưới) và được cắt bớt (truncate) bởi checkpoint khi tắt. |
| `OMNIROUTE_WAL_PASSIVE_INTERVAL_MS` | `300000` (5m) | `src/lib/db/walMaintenance.ts` | Ghi đè khoảng thời gian chạy `wal_checkpoint(PASSIVE)` thường xuyên (ms). Giữ cho các frame WAL đang chờ ở mức nhỏ để checkpoint luôn nhanh và tệp WAL luôn nằm trong giới hạn giữa các lần cắt bớt khi tắt. `0` để tắt. |
| `OMNIROUTE_WAL_GUARD_MAX_MB` | `256` | `src/lib/db/walMaintenance.ts` | Khi một lần kiểm tra PASSIVE phát hiện tệp WAL vượt quá kích thước này, chạy `wal_checkpoint(RESTART)` để WAL bắt đầu lại mà không cần ghi lại wal-index đã ánh xạ. Các checkpoint chế độ truncate trực tiếp đã bị xóa (xem hàng `OMNIROUTE_WAL_TRUNCATE_INTERVAL_MS`). |
| `OMNIROUTE_PRESSURE_SELF_RESTART` | `false` | `open-sse/utils/resourcePressure.ts` | Đặt thành `1`/`true`/`yes`/`on` để thoát tiến trình sau khi áp lực tài nguyên nghiêm trọng kéo dài trong `OMNIROUTE_PRESSURE_SELF_RESTART_AFTER_MS`, cho phép trình giám sát (systemd `Restart=always`, chính sách khởi động lại của Docker) khởi động lại một tiến trình sạch thay vì trả về lỗi 503 vô thời hạn. |
| `OMNIROUTE_PRESSURE_SELF_RESTART_AFTER_MS` | `120000` (2m) | `open-sse/utils/resourcePressure.ts` | Khoảng thời gian áp lực nghiêm trọng phải kéo dài trước khi việc thoát để tự khởi động lại được kích hoạt. |
| `OMNIROUTE_PRESSURE_PSI_DISABLED` | `false` | `open-sse/utils/resourcePressurePolicy.ts` | Đặt thành `1`/`true`/`yes`/`on` để bỏ qua `/proc/pressure/memory` toàn hệ thống (`psi_some` / `psi_full`) khi một noisy neighbor gây ra lỗi 503 trong khi tiến trình này vẫn ổn (#13124). Các cơ chế bảo vệ cgroup và heap V8 vẫn bật. PSI cũng ngừng được tính là bằng chứng throttle từ kernel cho `cgroup_high`: tổng cgroup vượt `memory.high` khi đó chỉ chuyển sang trạng thái nghiêm trọng khi có mức tăng `high`/`max` trong `memory.events`. Nếu không có `memory.events` thì giữ nguyên tỷ lệ thô. |
| `OMNIROUTE_SQLJS_WASM_PATH` | _(tự động phát hiện)_ | `src/lib/db/adapters/sqljsAdapter.ts` | Đường dẫn rõ ràng (tuyệt đối hoặc tương đối so với cwd) đến `sql-wasm.wasm` khi sử dụng adapter dự phòng WASM `sql.js`. Tự động phát hiện thông qua các phụ thuộc của gói và các bố cục ứng viên khi không đặt. |
| `OMNIROUTE_BATCH_RETENTION_DAYS` | `30` | `src/lib/db/cleanup.ts` | Số ngày mà các checkpoint, các tệp input/output/error được tham chiếu, và hàng dữ liệu của một job Batch API ở trạng thái kết thúc (completed/failed/cancelled/expired) được tiến trình dọn dẹp tự động giữ lại trước khi xóa. Chỉ có hiệu lực khi `BATCH_AND_FILE_AUTO_CLEANUP_ENABLED` được bật; tương ứng với thời hạn lưu giữ output của chính Batch API của OpenAI. Không ảnh hưởng đến route `DELETE /api/v1/batches/delete-completed` do operator kích hoạt, route này theo thiết kế vẫn vô điều kiện (không lọc theo tuổi). |
| `BATCH_AND_FILE_AUTO_CLEANUP_ENABLED` | `false` | `src/lib/db/cleanup.ts` | Khi là `true`, cho phép tiến trình dọn dẹp tự động xóa các job Batch API ở trạng thái kết thúc (và các checkpoint của chúng) đã quá `OMNIROUTE_BATCH_RETENTION_DAYS`, đồng thời xóa nội dung BLOB của các tệp đã tải lên khi quá `expires_at` của riêng chúng. Tắt theo mặc định: mọi bản cài đặt hiện có sẽ giữ nguyên dữ liệu này như trước cho đến khi operator chủ động chọn bật. Đây cũng là một feature flag có thể chỉnh sửa trên dashboard — xem `docs/reference/FEATURE_FLAGS.md` → Runtime. |
| `OMNIROUTE_SKIP_DB_HEALTHCHECK` | `0` | `src/lib/db/core.ts`, `src/lib/db/healthCheck.ts` | Đặt thành `1` để bỏ qua hoàn toàn DB healthcheck khi khởi động. Hữu ích cho các tác vụ ngắn hạn và kiểm thử tích hợp. |
| `OMNIROUTE_FORCE_DB_HEALTHCHECK` | `0` | `src/lib/db/core.ts` | Đặt thành `1` để buộc bật vòng lặp DB healthcheck, ngay cả khi nó thông thường sẽ bị bỏ qua (ví dụ: các tác vụ ngắn hạn). |
| `OMNIROUTE_SKIP_POSTINSTALL` | `0` | `scripts/postinstall.mjs` | Đặt thành `1` để bỏ qua bước warm-up native-runtime trong quá trình `npm install`. Hữu ích trong các bản cài CI/headless nơi sqlite đã được build sẵn. |
| `OMNIROUTE_MIGRATIONS_DIR` | _(tự động phát hiện)_ | `src/lib/db/migrationRunner.ts` | Ghi đè thư mục mà migration runner quét. Hữu ích khi đóng gói kèm các migration trong các bản build tùy chỉnh. |
| `OMNIROUTE_EXTRA_MIGRATIONS_DIRS` | _(chưa đặt)_ | `src/lib/db/migrationRunner/extraDirs.ts` | Các thư mục migration bổ sung dưới dạng các mục `namespace=dir` được phân tách bằng dấu phân tách đường dẫn của nền tảng (ví dụ: `ee=/opt/app/enterprise/db/migrations`). Các tệp tìm thấy ở đó được ghi lại dưới dạng `-`, nên một bản phân phối đóng gói migration riêng sẽ không bao giờ xung đột với các slot số của upstream. Một mục sai định dạng, namespace không hợp lệ hoặc thư mục không tồn tại sẽ gây lỗi khi khởi động thay vì âm thầm bỏ qua schema. |
| `OMNIROUTE_MAX_PENDING_MIGRATIONS` | `50` | `src/lib/db/migrationRunner.ts` | Ngưỡng an toàn cho trường hợp có hàng loạt migration đang chờ (#3416). Quá trình khởi động sẽ hủy nếu có nhiều hơn số migration này đang chờ trên một DB hiện có (bảo vệ chống lại việc bảng tracking bị xóa sạch). Tăng giá trị này để khôi phục một bản sao lưu cũ hơn; đặt thành `0` để tắt kiểm tra này. |
| `OMNIROUTE_INSTALL_UPGRADE_WORKDIR` | _(`/.install-upgrade`)_ | `scripts/check/check-install-upgrade.mjs` | Thư mục làm việc cho release gate `check:install-upgrade`. Nó cần khoảng 12 GB (hai cây cài đặt ~3 GB cộng với tarball), nên không được chạy trên một tmpfs nhỏ — trên self-hosted runner, `/tmp` là một tmpfs 12 GB chạy trên RAM và gate đã làm cạn kiệt nó, khiến gói bị cắt cụt. |
| `OMNIROUTE_SPEND_FLUSH_INTERVAL_MS` | _(mặc định trong code)_ | `src/lib/spend/batchWriter.ts` | Khoảng thời gian flush (ms) cho bộ ghi spend/cost theo lô. Giá trị thấp hơn làm giảm việc gộp ghi; giá trị cao hơn làm giảm tranh chấp DB. |
| `OMNIROUTE_SPEND_MAX_BUFFER_SIZE` | _(mặc định trong code)_ | `src/lib/spend/batchWriter.ts` | Số mục spend được buffer tối đa trước khi buộc flush. Tăng lên trên các triển khai QPS cao; giảm xuống khi việc giới hạn bộ nhớ quan trọng hơn. |
| `OMNIROUTE_PROXY_FETCH_DEBUG` | _(chưa đặt)_ | `open-sse/utils/proxyFetch.ts` | Đặt thành `"true"` để phát ra các log debug `[ProxyFetch]` trên đường relay của Vercel. Tắt theo mặc định để tránh làm lộ các gợi ý định tuyến. |
| `OMNIROUTE_PROXY_CORE_BINARY_PATH` | _(chưa đặt)_ | `src/lib/proxySubscription/coreConfig/sync.ts` | Đường dẫn tuyệt đối của binary proxy core cục bộ (một tệp tên `sing-box`) dùng để kiểm tra cấu hình core được tạo trước khi nó thay thế tệp đã áp dụng. Khi chưa đặt, chỉ ghi `.generated` bên cạnh tệp đã áp dụng. Chỉ dành cho môi trường host: không bao giờ được lưu trong database cũng như không được chấp nhận qua management API, vì binary này sẽ được thực thi. |
| `OMNIROUTE_PROXY_CORE_RELOAD_COMMAND` | _(chưa đặt)_ | `src/lib/proxySubscription/coreConfig/reload.ts` | Cách proxy core cục bộ tải lại sau khi thay thế cấu hình đã được xác minh: một mảng tham số JSON được chạy không qua shell, hoặc đúng giá trị `external` khi một bộ quan sát bên ngoài áp dụng tệp. Không bao giờ được lưu trong database cũng như không được lộ qua API. |
| `PROXY_LOG_INCLUDE_IPS` | `false` | `src/lib/proxyLogger.ts` | Đặt thành `"true"` hoặc `"1"` để bao gồm IP máy khách/egress và tiền tố tài khoản trong dòng nhật ký tiến trình `[ProxyEgress]` chi tiết. Mặc định TẮT để nhật ký tiến trình không làm lộ IP hoặc tiền tố tài khoản. |
| `OMNIROUTE_DEBUG` | _(chưa đặt)_ | `bin/cli/commands/quota.mjs` | Đặt thành `1` để in chẩn đoán thời gian theo từng yêu cầu (`[omniroute] GET completed in Nms`) từ các lệnh quota CLI ra stderr. |
| `OMNIROUTE_HEALTHCHECK_PATH` | _(tự động)_ | `scripts/dev/healthcheck.mjs` | Đường dẫn tường minh được probe bởi health check của container. Khi không đặt, probe sẽ suy ra nó từ `OMNIROUTE_BASE_PATH`; đặt nó sẽ bật lại endpoint giám sát chuyên sâu. |
| `OMNIROUTE_DEBUG_COMPLETION` | _(chưa đặt)_ | `bin/cli/commands/completion.mjs` | Đặt thành bất kỳ giá trị không rỗng nào để phát chẩn đoán `[omniroute completion]` từ các đường dẫn bộ nhớ đệm tự hoàn thành shell của CLI (đọc/làm mới/ghi). Mặc định tắt — các bộ nhớ đệm đó thất bại âm thầm để bộ nhớ đệm bị thiếu/hỏng không bao giờ làm hỏng tính năng tự hoàn thành bằng phím Tab. |
| `BATCH_RETRY_DURATION_MS` | `86400000` (24 giờ) | `open-sse/services/batchProcessor.ts` | Cửa sổ thử lại tối đa cho từng mục trong lô (ms). Các mục vượt quá thời lượng này được đánh dấu là thất bại. |
| `BATCH_BACKOFF_BASE_MS` | `5000` | `open-sse/services/batchProcessor.ts` | Độ trễ cơ sở (ms) cho backoff lũy thừa khi thử lại các mục trong lô. |
| `BATCH_BACKOFF_MAX_MS` | `3600000` (1 giờ) | `open-sse/services/batchProcessor.ts` | Giới hạn trên (ms) cho backoff lũy thừa giữa các lần thử lại mục trong lô. |
| `BATCH_MAX_CONCURRENT` | `1` | `open-sse/services/batchProcessor.ts` | Số lô tối đa được xử lý đồng thời. Tăng để tăng thông lượng; giữ thấp để tránh bão giới hạn tốc độ. |
> [!IMPORTANT]
> Trước khi thay đổi một cơ sở dữ liệu bền vững hiện có, trình chạy migration sẽ xuất bản một snapshot
> đầy đủ, được định địa chỉ theo nội dung dưới `DATA_DIR/db_backups/`. Việc xuất bản yêu cầu một hệ thống tệp
> hỗ trợ các liên kết cứng không ghi đè trong cùng hệ thống tệp cùng với đồng bộ tệp bền vững. Máy chủ POSIX cũng
> yêu cầu đồng bộ thư mục; trên Windows, Node có thể từ chối các handle thư mục, vì vậy OmniRoute flush
> tệp đã xuất bản và coi việc đồng bộ mục nhập thư mục là nỗ lực tốt nhất.
> Nếu `DATA_DIR` được gắn kết không thể cung cấp những đảm bảo đó, quá trình khởi động sẽ thất bại an toàn (fail closed) trước khi áp dụng
> một migration. Di chuyển `DATA_DIR` sang một volume có các primitive đó; không dùng
> `DISABLE_SQLITE_AUTO_BACKUP` để bỏ qua tính an toàn của migration.
### Các tình huống
| Kịch bản | Cấu hình |
| ---------------------- | -------------------------------------------------------------------------------- |
| **Phát triển cục bộ** | Giữ tất cả mặc định. DB nằm tại `~/.omniroute/omniroute.db`. |
| **Docker** | `DATA_DIR=/data` + gắn một volume tại `/data`. |
| **Mã hóa khi lưu trữ** | Đặt `STORAGE_ENCRYPTION_KEY` + giữ bản sao lưu của khóa! Mất khóa = mất dữ liệu. |
| **CI/Kiểm thử** | `DATA_DIR=/tmp/omniroute-test` — tạm thời, không cần mã hóa. |
---
## 3. Mạng & Cổng
| Variable | Default | Source File | Description |
| ------------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PORT` | `20128` | `src/lib/runtime/ports.ts` | Cổng chính cho cả Dashboard UI và các endpoint API (chế độ cổng đơn). |
| `OMNIROUTE_BASE_PATH` | _(trống = gốc)_ | `next.config.mjs`, `scripts/docker/ensure-docker-base-path.mjs` | Đường dẫn con URL để phục vụ OmniRoute phía sau reverse proxy (đặt `basePath` của Next.js; các chuyển hướng xác thực có nhận biết basePath). Ví dụ: `/omniroute`. Trong Docker, giá trị được ghi cứng trong quá trình `docker build` (`ARG OMNIROUTE_BASE_PATH`); các image gốc dựng sẵn có thể áp dụng một giá trị runtime khác một lần khi container khởi động, trước khi Next.js khởi động. Đặt `NEXT_PUBLIC_BASE_URL` thành origin công khai bao gồm cùng đường dẫn con đó. |
| `NEXT_PUBLIC_OMNIROUTE_BASE_PATH` | _(trống = gốc)_ | `src/shared/hooks/useDisplayBaseUrl.ts` | Bản sao phía trình duyệt của `OMNIROUTE_BASE_PATH`, được nội tuyến tại thời điểm build để phần hiển thị endpoint trên dashboard hiển thị `https://host/omniroute/v1` thay vì `https://host/v1`. Sử dụng `OMNIROUTE_BASE_PATH` làm dự phòng khi chưa đặt. Cần build lại sau khi thay đổi (`basePath` của Next là thời điểm build). |
| `DASHBOARD_ALLOW_EMBED` | _(chưa đặt = không bao giờ được nhúng frame)_ | `next.config.mjs`, `scripts/build/dashboardEmbed.mjs` | Tùy chọn cho phép nhúng iframe các trang HTML. Khi không đặt, mọi route đều gửi kèm `frame-ancestors 'none'` + `X-Frame-Options: DENY`. Đặt thành `vscode` để phục vụ các trang (dashboard, login, docs, landing) với `frame-ancestors 'self' vscode-webview:` và không có `X-Frame-Options`, để Simple Browser của VS Code có thể hiển thị chúng (chế độ `dashboardOpen: "editor"` của OmniCopilot). Bề mặt API (`/api`, `/v1`, `/v1beta`, `/a2a`, `/healthz`, các alias cấp gốc) vẫn giữ các header nghiêm ngặt trong cả hai trường hợp. Chỉ `vscode` được nhận diện — `1`/`true` không kích hoạt tính năng này. Thời điểm build: cần build lại sau khi thay đổi (`docker build --build-arg DASHBOARD_ALLOW_EMBED=vscode` cho image; đặt nó trên bản cài đặt dựng sẵn sẽ không có tác dụng). |
| `API_PORT` | _(chưa đặt)_ | `src/lib/runtime/ports.ts` | Khi được đặt, phục vụ API proxy `/v1/*` trên cổng riêng này. |
| `API_HOST` | `0.0.0.0` | `src/lib/runtime/ports.ts` | Địa chỉ bind cho cổng API. |
| `DASHBOARD_PORT` | _(chưa đặt)_ | `src/lib/runtime/ports.ts` | Khi được đặt, phục vụ Dashboard UI trên cổng riêng này. |
| `OMNI_MAX_CONCURRENT_CONNECTIONS` | `0` _(tắt)_ | `src/sse/utils/backpressure.ts` | Giới hạn số kết nối chat đồng thời đang xử lý; các yêu cầu vượt quá giới hạn sẽ nhận `503` kèm `Retry-After`. Số nguyên dương kích hoạt cơ chế bảo vệ; không đặt/`0` sẽ tắt nó. |
| `OMNIROUTE_INSTANCE_ID` | _(chưa đặt)_ | `src/shared/resilience/peerRouting.ts` | ID ổn định, duy nhất cho gateway này khi kết nối chuỗi nhiều instance OmniRoute. Kích hoạt kiểm tra vòng lặp peer đến. Ký tự được phép: chữ cái, chữ số, `.`, `_`, `:`, và `-`; tối đa 64 ký tự. |
| `OMNIROUTE_PEER_URLS` | _(unset)_ | `src/shared/resilience/peerRouting.ts`, `open-sse/executors/base.ts` | Các base URL OmniRoute phân tách bằng dấu phẩy được phép nhận `X-OmniRoute-Peer-Trace`. Chỉ các URL upstream được liệt kê rõ ràng trong danh sách cho phép mới nhận metadata của peer; mọi provider khác không bị ảnh hưởng. |
| `OMNIROUTE_PEER_MAX_HOPS` | `4` | `src/shared/resilience/peerRouting.ts` | Số lượng tối đa các instance OmniRoute đã đi qua được chấp nhận trên một request chuỗi (`1`-`32`). Các instance lặp lại hoặc ngân sách hop đã cạn sẽ trả về HTTP `508 Loop Detected`. |
| `PROD_DASHBOARD_PORT` | `20130` | `docker-compose.prod.yml` | Cổng được publish phía host cho Dashboard ở chế độ Docker production. |
| `PROD_API_PORT` | `20131` | `docker-compose.prod.yml` | Cổng được publish phía host cho API ở chế độ Docker production. |
| `OMNIROUTE_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | Được ưu tiên hơn `PORT` khi chạy bên trong Electron hoặc các wrapper khác. |
| `LIVE_WS_PORT` | `20129` | `src/server/ws/liveServer.ts` | Cổng cho server WebSocket giám sát trực tiếp theo thời gian thực. |
| `LIVE_WS_HOST` | `127.0.0.1` | `src/server/ws/liveServer.ts` | Địa chỉ bind cho server WebSocket trực tiếp. Đặt thành `0.0.0.0` để mở ra mạng LAN (cũng cần cấu hình `LIVE_WS_ALLOWED_ORIGINS`). Kết nối xác thực bằng session cookie của dashboard hoặc Bearer API key có quyền quản lý (`manage`/`admin`). |
| `LIVE_WS_ALLOWED_ORIGINS` | _(unset)_ | `src/server/ws/liveServer.ts` | Các origin bổ sung phân tách bằng dấu phẩy được phép mở WebSocket trực tiếp. Các origin dashboard trên loopback đã được cho phép theo mặc định. |
| `LIVE_WS_ALLOWED_HOSTS` | _(unset)_ | `src/server/ws/liveServerAllowList.ts` | Các hostname bổ sung phân tách bằng dấu phẩy được phép cho origin WebSocket trực tiếp. Khác với `LIVE_WS_ALLOWED_ORIGINS` (URL origin đầy đủ), chỉ khớp với phần host — hữu ích cho các thiết lập LAN/Tailscale. |
| `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL` | _(unset)_ | `src/hooks/useLiveDashboard.ts` | URL công khai cho WebSocket dashboard trực tiếp (phía trình duyệt). Đặt khi đặt server WS sau reverse proxy hoặc Cloudflare Tunnel (ví dụ `wss://ws.my-ai.com/live-ws`); trình duyệt sẽ kết nối đến đó thay vì `ws://hostname:20132`. Phần pathname cũng được dùng làm đường dẫn upgrade WebSocket (mặc định: `/live-ws`). |
| `OMNIROUTE_ENABLE_LIVE_WS` | `true` | `src/server/ws/liveServer.ts` và `scripts/start-ws-server.mjs` | Đặt thành `0` hoặc `false` để tắt server WebSocket thời gian thực (mặc định bật, bind vào loopback). Công tắc CI/harness để tắt script helper WebSocket trực tiếp chạy độc lập. |
| `RELAY_IP_PER_MINUTE` | `30` | `src/app/api/v1/relay/chat/completions/route.ts` | Giới hạn tốc độ relay theo từng (token, IP), số request/phút. Lưu trong bộ nhớ, theo từng instance. `0` hoặc số âm sẽ tắt cổng kiểm soát theo chiều IP (giới hạn DB theo từng token vẫn áp dụng). |
| `NODE_ENV` | `production` | Next.js core | Kiểm soát mức độ chi tiết của log, bộ nhớ đệm, mức độ lộ chi tiết lỗi và các tối ưu hóa của Next.js. |
| `OMNIROUTE_USE_TURBOPACK` | `1` (Turbopack — mặc định trong code) | `package.json` / Next.js 16 | Turbopack là bundler mặc định cho `npm run dev` và `npm run build` (build nhanh hơn 2-3×, đã đo benchmark). Đặt thành `0` để quay lại dùng webpack trên Windows, khi gặp các vấn đề không tương thích về native binding / tương thích bundler, **hoặc trên các máy bị hạn chế RAM** — các bản build production bằng Turbopack trên dòng phiên bản Next.js này (16.2.x) được phía upstream xác nhận là có mức đỉnh sử dụng bộ nhớ cao hơn nhiều so với webpack trên các đồ thị module lớn (bản sửa lỗi memory-eviction của Turbopack trong Next 16.3 chưa ổn định); bản dự phòng webpack có mức đỉnh thấp hơn nhiều. Xem #6409. **Build image Docker mặc định là `0` (webpack)**: `Dockerfile` khai báo `ARG OMNIROUTE_USE_TURBOPACK=0` để lệnh `docker build .` thuần túy (Railway và các host triển khai một cú nhấp chuột khác, người tự host tùy ý) không bị OOM-kill trên builder bị giới hạn bộ nhớ; truyền `--build-arg OMNIROUTE_USE_TURBOPACK=1` để build image bằng Turbopack. Xem `docs/guides/DOCKER_GUIDE.md` → Tài nguyên lúc build. |
| `OMNIROUTE_SKIP_DB_HEALTHCHECK` | _(chưa đặt)_ | `src/lib/db/core.ts` / `src/lib/db/healthCheck.ts` | Đặt thành `1` để bỏ qua kiểm tra sức khỏe tính toàn vẹn của SQLite khi khởi động. Hữu ích để khởi động nhanh hơn với các cơ sở dữ liệu lớn. |
| `NOTIFY_SOCKET` | _(chưa đặt)_ | systemd (giao thức sd_notify) | Được systemd thiết lập khi tiến trình chạy dưới một service unit có tích hợp sd_notify; OmniRoute đọc biến này (xem `OMNIROUTE_DISABLE_SD_NOTIFY`) để gửi các thông báo READY/WATCHDOG. Người dùng không bao giờ tự đặt biến này. |
| `OMNIROUTE_DISABLE_SD_NOTIFY` | _(chưa đặt)_ | `scripts/dev/systemd-notify.mjs` | Đặt thành `1` để tắt systemd sd_notify (Type=notify / WatchdogSec=) ngay cả khi đang chạy dưới một systemd unit. Trình thông báo này vốn đã không có tác dụng khi chạy ngoài systemd. |
| `CREDENTIAL_HEALTH_CHECK_INTERVAL` | `3600000` | `open-sse/config/constants.ts` / `src/lib/credentialHealth/scheduler.ts` | Khoảng thời gian (ms) cho trình lập lịch kiểm tra sức khỏe credential chạy nền. Tối thiểu: 10000 (10 giây). |
| `CREDENTIAL_HEALTH_CACHE_TTL` | `300000` | `open-sse/config/constants.ts` / `src/lib/credentialHealth/cache.ts` | TTL (ms) cho trạng thái sức khỏe credential được lưu trong bộ nhớ đệm. |
| `OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK` | `false` | `src/lib/credentialHealth/scheduler.ts` | Đặt thành `1` hoặc `true` để tắt việc kiểm tra định kỳ chạy nền các kết nối provider. Các search provider (SEARCH_VALIDATOR_CONFIGS trong `src/lib/providers/validation/searchProviders.ts`, ví dụ `tavily-search`) luôn bị loại khỏi đợt quét — việc "xác thực" của chúng là một truy vấn upstream có tính phí thực sự, vì vậy chúng không bao giờ được kiểm tra sức khỏe theo bộ hẹn giờ (#9970). |
| `DEEP_HEALTH_CHECK_ENABLED` | `0` | `src/app/api/monitoring/health/route.ts` | Đặt thành `1` để cho phép caller đã xác thực yêu cầu `/api/monitoring/health?deep=1`, lệnh này sẽ lấy mẫu bề mặt completions một lần mỗi chu kỳ TTL. Caller ẩn danh không bao giờ kích hoạt probe. |
| `OMNIROUTE_EVENT_LOOP_STALL_THRESHOLD_MS` | `5000` | `src/lib/healthzLag.ts` | Ngưỡng stall (ms) cho trình ghi event loop lúc khởi động: một lần đóng băng dài hơn ngưỡng này sẽ ghi một dòng `event loop stalled` khi tiếp tục chạy, kèm theo số liệu bộ nhớ và số request đang xử lý, đồng thời tăng bộ đếm/giá trị tối đa `eventLoopStall` trên `/api/monitoring/health`. Đặt thành `0` để tắt; giá trị không đọc được hoặc giá trị âm sẽ quay về `5000`. |
| `HOST` | `0.0.0.0` | `scripts/dev/run-next.mjs` | Địa chỉ bind cho server dev/start của Next.js. Ghi đè giá trị mặc định `0.0.0.0` khi được đặt. |
| `HOSTNAME` | `127.0.0.1` | `scripts/dev/run-next-playwright.mjs` | Địa chỉ bind mà trình chạy Playwright sử dụng khi khởi chạy Next.js. Mặc định là `127.0.0.1` cho các kiểm thử hermetic. **Không dùng cho `omniroute serve`** — hãy dùng `OMNIROUTE_SERVER_HOST` thay thế (các shell POSIX tự động đặt `HOSTNAME` thành tên máy; `.env` không thể ghi đè nó). |
| `OMNIROUTE_SERVER_HOST` | `0.0.0.0` | `bin/cli/commands/serve.mjs` | Địa chỉ bind cho `omniroute serve`. Tránh xung đột với biến `HOSTNAME` của shell POSIX (luôn được bash/zsh đặt thành tên máy). Quay về `0.0.0.0` khi không được đặt. (#6194) |
### Chế độ cổng
```
┌─────────────────────────── Cổng đơn (mặc định) ────────────────────────────┐
│ PORT=20128 │
│ → Dashboard: http://localhost:20128 │
│ → API: http://localhost:20128/v1/chat/completions │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────── Tách cổng ───────────────────────────────────────┐
│ DASHBOARD_PORT=20128 │
│ API_PORT=20129 │
│ API_HOST=0.0.0.0 │
│ → Dashboard: http://localhost:20128 │
│ → API: http://0.0.0.0:20129/v1/chat/completions │
│ Trường hợp sử dụng: Mở API ra mạng LAN trong khi giới hạn Dashboard │
│ chỉ trên localhost. │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────── Docker (production) ────────────────────────────┐
│ PROD_DASHBOARD_PORT=443 PROD_API_PORT=8443 │
│ → Ánh xạ cổng container sang cổng máy chủ trong │
│ docker-compose.prod.yml. │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## 4. Bảo mật & Xác thực
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MACHINE_ID_SALT` | `endpoint-proxy-salt` | `src/lib/auth` | Salt kết hợp với các định danh phần cứng để tạo dấu vân tay máy (machine fingerprinting). Thay đổi theo từng lần triển khai để cách ly. |
| `OMNIROUTE_CLI_SALT` | _(chưa đặt = salt ngẫu nhiên theo mỗi lần cài đặt, được lưu tại `/cli-token-salt.json`)_ | `src/lib/machineToken.ts` | Salt HMAC dùng để dẫn xuất token xác thực CLI cục bộ. Đặt giá trị này sẽ xoay vòng tất cả token CLI trên máy và luôn được ưu tiên hơn salt đã lưu. Xem `docs/security/CLI_TOKEN.md`. |
| `AUTH_COOKIE_SECURE` | `false` | `src/lib/auth` | Đặt cờ `Secure` cho cookie phiên. **Phải là `true`** khi chạy sau HTTPS. |
| `REQUIRE_API_KEY` | `false` | API middleware | Khi là `true`, tất cả các yêu cầu proxy `/v1/*` phải kèm theo khóa API hợp lệ. **Cờ này không kiểm soát `GET /v1/models`**, endpoint này tuân theo chính sách đăng nhập của dashboard (`requireAuthForModels`) — vì vậy lỗi `401` từ `/v1/models` KHÔNG có nghĩa là inference được bảo vệ. Xem `docs/security/INFERENCE_AUTH_POSTURE.md` (#13695). |
| `ALLOW_API_KEY_REVEAL` | `false` | `src/shared/constants/featureFlagDefinitions.ts` | Cho phép hiển thị toàn bộ giá trị khóa API trong giao diện Dashboard. Có thể cấu hình từ Dashboard Feature Flags; rủi ro bảo mật trên các instance dùng chung. |
| `NO_LOG_API_KEY_IDS` | _(trống)_ | `src/lib/compliance/index.ts` | Danh sách ID khóa API phân tách bằng dấu phẩy được bỏ qua ghi log yêu cầu (tuân thủ GDPR). |
| `DEFAULT_RATE_LIMIT_PER_DAY` | _(chưa đặt = không giới hạn)_ | `src/shared/utils/apiKeyPolicy.ts` | Hạn ngạch yêu cầu mỗi ngày dự phòng, áp dụng cho các khóa API có cột `rate_limits` là null. Chưa đặt hoặc để trống: không có giới hạn ngầm định (#2289, #11017). `0` cũng tương tự (không giới hạn). Số nguyên dương N sẽ bật giới hạn N/ngày, 5N/tuần, 20N/tháng. Các giá trị không rỗng nhưng sai định dạng sẽ quay về các ngưỡng cũ 1000/ngày, 5000/tuần, 20000/tháng. |
| `MAX_BODY_SIZE_BYTES` | `10485760` (10 MB) | `src/shared/middleware/bodySizeGuard.ts` | Kích thước phần thân yêu cầu tối đa được phép. Từ chối các payload vượt quá giới hạn này. |
| `OMNIROUTE_CHAT_LARGE_BODY_BYTES` | `262144` (256 KB) | `src/shared/middleware/chatBodyAdmission.ts` | Các phần thân yêu cầu thực tế đạt hoặc vượt ngưỡng này sẽ chiếm lease admission heavyweight mang tính nguyên tử, cục bộ trong tiến trình trước khi phân tích cú pháp JSON (đường BYTE, bao gồm `POST /v1/responses`). Cùng cơ chế thoát healthy-headroom của [#10437](https://github.com/diegosouzapw/OmniRoute/pull/10437) như structure-heavy; vẫn bị giới hạn bởi `OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES` / [#10110](https://github.com/diegosouzapw/OmniRoute/issues/10110) để [#7849](https://github.com/diegosouzapw/OmniRoute/issues/7849) không tái diễn. |
| `OMNIROUTE_CHAT_HARD_MAX_BODY_BYTES` | `52428800` (50 MB) | `src/shared/middleware/chatBodyAdmission.ts` | Giới hạn cứng của route chat, được áp dụng đối với số byte đọc được trong quá trình nhập có giới hạn (bounded ingestion), bao gồm cả các request thiếu `Content-Length`, `Content-Length` không hợp lệ hoặc khai báo gian dối; phần vượt quá sẽ nhận `413`. |
| `OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT` | _(chưa đặt — không có giới hạn số lượng request)_ | `src/shared/middleware/chatBodyAdmission.ts` | **#503-fanout:** giới hạn SỐ LƯỢNG request kiểu cũ này giờ chỉ có hiệu lực khi được đặt rõ ràng. Khi không đặt (mặc định), việc tiếp nhận chat nặng (heavyweight) thay vào đó được kiểm soát bởi `OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES` — một ngân sách BYTE tự động suy ra, được định cỡ từ trần bộ nhớ thực của tiến trình trong **một tiến trình** (một V8 heap). Hai `/v1/responses` ~750k token chồng lấp nhau sẽ làm hủy các heap ~12 Gi (#7849) — đây là cảnh báo **ngân sách bộ nhớ**, không phải giới hạn cứng của sản phẩm là 2. Một tiến trình khỏe mạnh (heap dưới tỷ lệ shed) CÓ THỂ tiếp nhận thêm các `/v1/responses` dài đồng thời thông qua `OMNIROUTE_CHAT_ADMISSION_HEALTHY_HEADROOM`. Hàng chục client SSE dài (40–50) là chuyện của heap + `OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES` / #10110, không phải "tối đa 2". Việc mù quáng tăng giá trị này để "dùng hết máy chủ" sẽ tái hiện #7849. Hãy nhân **heap** bằng **N `DATA_DIR` độc lập** (#11024); tuyệt đối không `replicas>1` trên một tệp SQLite. |
| `OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES` | _(tự động suy ra)_ | `src/shared/middleware/admissionBudget.ts` | **#503-fanout:** ghi đè cho ngân sách byte nhập (ingest) tự động suy ra (25% của trần bộ nhớ V8/cgroup chặt hơn, chia cho hệ số khuếch đại tạm thời 8x). Giá trị suy ra lẫn giá trị đặt rõ đều được kẹp (clamp) trong khoảng 8 MiB–2 GiB. Một body lớn hơn ngân sách hiệu dụng sẽ thất bại ngay lập tức với `413 body_exceeds_budget`; sự tranh chấp giữa các body vốn có thể phục vụ riêng lẻ vẫn là `503` có thể thử lại. 40–50 client SSE dài đồng thời là ngân sách này + heap, không phải giới hạn cứng "tối đa 2". Hãy đọc `chatAdmission.maxInflightBytes` / `budgetSource` / `pressureSeverity` tại `/api/monitoring/health` trước khi điều chỉnh. |
| `OMNIROUTE_CHAT_ADMISSION_HEAP_SHED_RATIO` | `0.75` | `src/shared/middleware/chatBodyAdmission.ts` | Tỷ lệ shed theo áp lực heap (`heapUsed / heap_size_limit`) cho việc tiếp nhận nặng (heavyweight) theo BYTE và STRUCTURE (#10183, #10268, #10437). Một request nặng đồng thời vượt quá `OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT` chỉ bị shed với `503` có thể thử lại khi heap CŨNG đang ở hoặc trên tỷ lệ này; trên heap khỏe mạnh, nó được tiếp nhận thông qua healthy-headroom (dư địa khỏe mạnh) thay vào đó. |
| `OMNIROUTE_CHAT_ADMISSION_HEALTHY_HEADROOM` | `OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT` (mặc định `1`) | `src/shared/middleware/chatBodyAdmission.ts` | Dung lượng bổ sung có giới hạn cho đường nhanh heap-khỏe-mạnh (#10437) trên **cả** STRUCTURE và BYTE (`admitChatRequest`, bao gồm cả các body ≥ `OMNIROUTE_CHAT_LARGE_BODY_BYTES`). Nếu không có giới hạn này, mọi request bận-nhưng-heap-khỏe đều bỏ qua bước tiếp nhận (admission) mà không có trần nào. Một khi đã có chừng này lease đồng thời đang hoạt động qua đường heap-khỏe-mạnh, các request bận tiếp theo sẽ đi xuống CÙNG đường chờ-có-giới-hạn/shed được dùng khi có áp lực heap thực sự. `0` vô hiệu hóa hoàn toàn đường vòng này. |
| `OMNIROUTE_CHAT_HEAVY_MESSAGE_COUNT` | `200` | `src/shared/middleware/chatBodyAdmission.ts` | Số lượng message khiến một request chat bị phân loại là nặng (heavyweight) ngay cả khi body của nó dưới ngưỡng byte. |
| `OMNIROUTE_CHAT_HEAVY_TOOL_COUNT` | `64` | `src/shared/middleware/chatBodyAdmission.ts` | Số lượng tool khiến một request chat bị phân loại là nặng (heavyweight) ngay cả khi body của nó dưới ngưỡng byte. |
| `OMNIROUTE_CHAT_HEAVY_ESTIMATED_TOKENS` | `32000` | `src/shared/middleware/chatBodyAdmission.ts` | Ước tính token bảo thủ dựa trên kích thước chuỗi, dùng để phân loại một request là nặng; đây là đại diện cho chi phí tiếp nhận (admission-cost proxy), không phải cách token hóa để tính phí của nhà cung cấp. |
| `OMNIROUTE_CHAT_HARD_MAX_MESSAGES` | `0` (tắt) | `src/shared/middleware/chatBodyAdmission.ts` | Giới hạn lịch sử chat tùy chọn, phải bật rõ (opt-in). Tắt theo mặc định: số lượng message là chính sách triển khai, không phải thuộc tính phổ quát của một request, và việc giới hạn tại đây sẽ từ chối các cuộc hội thoại bằng `413` dứt điểm trước khi pipeline nén có thể khiến chúng phục vụ được. Mức tăng heap được giới hạn bởi `OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT` và cơ chế shed theo áp lực heap. Đặt giá trị dương trên các triển khai hạn chế bộ nhớ cần một trần cứng; phần vượt quá khi đó sẽ nhận `413` compact-required có cấu trúc. |
| `OMNIROUTE_MAX_NONSTREAMING_RESPONSE_BYTES` | `67108864` (64 MB) | `open-sse/handlers/chatCore/nonStreamingResponseBody.ts` | Giới hạn cứng cho một response upstream không streaming được đệm (buffer) toàn bộ vào bộ nhớ. Vượt quá mức này, bộ đọc upstream bị hủy và request thất bại nhanh (fail fast) thay vì phình một chuỗi không giới hạn cho đến khi cạn heap. |
| `OMNIROUTE_FORWARDING_HEADER_BUDGET_BYTES` | `768` | `open-sse/handlers/chatCore/responseHeaders.ts` | Số byte tối đa trên đường truyền được chuyển tiếp từ các header phản hồi upstream. Khi vượt quá ngân sách, các header có mức ưu tiên thấp hơn (ví dụ: `x-codex-*` tùy chỉnh, `x-oai-request-id`) sẽ bị loại bỏ để nằm trong giới hạn header thông thường của reverse proxy. Đặt cao hơn để chuyển tiếp nhiều metadata upstream hơn với cái giá là kích thước header phản hồi lớn hơn. |
| `CORS_ORIGIN` | _(chưa đặt)_ | `src/server/cors/origins.ts` | Danh sách cho phép CORS một nguồn gốc duy nhất kiểu cũ. Hãy ưu tiên `CORS_ALLOWED_ORIGINS` cho các triển khai mới. CORS chỉ dành cho các client API trình duyệt cross-origin; các thao tác ghi trên dashboard đã xác thực sử dụng các request cùng nguồn gốc (same-origin) cộng với bảo vệ CSRF gắn với phiên. |
| `CORS_ALLOWED_ORIGINS` | _(chưa đặt)_ | `src/server/cors/origins.ts` | Danh sách cho phép CORS phân tách bằng dấu phẩy. Không có wildcard nào được gửi trừ khi `CORS_ALLOW_ALL=true` được cấu hình rõ ràng. |
| `CORS_ALLOW_ALL` | `false` | `src/server/cors/origins.ts` | Cơ chế thoát hiểm chỉ dành cho môi trường phát triển để phản hồi lại bất kỳ `Origin` nào của trình duyệt. Không bật trên các triển khai dùng chung hoặc production. |
| `OUTBOUND_SSRF_GUARD_ENABLED` | `true` | `src/shared/network/outboundUrlGuardPolicy.ts` | Bí danh kiểu cũ. Nút bật/tắt trên dashboard của nó (một ghi đè trong DB) được đọc trước giá trị môi trường này; `false`, `0`, `no`, hoặc `off` ở một trong hai sẽ tắt các kiểm tra host theo cách giống như `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS=true`, ngay cả khi nút bật/tắt trên dashboard của flag đó được lưu ở trạng thái tắt; các giá trị khác sẽ để việc bảo vệ cho hai flag bên dưới quyết định. |
| `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` | `false` | `src/shared/network/outboundUrlGuardPolicy.ts` | Tắt các kiểm tra host của bộ bảo vệ URL outbound, bao gồm cả việc chặn cloud-metadata (toàn bộ 169.254.0.0/16, metadata.google.internal), trên các đường dẫn provider tuân theo chế độ bảo vệ: xác thực URL, khám phá model, base URL của các node provider (bao gồm các node rerank từ xa), và kiểm thử proxy-fallback, cùng các đường dẫn outbound liên quan đến provider khác như tải ảnh/media từ xa. Nó cũng cho phép các đích webhook riêng tư, ngoại trừ các endpoint cloud-metadata/link-local, vốn vẫn bị chặn ngay cả khi flag này bật. Các request chat được điều phối qua `BaseExecutor.execute()` vẫn giữ kiểm tra cloud-metadata của chúng. Các provider cục bộ hoạt động với giá trị mặc định: `OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS` (mặc định `true`) đã cho phép các URL cục bộ và LAN trên các đường dẫn xác thực, khám phá và node provider; kiểm thử proxy-fallback và các đích webhook riêng tư chỉ tham khảo flag này và chặn các host cục bộ/LAN khi nó tắt. Ghi đè `OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS=false`. Giá trị được lưu từ nút bật/tắt trên dashboard được ưu tiên hơn biến này. |
| `OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS` | `true` | `src/shared/network/outboundUrlGuardPolicy.ts` | Cho phép các URL provider trên địa chỉ cục bộ/riêng tư (127.0.0.1, localhost, LAN, các dải riêng tư) cho việc xác thực provider, khám phá model, chat, và các đường dẫn outbound liên quan đến provider khác mà chế độ bảo vệ quản lý. **Mặc định `true`** (ưu tiên cục bộ): khi đó bộ bảo vệ chặn các endpoint cloud-metadata — toàn bộ 169.254.0.0/16 cộng với các hostname metadata đã biết (metadata.google.internal, metadata.goog, IMDS của Alibaba/Azure/Oracle, fd00:ec2::254). Đặt `false` cho chế độ chỉ-công-cộng, chế độ này cũng chặn cả các host riêng tư và loopback. Bộ bảo vệ kiểm tra hostname hoặc IP literal đúng như được viết, trước bất kỳ tra cứu DNS nào; ở chế độ chỉ-công-cộng, wrapper safe-fetch sẽ phân giải thêm hostname và từ chối bất kỳ kết quả riêng tư nào. `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS=true` tắt các kiểm tra này trên các đường dẫn mà hàng của nó liệt kê. Các provider cục bộ tích hợp sẵn, như LM Studio, Ollama, vLLM, Llamafile, và Triton, bỏ qua mọi kiểm tra host cho việc xác thực key và chat. Giá trị được lưu từ nút bật/tắt trên dashboard được ưu tiên hơn biến này. (#5066) |
| `AUDIO_REMOTE_PROVIDER_NODES` | `false` | `src/app/api/v1/_shared/audioProviderNodes.ts` | Cho phép các route `/v1/audio/*` (transcriptions, speech, translations) sử dụng một node provider tương thích OpenAI được lưu trữ ngoài localhost. Tắt theo mặc định — định tuyến audio đến một host từ xa sẽ thay đổi danh tính egress và phải là một quyết định rõ ràng của người vận hành. Các node loopback/riêng tư (localhost, 127.0.0.1, 172.16-31.x) luôn được phép và không bị ảnh hưởng. (#3963) |
| `RERANK_REMOTE_PROVIDER_NODES` | `false` | `src/app/api/v1/_shared/rerankProviderNodes.ts` | Cho phép `POST /v1/rerank` (và bước rerank loopback của memory engine) sử dụng một node provider tương thích OpenAI được lưu trữ ngoài localhost — một máy trong LAN hoặc một peer Tailscale chạy TEI, Infinity, vLLM, v.v. Tắt theo mặc định — định tuyến đến một host từ xa sẽ thay đổi danh tính egress và phải là một quyết định rõ ràng của người vận hành. Các node loopback (localhost, 127.0.0.1, 172.16-31.x) luôn được phép và không bị ảnh hưởng. Base URL của một node từ xa cũng phải vượt qua chính sách URL outbound của provider (`OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS` / `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS`). |
| `OMNIROUTE_LOCAL_PROVIDER_NODE_HOSTS` | _(trống)_ | `src/shared/network/localNodeHosts.ts` | Tên máy chủ (phân tách bằng dấu phẩy hoặc khoảng trắng) mà định tuyến provider-node coi là cục bộ — thường là tên dịch vụ Docker/Compose của một reranker, TEI hoặc audio sidecar trên mạng Docker của chính OmniRoute (`http://reranker:8080/v1`), nhờ đó node không cần IP container được hard-code. Các host được liệt kê đủ điều kiện sử dụng `/v1/rerank`, `/v1/audio/*` và kiểm tra sức khỏe cục bộ mà không cần bật `RERANK_REMOTE_PROVIDER_NODES` / `AUDIO_REMOTE_PROVIDER_NODES` cho mọi node từ xa, đồng thời được gọi trực tiếp — không bao giờ thông qua `HTTP(S)_PROXY` hoặc proxy được ghim của kết nối. Chúng vẫn gửi API key của kết nối. Chỉ chấp nhận tên một nhãn và tên `.internal`/`.local`; các FQDN công khai, địa chỉ IP dạng literal và tên cloud-metadata sẽ bị bỏ qua kèm cảnh báo. (#14635) |
| `OMNIROUTE_OIDC_DISABLE_PASSWORD_LOGIN` | `false` | `src/app/api/auth/login/route.ts` | Khi OIDC được bật, tắt đăng nhập bằng mật khẩu để người dùng chỉ có thể xác thực qua OIDC Single Sign-On. Bí danh không tiền tố `OIDC_DISABLE_PASSWORD_LOGIN` cũng được chấp nhận; Feature Flag trên Dashboard có cùng khóa sẽ được ưu tiên áp dụng. (#10889) |
| `OIDC_DISABLE_PASSWORD_LOGIN` | `false` | `src/app/api/auth/login/route.ts` | Bí danh không tiền tố của `OMNIROUTE_OIDC_DISABLE_PASSWORD_LOGIN` (#10889). |
### Danh sách kiểm tra tăng cường bảo mật
```bash
# Mức tối thiểu về bảo mật cho production:
AUTH_COOKIE_SECURE=true # Yêu cầu HTTPS
REQUIRE_API_KEY=true # Xác thực mọi lệnh gọi proxy
ALLOW_API_KEY_REVEAL=false # Không bao giờ để lộ khóa trên UI
CORS_ALLOWED_ORIGINS=https://your.domain.com
MAX_BODY_SIZE_BYTES=5242880 # Giới hạn 5 MB
```
---
## 5. Làm sạch dữ liệu đầu vào & bảo vệ PII
OmniRoute cung cấp cơ chế phòng vệ hai lớp: quét tấn công chèn ở phía yêu cầu và loại bỏ PII ở phía phản hồi.
> **⚠️ Hạn chế:** Các biện pháp bảo vệ này là cơ chế phát hiện theo kinh nghiệm với _nỗ lực tối đa_, không phải tường lửa chống prompt injection hoàn chỉnh hay hệ thống DLP dành cho PII. Chúng có thể tạo ra kết quả dương tính giả (các prompt nhập vai/RPG lành tính bị gắn cờ) và âm tính giả (leet speak, chèn khoảng trắng, các mẫu không phải tiếng Anh). Chỉ riêng chúng không đủ để đảm bảo tuân thủ. Hãy tinh chỉnh các chế độ và kiểm thử với lưu lượng thực tế của bạn trước khi dựa vào chúng.
### Phía yêu cầu: Cơ chế bảo vệ chống prompt injection
| Biến | Mặc định | Tệp nguồn | Mô tả |
| --------------------------------- | ------------ | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `INPUT_SANITIZER_ENABLED` | `true` | `src/middleware/promptInjectionGuard.ts` | Bật tính năng quét các thông điệp gửi đến để phát hiện những mẫu prompt injection. |
| `INPUT_SANITIZER_MODE` | `warn` | `src/middleware/promptInjectionGuard.ts` | Chính sách chống tấn công chèn: `warn` = chỉ ghi nhật ký, `block` = từ chối yêu cầu với mã 400. Chế độ cũ `redact` **không** loại bỏ văn bản tấn công chèn; hãy dùng `PII_REDACTION_ENABLED` để ghi lại PII trong yêu cầu. |
| `INJECTION_GUARD_MODE` | _(chưa đặt)_ | `src/middleware/promptInjectionGuard.ts` | Bí danh cũ của `INPUT_SANITIZER_MODE` — có cùng hành vi. |
| `INPUT_SANITIZER_BLOCK_THRESHOLD` | `high` | `src/shared/utils/injectionSeverity.ts` | Mức độ nghiêm trọng tối thiểu bị `MODE=block` từ chối: `high` (mặc định), `medium` hoặc `low`. Các mẫu ở mức trung bình chỉ được quan sát trừ khi hạ ngưỡng. |
| `INJECTION_GUARD_BLOCK_THRESHOLD` | _(chưa đặt)_ | `src/shared/utils/injectionSeverity.ts` | Bí danh cũ của `INPUT_SANITIZER_BLOCK_THRESHOLD` — có cùng hành vi. |
| `PII_REDACTION_ENABLED` | `false` | `src/lib/guardrails/piiMasker.ts` | Khi là `true`, che PII trong các yêu cầu gửi đến (độc lập với chế độ chống tấn công chèn). |
| `CREDENTIAL_REDACTION_ENABLED` | `false` | `src/lib/guardrails/credentialMasker.ts` | Che các mẫu khóa API / token bí mật phổ biến khỏi payload yêu cầu/phản hồi. Đây là tính năng tùy chọn; hoạt động tương tự `PII_REDACTION_ENABLED`. |
### Phía phản hồi: Bộ làm sạch PII
| Biến | Mặc định | Tệp nguồn | Mô tả |
| -------------------------------- | -------- | ------------------------- | --------------------------------------------------------------------------------- |
| `PII_RESPONSE_SANITIZATION` | `false` | `src/lib/piiSanitizer.ts` | Quét phản hồi của LLM để phát hiện PII bị rò rỉ trước khi trả về cho máy khách. |
| `PII_RESPONSE_SANITIZATION_MODE` | `redact` | `src/lib/piiSanitizer.ts` | `redact` = che PII, `warn` = chỉ ghi nhật ký, `block` = loại bỏ toàn bộ phản hồi. |
### Bộ làm sạch ngữ cảnh tuyến được token hóa của VS Code
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ----------------------------------- | -------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_VSCODE_SANITIZE_CONTEXT` | `1` | `src/app/api/v1/vscode/contextSanitizer.ts` | Loại bỏ ngữ cảnh ngầm định của trình chỉnh sửa đang hoạt động (`editorContext`, `activeEditor`, `currentFile`, `selection`, `openTabs`…) khỏi các yêu cầu `/v1/vscode/[token]/*` và che nội dung của các tệp nhạy cảm được đính kèm rõ ràng. Bảo mật theo mặc định; đặt thành `0` để vô hiệu hóa. |
### Các tình huống
| Tình huống | Cấu hình |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Tuân thủ doanh nghiệp** | `INPUT_SANITIZER_ENABLED=true`, `INPUT_SANITIZER_MODE=block`, `PII_REDACTION_ENABLED=true`, `PII_RESPONSE_SANITIZATION=true` (chặn tấn công chèn + che PII trong yêu cầu/phản hồi; các chế độ hoạt động độc lập) |
| **Chỉ giám sát** | `INPUT_SANITIZER_ENABLED=true`, `INPUT_SANITIZER_MODE=warn` — ghi nhật ký nhưng không bao giờ chặn |
| **Sử dụng cá nhân** | Để tất cả ở trạng thái vô hiệu hóa — không phát sinh chi phí xử lý bổ sung |
---
## 6. Chính sách công cụ & định tuyến
| Variable | Default | Source File | Description |
| ----------------------------------------------------------- | ---------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `TOOL_POLICY_MODE` | `disabled` | `src/lib/toolPolicy.ts` | Kiểm soát quyền truy cập gọi công cụ/hàm (tool/function-calling) của LLM. `allowlist` = chỉ các công cụ được liệt kê, `denylist` = tất cả trừ các công cụ được liệt kê, `disabled` = không hạn chế. |
| `OMNIROUTE_PAYLOAD_RULES_PATH` | `./config/payloadRules.json` | `open-sse/services/payloadRules.ts` | Đường dẫn đến tệp JSON chứa các quy tắc chỉnh sửa payload (tinh chỉnh upstream theo từng mô hình/giao thức). |
| `OMNIROUTE_PAYLOAD_RULES_RELOAD_MS` | `5000` | `open-sse/services/payloadRules.ts` | Khoảng thời gian tải lại (ms) để hot-reload tệp quy tắc payload. Tối thiểu `1000`. |
| `OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS` | `false` | `open-sse/services/model.ts` | Tùy chọn bật: định tuyến các ID mô hình `claude-*` không có tiền tố từ các client Claude Code qua tài khoản Claude Code OAuth thay vì yêu cầu tiền tố provider. Tiền tố provider chỉ định rõ vẫn được ưu tiên. Cũng có thể cấu hình qua công tắc trên dashboard tại trang provider Claude. |
| `OMNIROUTE_REDACT_THINKING` | `true` | `open-sse/executors/base/redactThinkingBeta.ts` | Đặt `false` để ngăn OmniRoute tự thêm beta Anthropic `redact-thinking-2026-02-12` (các khối thinking rỗng chỉ còn chữ ký). Các yêu cầu có `thinking.display: "summarized"` luôn bỏ qua beta này; một beta redact do client thương lượng hoặc tùy chọn bật `requestDefaults.redactThinking` tương thích CC sẽ giữ lại nó. Các yêu cầu Claude OAuth giữ beta này (vì nó là một phần của dấu vân tay Claude Code OAuth) trừ khi cờ tính năng `CLAUDE_OAUTH_SUMMARIZED_THINKING_UNREDACTED` (mặc định tắt) được bật. |
| `BARE_MODEL_DEFAULT_OVERRIDE_LEGACY` | `false` | `open-sse/services/model.ts` | Hành vi `resolveBareModelToConnectionDefault` cũ (legacy) (#4825): thay thế bất kỳ tên mô hình không tiền tố nào bằng `defaultModel` của kết nối được chọn. Mặc định tắt, chỉ `auto` hoặc mô hình rỗng mới được thay thế; khi bật, ghi một cảnh báo cho mỗi cặp vào nhật ký. |
| `COMBO_CONCURRENCY_PER_MODEL` | `3` | `open-sse/services/comboConfig.ts` | Giới hạn đồng thời theo từng mô hình cho các combo round-robin (#9100). Trước đây semaphore của combo round-robin bị giới hạn cứng ở 3 yêu cầu đồng thời mỗi mô hình mà không thể ghi đè, khiến lưu lượng có độ đồng thời cao hơn bị xếp hàng tuần tự sau giới hạn đó. Được xác thực `>= 1`, kẹp tối đa `<= 32`. |
| `DISABLE_CONTEXT_WINDOW_CHECKS` | `false` | `open-sse/handlers/chatCore.ts` | Tùy chọn bật nguy hiểm: bỏ qua kiểm tra cửa sổ ngữ cảnh / max-input-token cục bộ của OmniRoute cho các yêu cầu trực tiếp đến một mô hình đơn lẻ. Các provider upstream vẫn thực thi giới hạn thực tế của họ; tính năng nén prompt và giới hạn output-token của chính mô hình vẫn hoạt động. Thứ tự ưu tiên hiệu lực: ghi đè trong Feature Flags DB > biến môi trường > mặc định; không cần khởi động lại. |
| `OMNIROUTE_SELF_HOSTED_PROVIDERS` | _(chưa đặt)_ | `open-sse/services/selfHostedEntry.ts` | Tài liệu YAML `providers:` nội tuyến (RIC-738, D4). Khi được đặt (có hoặc không có khối `strategy:`), `/v1/chat/completions` sẽ chuyển hướng sang điểm vào tự lưu trữ thống nhất tương thích OpenAI thay vì pipeline đám mây. Không đặt (mặc định): route đi thẳng qua pipeline đám mây hiện có. Xem `docs/routing/SELF_HOSTED_OPENAI_ENTRY.md`. |
| `OMNIROUTE_SELF_HOSTED_PROVIDERS_FILE` | _(chưa đặt)_ | `open-sse/services/selfHostedEntry.ts` | Đường dẫn đến tệp YAML chứa cùng tài liệu `providers:` như `OMNIROUTE_SELF_HOSTED_PROVIDERS`, dành cho các triển khai muốn dùng tệp thay vì biến môi trường nội tuyến. Chỉ cần một trong hai để kích hoạt điểm vào tự lưu trữ. |
| `OMNIROUTE_SELF_HOSTED_API_KEY` | _(chưa đặt — route mở)_ | `open-sse/services/selfHostedEntry.ts` | Khóa API dùng chung tùy chọn cho điểm vào tự lưu trữ thống nhất (khung D5, dành riêng cho hệ thống hạn ngạch theo khóa). Khi được đặt, các yêu cầu phải kèm `Authorization: Bearer `. Không đặt: route mở, phù hợp với mô hình provider cục bộ tự lưu trữ hiện có (triển khai trên loopback/mạng tin cậy). |
| `OMNIROUTE_SELF_HOSTED_STRATEGY` | _(chưa đặt)_ | `open-sse/services/routingStrategies.ts` | Tài liệu YAML `strategy:` nội tuyến cho engine định tuyến xác định (M2/RIC-740, D3) — blacklist/whitelist, bộ ngắt cooldown, ưu tiên theo chi phí, nhận biết độ trễ, chuỗi fallback. Ghi đè khối `strategy:` nội tuyến được lồng bên trong `OMNIROUTE_SELF_HOSTED_PROVIDERS`, theo từng key. Xem `docs/routing/DETERMINISTIC_ROUTING.md`. |
| `OMNIROUTE_SELF_HOSTED_STRATEGY_FILE` | _(chưa đặt)_ | `open-sse/services/routingStrategies.ts` | Đường dẫn tới một file YAML chứa cùng tài liệu `strategy:` như `OMNIROUTE_SELF_HOSTED_STRATEGY`, dành cho các triển khai thích dùng file hơn là biến môi trường nội tuyến. |
| `OMNIROUTE_DISABLE_CONVERSATION_TRACKING` | _(chưa đặt)_ | `open-sse/services/conversationTracker.ts` | Đặt `1` để ngừng thu thập lịch sử hội thoại. `resolveConversationId()` trả về kết quả không theo dõi trước khi đọc SQLite hoặc phân tích lịch sử tin nhắn, và các session ID do client cung cấp cũng được bao gồm. Việc xử lý phiên định tuyến không thay đổi và các bản ghi hiện có không bị xóa. Dành cho các triển khai không sử dụng chế độ xem hội thoại của dashboard và muốn bảng lượt (turn table) ngừng tăng trưởng. |
| `OMNIROUTE_NADIR_API_KEY` | _(chưa đặt)_ | `open-sse/services/autoCombo/nadirStrategy.ts` | Khóa API cho chiến lược router auto-combo `nadir` (tự chọn tham gia), được dùng khi `config.nadir.apiKey` của chính combo đó chưa được đặt. Tùy chọn: các cuộc gọi không có khóa sẽ rơi vào tầng ẩn danh của Nadir, tầng này bị giới hạn tốc độ theo IP và do đó không dùng được phía sau một gateway dùng chung. Thông tin nhạy cảm; nên dùng trường theo từng combo khi các combo sử dụng các tài khoản khác nhau. |
| `OMNIROUTE_NADIR_BASE_URL` | `https://api.getnadir.com` | `open-sse/services/autoCombo/nadirStrategy.ts` | Origin gốc của API quyết định Nadir, được dùng khi `config.nadir.baseUrl` của chính combo đó chưa được đặt. Chỉ cần thiết khi tự lưu trữ Nadir, giúp giữ các phần đầu prompt nằm trong mạng riêng của bạn. Hậu tố `/v1` ở cuối được chấp nhận và sẽ bị loại bỏ. |
| `OMNIROUTE_API_KEY_WEEKLY_WINDOW` | `provider` | `src/lib/usage/apiKeyUsageLimits.ts` | Cửa sổ tuần cho giới hạn mức sử dụng USD theo từng khóa API (áp dụng khi xử lý yêu cầu, `GET /api/keys/{id}/usage-limits`, `@@om-usage`). `provider`: tuần kết thúc tại thời điểm reset tuần sớm nhất trong số các kết nối upstream mà khóa có thể truy cập, hoặc là 7 ngày cuốn chiếu khi không xác định được. `calendar`: tuần theo giờ địa phương từ thứ Hai 00:00 đến thứ Hai 00:00 kế tiếp, giống nhau cho mọi khóa. `calendar` được khuyến nghị khi một nhóm tài khoản upstream được chia sẻ bởi nhiều khóa có ngân sách riêng lẻ. Giá trị không hợp lệ sẽ quay về `provider`. |
| `OMNIROUTE_API_KEY_WEEKLY_WINDOW_TIMEZONE` | _(múi giờ của tiến trình)_ | `src/lib/usage/apiKeyUsageLimits.ts` | Múi giờ IANA (ví dụ `Asia/Shanghai`) xác định thứ Hai 00:00 cho cửa sổ tuần `calendar`. Chưa đặt hoặc không hợp lệ: múi giờ của tiến trình OmniRoute (`TZ` của host hoặc container, thường chưa được đặt, tức Giờ Phối hợp Quốc tế — UTC, trong các image container). Bị bỏ qua ở chế độ `provider`. |
| `OMNIROUTE_MAX_TOOLS_LIMIT` | `128` | `open-sse/config/constants.ts` | Số lượng công cụ tối đa mặc định được phép trong một yêu cầu (mặc định của OpenAI). Chỉ chấp nhận số nguyên dương; giá trị chưa đặt hoặc không hợp lệ sẽ giữ nguyên `128`. Một provider có giới hạn đã biết/chủ động (`grok-cli` 200, `nvidia` 1536) vẫn áp dụng mức trần riêng của nó — tùy chọn này chỉ thay đổi ngưỡng trần mặc định. |
| `OMNIROUTE_PROMPT_EMULATE_TOOLS` | _(bật)_ | `open-sse/executors/syntxChat.ts` | Gọi công cụ mô phỏng bằng prompt của SYNTX.ai: chưa đặt hoặc `1`/`true`/`on`/`yes` sẽ chèn danh mục công cụ cục bộ vào prompt; bất kỳ giá trị nào khác (ví dụ `0`) sẽ bỏ qua việc chèn đó. |
## 7. URL & Đồng bộ hóa đám mây
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `BASE_URL` | `http://localhost:20128` | `src/lib/cloudSync.ts` | URL phía máy chủ để các tác vụ đồng bộ hóa nội bộ gọi `/api/sync/cloud`. Hãy giữ đây là URL loopback/container ngay cả khi ứng dụng được proxy công khai. |
| `CLOUD_URL` | _(trống)_ | `src/lib/cloudSync.ts` | URL điểm cuối chuyển tiếp đám mây (tính năng cao cấp). |
| `CLOUD_SYNC_TIMEOUT_MS` | `12000` | `src/lib/cloudSync.ts` | Thời gian chờ HTTP cho các yêu cầu đồng bộ hóa đám mây. |
| `OMNIROUTE_BUILD_PROFILE` | `full` | Cấu hình build Webpack | Cấu hình build tại thời điểm build (đặt thành `minimal` để loại trừ hoàn toàn các mô-đun đặc quyền khỏi bundle). |
| `OMNIROUTE_STANDALONE_DIR` | _đầu ra standalone .build/_ | `scripts/build/colocate-standalone.mjs` | Giá trị ghi đè tại thời điểm build cho thư mục đầu ra standalone được bước sắp xếp sau build sử dụng. Đây không phải là cài đặt thời gian chạy. |
| `OMNIROUTE_CLOUD_SYNC_SECRET` | _(trống)_ | `src/lib/cloudSync.ts` | Bí mật dùng chung để xác minh chữ ký HMAC-SHA256 của các phản hồi Đồng bộ hóa đám mây. |
| `OMNIROUTE_CLOUD_SYNC_SECRETS` | `false` | `src/lib/cloudSync.ts` | Đặt thành `true` để cho phép điểm cuối Đồng bộ hóa đám mây ghi đè thông tin xác thực cục bộ. Giá trị mặc định là `false`. |
| `OMNIROUTE_CLOUD_SYNC_ENFORCE_SIGNATURE` | `false` | `src/lib/cloudSync.ts` | Đặt thành `true` để từ chối phản hồi Đồng bộ hóa đám mây không có chữ ký khi không có bí mật cục bộ nào được cấu hình (#13679). Chữ ký hiện diện luôn được xác minh — và luôn bị từ chối khi `OMNIROUTE_CLOUD_SYNC_SECRET` chưa được đặt — bất kể cờ này. Mặc định sẽ chuyển sang bắt buộc trong v3.9. |
| `OMNIROUTE_ZED_IMPORT_LEGACY_ONE_STEP` | `false` | `src/app/api/providers/zed/import/route.ts` | Đặt thành `true` để quay lại hành vi "nhập mọi thứ" trong một bước của v3.8.5 mà không cần người dùng xác nhận. |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | OAuth, Bảng điều khiển, đồng bộ hóa | URL công khai dành cho OAuth redirect_uri, các liên kết Bảng điều khiển và các URL công khai được tạo. Đặt giá trị này thành URL công khai ổn định khi callback OAuth hoặc các liên kết trình duyệt được tạo phải sử dụng máy chủ reverse-proxy chuẩn tắc. |
| `NEXT_PUBLIC_CLOUD_URL` | _(trống)_ | Phía máy khách | Bản sao phía máy khách của `CLOUD_URL`. |
| `NEXT_PUBLIC_APP_URL` | _(chưa đặt)_ | `src/shared/services/cloudSyncScheduler.ts` | Phương án dự phòng cũ cho `NEXT_PUBLIC_BASE_URL`. |
| `NEXT_PUBLIC_PORT` | _(chưa đặt — dự phòng về `PORT`)_ | `src/shared/hooks/useDisplayBaseUrl.ts` | Cổng dự phòng phía máy khách dành cho các URL hiển thị khi không xác định được origin (SSR/kiểm thử); được đọc trước `PORT`. |
| `OMNIROUTE_PUBLIC_BASE_URL` | _(chưa đặt)_ | Trình phân giải origin công khai, URL hình ảnh | Origin OmniRoute dành cho trình duyệt có mức ưu tiên cao nhất, được dùng để tạo URL công khai và xác thực origin của trình duyệt ngoài dashboard. Hãy đặt biến này khi OpenWebUI hoặc một relay khác truy cập OmniRoute qua URL nội bộ nhưng trình duyệt của người dùng phải tải nội dung đa phương tiện được tạo từ mạng LAN, tunnel hoặc origin công khai. **Không** bao gồm `/v1`. |
| `OMNIROUTE_PROVIDER_MANIFEST_URL` | _(chưa đặt)_ | `open-sse/config/providerPluginManifestUrl.ts` | URL tuyệt đối của manifest plugin nhà cung cấp được công bố cho các máy khách sidecar. Khi chưa được đặt, OmniRoute suy ra `/api/v1/provider-plugin-manifest` từ origin của yêu cầu hoặc HOST/PORT. |
| `OMNIROUTE_PUBLIC_PROTOCOL` | `http` | `open-sse/config/providerPluginManifestUrl.ts` | Giao thức được sử dụng khi suy ra URL manifest plugin nhà cung cấp từ HOST/PORT mà không có origin của yêu cầu. Đặt thành `https` khi nằm sau proxy công khai chấm dứt TLS nếu không đặt `OMNIROUTE_PROVIDER_MANIFEST_URL` rõ ràng. |
| `OMNIROUTE_TRUST_PROXY` | _(chưa đặt)_ | `src/server/origin/publicOrigin.ts` | Chế độ tin cậy tùy chọn cho các header origin công khai được chuyển tiếp. Chưa đặt = không tin cậy `Forwarded` / `X-Forwarded-*` cho các quyết định bảo mật. `true` / `loopback` chỉ tin cậy host/giao thức được chuyển tiếp từ proxy loopback có gắn token. `private` / `lan` cũng tin cậy các peer proxy trong mạng LAN riêng và cho phép bridge `API_PORT` giữ lại `X-Forwarded-For` của peer đó. Nên ưu tiên đặt rõ ràng `NEXT_PUBLIC_BASE_URL` trong môi trường production. |
| `KIE_CALLBACK_URL` | _(chưa đặt)_ | `open-sse/utils/kieTask.ts` | URL callback công khai dành cho các tác vụ kie.ai bất đồng bộ. Giá trị ghi đè có mức ưu tiên cao nhất, trước `OMNIROUTE_KIE_CALLBACK_URL` và `OMNIROUTE_PUBLIC_URL`. |
| `OMNIROUTE_KIE_CALLBACK_URL` | _(chưa đặt)_ | `open-sse/utils/kieTask.ts` | Cách viết thay thế của `KIE_CALLBACK_URL`. Được dùng làm phương án dự phòng khi biến chính chưa được đặt. |
| `OMNIROUTE_PUBLIC_URL` | _(chưa đặt)_ | `open-sse/utils/kieTask.ts` | Origin công khai được dùng để tạo các URL callback bất đồng bộ. Phương án dự phòng có mức ưu tiên thấp nhất cho các callback kie.ai; cũng được dùng làm URL công khai chung cho các relay khác. |
| `OMNIROUTE_CROF_USAGE_URL` | `https://crof.ai/usage_api/` | `open-sse/services/usage.ts` | Endpoint tra cứu hạn ngạch CrofAI được trang Usage sử dụng. Ghi đè cho các relay / fixture kiểm thử. |
| `OMNIROUTE_CLINEPASS_USAGE_URL` | `https://api.cline.bot/api/v1/users/me/plan/usage-limits` | `open-sse/services/usage/clinepass.ts` | Endpoint hạn ngạch 5 giờ / hằng tuần / hằng tháng của ClinePass được trang Usage sử dụng. Ghi đè cho các relay / fixture kiểm thử. |
| `OMNIROUTE_OPENCODE_QUOTA_URL` | `https://opencode.ai/zen/go/v1/usage` | `open-sse/services/opencodeQuotaFetcher.ts` | Endpoint mức sử dụng OpenCode Go chính thức được xác thực bằng khóa API và được trang Usage sử dụng. Ghi đè cho các relay / fixture kiểm thử. |
| `OPENCODE_SYNTHESIZE_CLI_HEADERS` | `true` | `open-sse/executors/opencode.ts` | Tổng hợp các header nhận dạng OpenCode CLI (User-Agent, x-opencode-client/project, UUID yêu cầu/phiên) trên các yêu cầu upstream opencode-go/zen mà máy khách không gửi, để Cloudflare chấp nhận chúng khi lưu lượng đi ra từ VPS (#6210/#5997). Được bật theo mặc định kể từ #10571; có thể tắt bằng `false`/`0`/`no`/`off`. |
| `OPENCODE_USER_AGENT` | `opencode/1.18.31` | `open-sse/utils/opencodeHeaders.ts` | User-Agent mặc định được sử dụng khi `OPENCODE_SYNTHESIZE_CLI_HEADERS` được bật và không đặt giá trị ghi đè `_USER_AGENT` riêng cho từng nhà cung cấp. Chỉ áp dụng cho các trình thực thi opencode. Với một yêu cầu không có khóa bị hệ thống thượng nguồn chặn, giá trị đã cấu hình nhưng không chứa `opencode/= 1.17>` sẽ được thay thế bằng giá trị mặc định này thay vì bị từ chối. |
| `OMNIROUTE_FORWARD_ATTRIBUTION` | `1` (bật) | `open-sse/utils/opencodeHeaders.ts` | Chuyển tiếp các header phân bổ ứng dụng máy khách (`x-session-id`, `x-title`, `http-referer`) đến các nhà cung cấp thượng nguồn, để yêu cầu bắt đầu bên trong một harness được liệt kê vẫn giữ nguyên danh tính khi đi qua router (các cổng nhà phát hành OpenRouter dựa vào các header này). `0`/`false`/`no`/`off` giữ lại danh tính của registry/toán tử và loại bỏ các giá trị do máy khách cung cấp. Các header tùy chỉnh do toán tử cấu hình luôn được ưu tiên hơn giá trị từ máy khách. |
| `OPENCODE_CLIENT` | `desktop` | `open-sse/executors/opencode.ts` | Giá trị cho header `x-opencode-client` được tổng hợp khi `OPENCODE_SYNTHESIZE_CLI_HEADERS` được bật. |
| `OPENCODE_PROJECT` | `global` | `open-sse/executors/opencode.ts` | Giá trị cho header `x-opencode-project` được tổng hợp khi `OPENCODE_SYNTHESIZE_CLI_HEADERS` được bật. |
| `OMNIROUTE_EGRESS_IP_LOCK_PROVIDERS` | _(chưa đặt)_ | `open-sse/config/providerErrorRules.ts` | Tập hợp nhà cung cấp có hiệu lực mà lỗi thượng nguồn của họ được phân nhóm theo IP đầu ra (một lỗi 429 sẽ tạm dừng mọi kết nối cùng nhóm dùng chung IP đó). Khi chưa đặt, sử dụng giá trị mặc định của gói miễn phí là `opencode,opencode-go,opencode-cli`; `none`/`off`/`false`/`0` vô hiệu hóa hoàn toàn cơ chế liên đới này; danh sách phân tách bằng dấu phẩy sẽ thay thế tập hợp đó. Các gói trả phí được phân nhóm theo tài khoản ở thượng nguồn và có thể vô hiệu hóa cơ chế này một cách an toàn (#9611). |
| `OMNIROUTE_EGRESS_QUOTA_ROTATION_PROVIDERS` | _(chưa đặt)_ | `open-sse/config/providerErrorRules.ts` | Phạm vi xoay vòng đầu ra khi hạn ngạch bị từ chối. Khi chưa đặt, một thành viên của nhóm chỉ bị tạm loại sau lỗi 429 đối với họ nhà cung cấp được phân nhóm theo IP nêu trên; `all` mở rộng thao tác ghi đó đến mọi nhà cung cấp, để khi nhận được giới hạn tốc độ qua một thành viên, lần chọn tiếp theo sẽ sử dụng đầu ra ở nơi khác. Mọi giá trị ngoài `all` đều bị bỏ qua. Yêu cầu `PROXY_SKIP_RECENTLY_FAILED` (được bật theo mặc định). Kho lưu trữ được định danh theo địa chỉ đầu ra, không phải theo (nhà cung cấp, địa chỉ), nên lỗi 429 được mở rộng phạm vi sẽ tạm dừng thành viên đó đối với mọi nhà cung cấp cho đến khi hết thời hạn (5 phút, tăng gấp đôi lên 15 phút). Được đọc theo từng kết quả phản hồi, vì vậy thay đổi sẽ có hiệu lực mà không cần khởi động lại. |
| `OPENCODE_FREE_TIER_REQUEST_CONTRACT` | _(chưa đặt)_ | `open-sse/executors/opencodeFreeTierContract.ts` | Đặt thành `off` để ngừng điều chỉnh phần thân của các yêu cầu OpenCode không có khóa (cờ truyền phát trực tiếp và danh sách công cụ). Các header vẫn được áp dụng. Được đọc theo từng yêu cầu, vì vậy thay đổi có hiệu lực ngay lập tức. |
| `OPENCODE_FREE_TIER_PLACEHOLDER_TOOLS` | _(chưa đặt)_ | `open-sse/executors/opencodeFreeTierContract.ts` | Các tên công cụ phân tách bằng dấu phẩy để khai báo trong một yêu cầu OpenCode không có khóa và không chứa công cụ nào, khi chưa quan sát thấy công cụ nào cho mô hình đó. Giá trị rỗng sẽ dùng một công cụ giữ chỗ duy nhất mà mô hình được yêu cầu không gọi. Tối đa 32 mục, `[A-Za-z_][A-Za-z0-9_-]{0,63}`; các mục không hợp lệ sẽ bị bỏ qua. |
| `OMNIROUTE_OLLAMA_CLOUD_USAGE_URL` | `https://ollama.com/settings` | `open-sse/services/usage.ts` | URL cài đặt Ollama Cloud dùng để thu thập hạn ngạch. Ghi đè cho các relay / fixture kiểm thử. |
| `OMNIROUTE_OLLAMA_CLOUD_BALANCE_URL` | `https://ollama.com/api/balance` | `open-sse/services/ollamaCloudBalance.ts` | Điểm cuối số dư thượng nguồn Ollama Cloud được ghi trong tài liệu (`GET https://ollama.com/api/balance`, `Authorization: Bearer `). Được đọc một lần khi tải mô-đun. Được ưu tiên sử dụng để lấy hạn ngạch Ollama Cloud khi kết nối có khóa API; trình thu thập cookie từ trang cài đặt vẫn được dùng làm phương án dự phòng. Ghi đè cho các relay / fixture kiểm thử. |
| `OLLAMA_USAGE_COOKIE` | _(chưa đặt)_ | `open-sse/services/usage.ts` | Cookie `__Secure-session` của Ollama Cloud được dùng để thu thập hạn ngạch từ trang cài đặt. Dữ liệu nhạy cảm; nên ưu tiên trường Dashboard theo từng kết nối khi cấu hình nhiều tài khoản. |
| `OLLAMA_CLOUD_USAGE_COOKIE` | _(chưa đặt)_ | `open-sse/services/usage.ts` | Biến môi trường cookie `__Secure-session` thay thế cho Ollama Cloud. Dữ liệu nhạy cảm; nên ưu tiên trường Dashboard theo từng kết nối khi cấu hình nhiều tài khoản. |
| `OMNIROUTE_OLLAMA_USAGE_COOKIE` | _(chưa đặt)_ | `open-sse/services/usage.ts` | Biến môi trường cookie `__Secure-session` thay thế của Ollama Cloud, được sử dụng trước các bí danh ngắn hơn. Đây là dữ liệu nhạy cảm; nên ưu tiên trường Dashboard riêng cho từng kết nối khi cấu hình nhiều tài khoản. |
| `OMNIROUTE_CODEWHISPERER_BASE_URL` | `https://codewhisperer.us-east-1.amazonaws.com` | `open-sse/services/usage.ts` | Điểm cuối giới hạn sử dụng của CodeWhisperer (AWS Kiro). Ghi đè để sử dụng relay / fixture kiểm thử. |
> [!IMPORTANT]
> Khi triển khai phía sau reverse proxy (nginx, Caddy), hãy đặt `NEXT_PUBLIC_BASE_URL` thành URL công khai ổn định của bạn (ví dụ: `https://omniroute.example.com`) khi callback OAuth hoặc liên kết công khai được tạo phải sử dụng hostname đó. Nếu không, callback OAuth có thể thất bại do redirect_uri không khớp và các liên kết công khai được tạo có thể trỏ đến origin nội bộ của container.
>
> Giữ `BASE_URL` dưới dạng URL loopback/container nội bộ cho các tác vụ giao tiếp giữa máy chủ với máy chủ. Không sử dụng `Origin` của trình duyệt hoặc hostname công khai cho các yêu cầu tự truy xuất nội bộ có mang thông tin xác thực.
>
> Các thao tác ghi trên dashboard đã xác thực không yêu cầu URL cơ sở công khai tĩnh: dashboard gửi các yêu cầu không an toàn cùng origin với token CSRF gắn với phiên. OmniRoute vẫn tập trung hóa việc xác thực origin công khai cho các tích hợp trình duyệt không qua dashboard: các biến môi trường URL công khai được khai báo tường minh sẽ được tin cậy trước; các header `Forwarded` / `X-Forwarded-*` thô sẽ bị bỏ qua trừ khi `OMNIROUTE_TRUST_PROXY` được bật và peer proxy trực tiếp được đánh dấu bằng token là đáng tin cậy. Không sử dụng cài đặt CORS để khắc phục các yêu cầu cùng origin của dashboard; CORS chỉ dành cho các client trình duyệt khác origin.
---
## 8. Proxy đầu ra (Outbound)
Định tuyến các lệnh gọi đến nhà cung cấp LLM upstream thông qua proxy HTTP hoặc SOCKS5 để kiểm soát lưu lượng đi ra (egress), định tuyến theo vị trí địa lý, hoặc che giấu địa chỉ IP.
`OMNIROUTE_UPSTREAM_HTTP2_ENABLED` mặc định là `true`. Đặt giá trị thành `false`, `0`, `no` hoặc
`off` để buộc sử dụng HTTP/1.1 trên các dispatcher của Undici trong `open-sse/utils/proxyDispatcher.ts`
và `open-sse/utils/proxyFetch.ts`: kết nối đi ra trực tiếp, proxy HTTP(S)/SOCKS, các relay, và
các lần thử lại bằng socket mới của chúng. Cách này vẫn giữ nguyên việc xác minh chứng chỉ TLS, xác thực
proxy, giới hạn kết nối và các thiết lập keep-alive. Hãy khởi động lại OmniRoute sau
khi thay đổi vì các dispatcher được lưu trong bộ nhớ đệm và các relay agent được tạo lúc khởi động.
Tùy chọn này không kiểm soát việc giả lập dấu vân tay TLS (TLS fingerprinting) của wreq hay các
transport riêng của từng nhà cung cấp.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ---------------------------------------- | ------------ | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ENABLE_SOCKS5_PROXY` | `true` | `open-sse/executors` | Bật agent proxy SOCKS5 cho các cuộc gọi upstream. Tắt bằng `false`. |
| `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` | `true` | Phía client | Nhận biết phía client về khả năng sẵn có của SOCKS5. |
| `PROXY_SKIP_RECENTLY_FAILED` | `true` | `src/shared/utils/featureFlags.ts` | Cờ tính năng bật mặc định (xem [FEATURE_FLAGS.md](./FEATURE_FLAGS.md); giá trị ghi đè từ DB của dashboard được ưu tiên). Các pool proxy và luân chuyển theo tài khoản ngừng phục vụ lại một thành viên vừa thất bại (thăm dò TCP bị từ chối, hoặc lỗi 429 qua nó) trong một khoảng thời gian tăng gấp đôi sau mỗi lần lặp lại, tới một giới hạn tối đa. `false` khôi phục cách chọn thông thường. |
| `SELECTOR_CONTROL_ALLOWLIST` | _(chưa đặt)_ | `src/lib/proxySubscription/selectorGuard.ts` | Danh sách cho phép các đích điều khiển selector của local-core ngoài loopback (các host hoặc IP phân tách bằng dấu phẩy/khoảng trắng, `*` mở LAN/private nhưng không bao giờ mở metadata/link-local). Loopback qua http/https được cho phép theo mặc định. Giá trị từ DB của dashboard được ưu tiên hơn biến này khi được đặt và không rỗng. |
| `PROXY_QUOTA_429_BASE_MS` | `300000` | `open-sse/utils/proxyRefusalMemory.ts` | Khoảng thời gian cơ sở (ms) của việc tạm loại bỏ do 429, tăng gấp đôi sau mỗi lần lặp lại. Đọc một lần khi khởi động. Giới hạn trong `1000..3600000`; nếu ngoài phạm vi hoặc không đọc được thì quay về giá trị mặc định kèm cảnh báo. |
| `PROXY_QUOTA_429_MAX_MS` | `900000` | `open-sse/utils/proxyRefusalMemory.ts` | Giới hạn tối đa (ms) của việc tạm loại bỏ do 429. Đọc một lần khi khởi động. Giới hạn trong `1000..3600000`; nếu ngoài phạm vi hoặc không đọc được thì quay về giá trị mặc định kèm cảnh báo. Khi giới hạn tối đa thấp hơn giá trị cơ sở, nó quay về giá trị mặc định. Giảm giới hạn tối đa cũng rút ngắn thời gian quên chuỗi lỗi: các mục bị xóa sau `2 x max` khi hết hạn. |
| `PROXY_POOL_SHARED_EGRESS_ORDER` | `false` | `src/shared/utils/featureFlags.ts` | Cờ tính năng phải bật thủ công (xem [FEATURE_FLAGS.md](./FEATURE_FLAGS.md); giá trị ghi đè từ DB của dashboard được ưu tiên). Với các nhà cung cấp có hạn ngạch được nhóm theo địa chỉ egress, xếp hạng một thành viên pool dùng chung địa chỉ egress quan sát được với một thành viên vừa bị từ chối ngay dưới các thành viên khỏe mạnh. Chỉ ảnh hưởng thứ tự, không bao giờ loại trừ. Cần `PROXY_SKIP_RECENTLY_FAILED`, vốn tạo ra tín hiệu từ chối mà nó đọc. |
| `PROXY_WEBHOOK_REBOUND_MS` | `300000` | `src/lib/proxyEvents/proxyTransitionBridge.ts` | Cửa sổ rebound (ms) giới hạn các cảnh báo webhook `proxy.set_aside` lặp lại cho mỗi thành viên pool để một loạt từ chối chỉ gửi một sự kiện. Đọc mỗi lần phát sự kiện. Giới hạn trong `1000..3600000`; nếu ngoài phạm vi hoặc không đọc được thì âm thầm quay về giá trị mặc định. |
| `HTTP_PROXY` | _(chưa đặt)_ | Chuẩn Node.js | Proxy HTTP cho các cuộc gọi upstream. |
| `HTTPS_PROXY` | _(chưa đặt)_ | Chuẩn Node.js | Proxy HTTPS cho các cuộc gọi upstream. |
| `ALL_PROXY` | _(chưa đặt)_ | Chuẩn Node.js | Proxy đa dụng (hỗ trợ `socks5://`). |
| `OMNIROUTE_PROXY_ECHO_URL` | _(unset)_ | `src/lib/proxyEchoTarget.ts` | Ghim mục tiêu echo-IP được dùng bởi các lần dò egress qua proxy về một URL duy nhất. Khi không được đặt, lần dò sẽ thử `api64.ipify.org` rồi `api4.ipify.org` để các tunnel chỉ có IPv4 không bị báo là đã chết (#9694). |
| `NO_PROXY` | _(unset)_ | Node.js standard | Danh sách hostname/IP phân tách bằng dấu phẩy sẽ bỏ qua proxy. |
| `OMNIROUTE_PROXY_DISPATCHER_CONNECTIONS` | `32` | `open-sse/utils/proxyDispatcher.ts` | Số socket đồng thời tối đa cho mỗi dispatcher proxy HTTP/SOCKS được cache. Các luồng SSE tồn tại lâu như Codex `/v1/responses` cần nhiều hơn một kết nối khi nhiều yêu cầu dùng chung một proxy cấp tài khoản. Các giá trị trên `256` sẽ bị giới hạn. |
| `SOCKS_HANDSHAKE_TIMEOUT_MS` | `10000` | `open-sse/utils/socksConnectorWithFamily.ts` | Thời gian chờ handshake (kết nối) SOCKS5 tính bằng ms. Hãy tăng giá trị này khi một host gateway residential duy nhất chịu mức đồng thời cao (ví dụ 100 yêu cầu đồng thời) — handshake thực tế có thể vượt quá 10 giây khi pool bị bão hòa dù proxy vẫn kết nối được, nếu không sẽ bị báo sai thành `[Proxy Fast-Fail] Proxy unreachable`. Giới hạn ở `120000`. |
| `PROXY_FAIL_OPEN` | `false` | `src/sse/handlers/chatHelpers.ts` | Khi đặt `false` (mặc định), một yêu cầu mà proxy được gán không phân giải được sẽ **bị từ chối (fail-closed)** thay vì quay về kết nối trực tiếp — ngăn rò rỉ IP thật. Đặt `true` để khôi phục hành vi fallback DIRECT cũ. |
| `ENABLE_TLS_FINGERPRINT` | `false` | `open-sse/executors` | Giả mạo TLS fingerprint bằng wreq-js (bắt chước Chrome 124). Chống lại việc chặn JA3/JA4. |
| `TLS_FINGERPRINT_PROVIDERS` | _(unset)_ | `open-sse/utils/proxyFetch.ts` | Danh sách cho phép provider phân tách bằng dấu phẩy cho định tuyến TLS qua proxy mới (`open-sse/utils/proxyFetch.ts`). TLS trực tiếp giữ nguyên hành vi cũ khi không được đặt; chỉ các provider này được định tuyến qua cầu fingerprint Chrome-124. Groq (`api.groq.com`) bị loại trừ ngay cả khi danh sách cho phép không được đặt, vì JA3 của Chrome kích hoạt Cloudflare 1010 trong khi undici gốc vẫn truy cập được API. |
| `OMNIROUTE_TURNSTILE_IGNORE_TLS_ERRORS` | `false` | `open-sse/services/claudeTurnstileSolver.ts` | Cho phép ngữ cảnh trình duyệt Playwright của Claude Turnstile bỏ qua lỗi chứng chỉ HTTPS. |
### Các tình huống
| Tình huống | Cấu hình |
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| **SOCKS5 qua SSH tunnel** | `ALL_PROXY=socks5://127.0.0.1:7890`, `ENABLE_SOCKS5_PROXY=true` |
| **HTTP proxy doanh nghiệp** | `HTTP_PROXY=http://proxy.corp.com:3128`, `HTTPS_PROXY=http://proxy.corp.com:3128`, `NO_PROXY=localhost,internal.corp.com` |
| **Chống fingerprint** | `ENABLE_TLS_FINGERPRINT=true` — yêu cầu `wreq-js` (đã bao gồm sẵn) |
| **Kiểm soát egress / không có truy cập trực tiếp** | Giữ `PROXY_FAIL_OPEN=false` (mặc định). Các yêu cầu sẽ thất bại hoàn toàn khi proxy không khả dụng thay vì rò rỉ qua kết nối trực tiếp. |
| **Cũ / dev — cho phép fallback trực tiếp** | `PROXY_FAIL_OPEN=true`. Khôi phục hành vi trước khi tăng cường bảo mật: dùng kết nối trực tiếp khi phân giải proxy thất bại. |
> **Lưu ý (bỏ qua xác thực NVIDIA — #3226):** Endpoint xác thực API-key của NVIDIA
> bị treo khi được định tuyến qua fetch đã vá proxy/TLS toàn cục (undici dispatcher → 504).
> `src/lib/providers/validation.ts::directHttpsRequest()` cố ý bỏ qua bản vá proxy
> cho riêng lần gọi xác thực đó bằng `safeOutboundFetch({ bypassProxyPatch: true })`.
> Đây là một ngoại lệ có phạm vi được ghi trong tài liệu — nó **không** ảnh hưởng đến egress của chat/usage.
> Việc bỏ qua này được ghim phạm vi bởi `tests/unit/proxy-bypass-scope-guard-3226.test.ts`.
---
## 9. Tích hợp công cụ CLI
Kiểm soát cách OmniRoute phát hiện và khởi chạy các sidecar CLI (Claude Code, Codex, v.v.).
| Biến | Mặc định | Tệp nguồn | Mô tả |
| --------------------------------- | -------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CLI_MODE` | `auto` | `src/shared/services/cliRuntime.ts` | `auto` = tìm trong PATH hệ thống; `manual` = chỉ dùng các đường dẫn chỉ định rõ ràng. |
| `CLI_EXTRA_PATHS` | _(chưa đặt)_ | `src/shared/services/cliRuntime.ts` | Các mục PATH bổ sung để tìm kiếm binary CLI (phân tách bằng dấu hai chấm). |
| `CLI_CONFIG_HOME` | _(chưa đặt)_ | `src/shared/services/cliRuntime.ts` | Ghi đè thư mục home để đọc cấu hình CLI (`~/.claude`, `~/.codex`). Phải là đường dẫn tuyệt đối và nằm trong home của tiến trình — **hoặc**, trong container, một đường dẫn bind-mount (đó là cách `/host-home` hoạt động). Mọi giá trị khác sẽ quay về thư mục home. |
| `CLI_ALLOW_CONFIG_WRITES` | `true` | `src/shared/services/cliRuntime.ts` | Cho phép OmniRoute ghi các tệp cấu hình CLI (làm mới token, dữ liệu phiên). Đặt thành `false` để mọi thao tác ghi cấu hình CLI thất bại với lỗi rõ ràng "writes disabled". |
| `CLI_CLAUDE_BIN` | `claude` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Claude CLI. |
| `CLI_CODEX_BIN` | `codex` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Codex CLI. |
| `CLI_DROID_BIN` | `droid` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Droid CLI. |
| `CLI_OPENCLAW_BIN` | `openclaw` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary OpenClaw CLI. |
| `CLI_CURSOR_BIN` | `agent`, rồi `cursor` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Cursor agent. Nếu không đặt, quá trình phát hiện sẽ thử `agent` trước rồi quay về `cursor`. |
| `CLI_CLINE_BIN` | `cline` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Cline CLI. |
| `CLI_5DIVE_BIN` | `5dive` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary 5dive CLI. |
| `CLI_5DIVE_STATE_DIR` | `/var/lib/5dive` | `src/shared/services/cliRuntime.ts` | Thư mục state hệ thống của 5dive (các profile xác thực thuộc sở hữu root); tương ứng với giá trị mặc định STATE_DIR của chính 5dive. |
| `CLI_CONTINUE_BIN` | `cn` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Continue CLI. |
| `CLI_QODER_BIN` | `qodercli` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Qoder CLI. |
| `CLI_QWEN_BIN` | `qwen` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Qwen Code CLI. |
| `CLI_AIDER_BIN` | `aider` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Aider CLI. |
| `CLI_GOOSE_BIN` | `goose` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Goose CLI. |
| `CLI_GEMINI_BIN` | `gemini` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Google Gemini CLI — chỉ dùng cho việc phát hiện/kiểm tra sức khỏe phía server; `omniroute run gemini` phân giải binary `gemini` từ PATH hệ thống. |
| `CLI_KILO_BIN` | `kilocode` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Kilo Code CLI. |
| `CLI_OPENCODE_BIN` | `opencode` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary OpenCode CLI. |
| `CLI_HERMES_BIN` | `hermes` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Hermes. Dùng chung bởi cả hai mục catalog (`hermes` và `hermes-agent`). |
| `CLI_FORGE_BIN` | `forge` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary ForgeCode CLI. |
| `CLI_JCODE_BIN` | `jcode` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary jcode CLI. |
| `CLI_DEEPSEEK_TUI_BIN` | `deepseek-tui` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary DeepSeek TUI. |
| `CLI_CODEWHALE_BIN` | `codewhale` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary CodeWhale CLI. |
| `CLI_SMELT_BIN` | `smelt` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Smelt CLI. |
| `CLI_PI_BIN` | `pi` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Pi (pi-coding-agent). |
| `CLI_CRUSH_BIN` | `crush` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Crush CLI. |
| `CLI_OMP_BIN` | `omp` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary agent Oh My Pi (`omp`). |
| `CLI_LETTA_BIN` | `letta` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Letta CLI. |
| `CLI_PRIME_AGENT_BIN` | `prime-agent` | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Prime Agent (Prime Intellect). |
| `CLI_WINDSURF_BIN` | _(không có)_ | `src/shared/services/cliRuntime.ts` | Đường dẫn tùy chỉnh tới binary Windsurf. Windsurf **không có lệnh mặc định** — việc phát hiện binary sẽ bị vô hiệu hóa cho đến khi biến này được thiết lập. |
| `CLI_DEVIN_BIN` | `devin` | `open-sse/executors/devin-cli.ts` | Đường dẫn tùy chỉnh tới binary Devin CLI (v3.8.0). Được sử dụng bởi executor Windsurf/Devin. |
| `DEVIN_DESKTOP_VERSION` | `3.6.27` | `open-sse/executors/devin-desktop.ts` | `ide_version` của Devin Desktop. Giá trị ghi đè phải dùng định dạng `x.y.z`; giá trị không hợp lệ sẽ quay về giá trị mặc định đã được xác minh. |
| `DEVIN_DESKTOP_EXTENSION_VERSION` | `1.48.2` | `open-sse/executors/devin-desktop.ts` | `extension_version` của Codeium/language-server đi kèm, khác với `ide_version` của Desktop. Giá trị ghi đè phải dùng định dạng `x.y.z`; giá trị không hợp lệ sẽ dùng giá trị mặc định đi kèm. |
| `CLI_DEVIN_AGENTIC_BIN` | `devin` | `open-sse/executors/devin-cli-agentic.ts` | Ghi đè Devin CLI chỉ dành cho agentic bridge. Executor chỉ chấp nhận upstream ACP stdio cục bộ. |
| `DEVIN_AGENTIC_HOME` | _(bắt buộc)_ | `open-sse/executors/devin-cli-agentic.ts` | Thư mục home tuyệt đối, cô lập cho tiến trình con Devin agentic; các đường dẫn bridge được chấp nhận là `/home/bridge` và các đường dẫn `.sandbox` cục bộ theo tác vụ (trên Windows, `C:\...\.sandbox\...`). |
| `DEVIN_AGENTIC_ACP_TIMEOUT_MS` | `120000` | `open-sse/executors/devin-cli-agentic.ts` | Thời lượng tối đa của một lượt Devin ACP trước khi bridge chấm dứt tiến trình con và trả về lỗi timeout rõ ràng. |
| `DEVIN_BRIDGE_MODEL` | `devin-cli-agentic/swe-1-7` | `docker/devin-bridge/compose.yml` | Bí danh model Claude Code chính cho bridge cô lập. Harness trực tiếp sẽ thay thế ví dụ bằng một model do tài khoản Devin hiện tại trả về. |
| `DEVIN_BRIDGE_SONNET_MODEL` | `DEVIN_BRIDGE_MODEL` | `docker/devin-bridge/compose.yml` | Bí danh bridge cô lập được dùng khi Claude Code yêu cầu model Sonnet mặc định của nó. |
| `DEVIN_BRIDGE_OPUS_MODEL` | `DEVIN_BRIDGE_MODEL` | `docker/devin-bridge/compose.yml` | Bí danh bridge cô lập được dùng khi Claude Code yêu cầu model Opus mặc định của nó. |
| `DEVIN_BRIDGE_HAIKU_MODEL` | `DEVIN_BRIDGE_MODEL` | `docker/devin-bridge/compose.yml` | Bí danh bridge cô lập được dùng khi Claude Code yêu cầu model Haiku mặc định của nó. |
| `DEVIN_BRIDGE_SUBAGENT_MODEL` | `DEVIN_BRIDGE_MODEL` | `docker/devin-bridge/compose.yml` | Bí danh bridge cô lập được dùng cho các subagent của Claude Code. |
| `DEVIN_SEAT_API_URL` | `https://server.codeium.com` | `open-sse/services/usage/devinCli.ts` | Ghi đè tùy chọn cho API quản lý seat của Codeium được sử dụng bởi quota Devin CLI (`GetUserStatus`). |
| `AUGGIE_BIN` | `auggie` | `open-sse/executors/auggie.ts` | Ghi đè đường dẫn tuyệt đối cho binary Augment (Auggie) CLI được sử dụng bởi provider `auggie` cục bộ. Quay về `CLI_AUGGIE_BIN`, sau đó tìm kiếm trong PATH. |
| `CLI_AUGGIE_BIN` | `auggie` | `open-sse/executors/auggie.ts` | Ghi đè bí danh cho đường dẫn binary Augment (Auggie) CLI (được kiểm tra sau `AUGGIE_BIN`). |
| `ZCODE_BIN` | `zcode` | `open-sse/executors/zcode.ts` | Binary được sử dụng cho stdio client của provider `zcode` cục bộ. Quay về `zcode` trên PATH. |
| `ZCODE_ARGS` | — | `open-sse/executors/zcode.ts` | Mảng JSON (≤16 chuỗi) các tham số bổ sung được truyền cho binary `zcode` khi khởi chạy qua `cliTools`. |
| `ZCODE_CWD` | `process.cwd()` | `open-sse/executors/zcode.ts` | Thư mục làm việc cho subprocess ZCode app-server. |
| `ZCODE_PROVIDER_ID` | `builtin:zai-coding-plan` | `open-sse/executors/zcode.ts` | Ghi đè cho provider id được gửi đến app-server. |
| `ZCODE_SERVER_RUNTIME_ROOT` | `~/.zcode/server` | `open-sse/executors/zcode.ts` | Thư mục gốc của runtime ZCode app-server (nơi chứa `node` và `zcode-server.cjs` đi kèm). |
| `ZCODE_SERVER_NODE` | `/node` | `open-sse/executors/zcode.ts` | Node executable được sử dụng để chạy ZCode app-server. |
| `ZCODE_SERVER_ENTRY` | `/zcode-server.cjs` | `open-sse/executors/zcode.ts` | Script entry của app-server được sử dụng để chạy ZCode server. |
| `ZCODE_STARTUP_TIMEOUT_MS` | `10000` | `open-sse/executors/zcode.ts` | Thời gian chờ khởi động (ms) trước khi việc khởi chạy ZCode app-server bị coi là thất bại. |
| `ZCODE_RPC_TIMEOUT_MS` | `30000` | `open-sse/executors/zcode.ts` | Thời gian chờ RPC (ms) cho mỗi request tới ZCode app-server. |
| `ZCODE_TURN_TIMEOUT_MS` | `120000` | `open-sse/executors/zcode.ts` | Thời lượng tối đa (ms) của một lượt ZCode trước khi supervisor hết thời gian chờ. |
| `ZCODE_POLL_INTERVAL_MS` | `250` | `open-sse/executors/zcode.ts` | Khoảng thời gian polling (ms) cho việc hoàn thành lượt ZCode. |
| `HERMES_HOME` | `~/.hermes` | `src/lib/cli-helper/config-generator/hermesHome.ts` | Thư mục home của Hermes Agent nơi OmniRoute đọc/ghi cấu hình Hermes CLI. Khớp với biến môi trường mà trình cài đặt Hermes PowerShell thiết lập trên Windows (`%LOCALAPPDATA%\hermes`). |
### Tự động đồng bộ hóa CLI Profile
Các feature flag này là opt-in và mặc định tắt. Chúng cũng có thể được bật/tắt từ
dashboard CLI Code.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------- | -------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `OMNIROUTE_AUTO_SYNC_CODEX_PROFILES` | `false` | `src/shared/constants/featureFlagDefinitions.ts` | Sau khi đồng bộ hóa model của provider, tự động ghi lại các tệp profile `~/.codex/*.config.toml` từ catalog trực tiếp. Yêu cầu `CLI_ALLOW_CONFIG_WRITES`; không bao giờ thay đổi cấu hình Codex đang hoạt động/mặc định, auth, cài đặt Codex-lb, hoặc lựa chọn provider. |
| `OMNIROUTE_AUTO_SYNC_CLAUDE_PROFILES` | `false` | `src/shared/constants/featureFlagDefinitions.ts` | Sau khi đồng bộ hóa model của provider, tự động ghi lại các tệp profile Claude Code `~/.claude/profiles//settings.json` từ catalog trực tiếp. Yêu cầu `CLI_ALLOW_CONFIG_WRITES`; không bao giờ thay đổi cấu hình Claude đang hoạt động/mặc định, auth, hoặc lựa chọn provider. |
### Ví dụ Docker
```bash
# Mount các binary của host vào container và cho OmniRoute biết chúng nằm ở đâu:
CLI_EXTRA_PATHS=/host-cli/bin
CLI_CONFIG_HOME=/host-home
CLI_ALLOW_CONFIG_WRITES=true
CLI_CLAUDE_BIN=/host-cli/bin/claude
```
`CLI_CONFIG_HOME` chỉ có hiệu lực khi đường dẫn thực sự được bind-mount từ
máy chủ — hãy kết hợp nó với các mount như `~/.codex:/host-home/.codex:rw` (xem
profile `host` trong `docker-compose.yml`). Đường dẫn không nằm trong thư mục home
của người dùng container và cũng không phải là bind mount sẽ bị bỏ qua, vì dữ liệu
ghi vào đó sẽ bị mất khi container được tạo lại.
Image chạy với `USER node`, vì vậy `/root` không được mount **không** phải là
một giá trị ghi đè hợp lệ.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ---------------------------------------- | ----------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_CONTAINER` | _(tự động)_ | `src/shared/utils/containerEnv.ts` | Bắt buộc bật (`1`/`true`) hoặc tắt (`0`/`false`) việc phát hiện container. Chỉ cần thiết trên các runtime mà tính năng tự động phát hiện bỏ sót. |
| `OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE` | `false` | `src/shared/services/cliRuntime.ts` | Vẫn cho phép ghi cấu hình công cụ CLI vào đường dẫn container chưa được mount. Tương đương ở CLI là `--allow-container-write`. |
| `DOCKER_UPDATE_TRIGGER_FILE` | chưa đặt | `src/lib/system/autoUpdate.ts` | Chỉ dành cho image Docker: nút **Update Now** trên dashboard ghi một yêu cầu JSON vào tệp này (phải nằm trong `DATA_DIR`) để một trình theo dõi phía máy chủ pull image và tạo lại container. Xem [Hướng dẫn Docker](../guides/DOCKER_GUIDE.md#dashboard-updates-in-docker). |
### Các trợ lệnh của binary CLI (`omniroute`)
Các biến này điều chỉnh hành vi của chính binary CLI `omniroute` (không phải việc
phát hiện sidecar ở trên).
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------- | --------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_LANG` | _(hệ thống)_ | `bin/cli/i18n.mjs` | Ép ngôn ngữ đầu ra của CLI. Locale theo BCP-47 (ví dụ: `en`, `pt-BR`). Ghi đè các biến môi trường locale của hệ thống (LC_ALL, LC_MESSAGES). |
| `OMNIROUTE_SHOW_LOG` | _(chưa đặt)_ | `bin/cli/runtime/processSupervisor.mjs` | Đặt thành `1` để chuyển tiếp stdout/stderr của server ra terminal ở chế độ supervised. Tương đương với cờ `--log` của `omniroute serve`. |
| `OMNIROUTE_CLI_TOKEN` | _(chưa đặt)_ | `bin/cli/api.mjs` | Token xác thực máy được chèn vào header `x-omniroute-cli-token`. Tự động tạo trong task 8.12. |
| `GEMINI_CLI_HOME` | _(chưa đặt)_ | `bin/cli/commands/setup-gemini.mjs` | Thư mục gốc home của Gemini được lưu trữ lâu dài; lần chạy một lần (one-shot) sử dụng một home tạm thời được cô lập. |
| `OMNIROUTE_CHILD_SIGNAL_TIMEOUT_MS` | `5000` | `bin/cli/commands/run.mjs` | Thời gian chờ (tính bằng mili giây) trước khi buộc dừng một tiến trình con CLI đã nhận tín hiệu. |
| `OMNIROUTE_CLI_SKIP_DEFAULT_DATA_ENV` | _(chưa đặt)_ | `bin/omniroute.mjs` | Đặt thành 1 cùng với DATA_DIR được chỉ định rõ ràng để bỏ qua tệp môi trường thư mục dữ liệu của người dùng mặc định. |
| `OMNIROUTE_SYNC_TOKEN` | _(chưa đặt)_ | `bin/cli/commands/sync.mjs` | Token đồng bộ cho `omniroute sync bundle` (`GET /api/sync/bundle` chỉ chấp nhận token đồng bộ, không chấp nhận API key). Tương đương với `--token`. |
| `OMNIROUTE_HTTP_TIMEOUT_MS` | `30000` | `bin/cli/api.mjs` | Thời gian chờ HTTP cho mỗi lần thử (ms) đối với các yêu cầu từ CLI → server. |
| `OMNIROUTE_READY_TIMEOUT_MS` | `60000` | `bin/cli/utils/pid.mjs` | Thời gian tối đa (ms) mà CLI chờ endpoint sức khỏe của server trước khi in cảnh báo hết thời gian chờ. Hữu ích khi khởi động nguội chậm (ví dụ: Windows). Cũng có thể đặt qua `--ready-timeout`. |
| `OMNIROUTE_VERBOSE` | `0` | `bin/cli/api.mjs` | Đặt thành `1` để in thông tin chẩn đoán retry/backoff ra stderr trong khi chạy các lệnh CLI. |
| `OMNIROUTE_PLUGIN_PATH` | _(chưa đặt)_ | `bin/cli/plugins.mjs` | Thư mục tùy chỉnh để CLI khám phá plugin (các gói `omniroute-cmd-*`). Mặc định là `~/.omniroute/plugins/` khi chưa đặt. Chỉ dành cho CLI — nó không bao giờ chạm tới trình quét plugin phía server, vốn được chỉ định bởi `OMNIROUTE_PLUGINS_DIR` (mục 2). |
| `OMNIROUTE_NO_UPDATE_NOTIFIER` | _(chưa đặt)_ | `bin/omniroute.mjs` | Tắt thông báo cập nhật CLI khi tiến trình kết thúc nếu được đặt thành bất kỳ giá trị nào khác rỗng. Thông báo này vẫn bị tắt một cách độc lập trong CI, chế độ quiet và các chế độ đầu ra không phải văn bản. |
| `OMNIROUTE_DOCTOR_LIVENESS_URL` | _(suy ra)_ | `bin/cli/commands/doctor.mjs` | URL liveness được `omniroute doctor` thăm dò. Tùy chọn `livenessUrl` được truyền qua mã sẽ được ưu tiên; nếu không, giá trị này được sử dụng nguyên văn. Khi chưa đặt, CLI tự suy ra endpoint `/api/health/degradation` của dashboard cục bộ. |
| `OMNIROUTE_PROVIDER_CATALOG_PATH` | `src/shared/constants/providers/` | `bin/cli/provider-catalog.mjs` | Đường dẫn danh mục provider được các lệnh provider của CLI sử dụng. Tùy chọn `catalogPath` được truyền qua mã sẽ được ưu tiên. Đường dẫn tuyệt đối được dùng nguyên trạng; đường dẫn tương đối được phân giải từ thư mục gốc của dự án. Khi chưa đặt, CLI sử dụng thư mục hằng số provider, với tệp `providers.ts` cũ làm phương án dự phòng. |
| `OMNIROUTE_PROVIDER_TEST_MODEL` | _(mặc định của provider)_ | `bin/cli/provider-test.mjs` | Model dự phòng toàn cục cho các bài kiểm tra kết nối provider của CLI. Thứ tự ưu tiên là: model của kết nối đã cấu hình, ghi đè model theo từng provider, giá trị này, rồi đến model kiểm tra tích hợp sẵn của provider. |
---
## 10. Tích hợp Agent nội bộ & MCP
| Variable | Default | Source File | Description |
| ----------------------------------------------- | --------------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_BASE_URL` | auto-detect | `open-sse/mcp-server/server.ts` | URL rõ ràng để các công cụ MCP/A2A kết nối tới OmniRoute. Ghi đè tính năng tự động phát hiện localhost. |
| `OMNIROUTE_API_KEY` | _(chưa thiết lập)_ | MCP/A2A modules | Khóa API cho các lệnh gọi công cụ MCP nội bộ và skill A2A. |
| `OMNIROUTE_API_KEY_ID` | _(chưa thiết lập)_ | `open-sse/mcp-server/audit.ts` | ID khóa dùng để ghi nhận nguồn trong nhật ký audit của MCP. |
| `ROUTER_API_KEY` | _(chưa thiết lập)_ | Cũ (legacy) | Bí danh cũ của `OMNIROUTE_API_KEY`. |
| `OMNIROUTE_A2A_HISTORY_RETENTION_DAYS` | `30` | `src/lib/a2a/taskManager.ts` | Số ngày lưu giữ lịch sử tác vụ A2A trong cơ sở dữ liệu cục bộ trước khi tiến trình dọn dẹp hằng ngày xóa một hàng. Nếu không thiết lập, không phải số, hoặc `<= 0` thì quay về `30`. |
| `OMNIROUTE_A2A_MEMORY_HITS` | `1` | `src/lib/a2a/taskExecution.ts` | Công tắc tắt (kill-switch) cho tính năng quan sát memory-hits của A2A. Đặt thành `0` để bỏ qua hoàn toàn bước tra cứu gợi nhớ bộ nhớ cho một tác vụ; mọi giá trị khác (kể cả khi không thiết lập) đều giữ tính năng này được bật. |
| `OMNIROUTE_ISSUE_AGENT_ENABLED` | `false` | `src/app/api/issue-agent/runs/route.ts` | Bật endpoint recorded-triage của Issue Agent ở chế độ offline/cục bộ. Giữ ở trạng thái tắt trừ khi bạn cố tình chạy các quy trình recorded-triage cục bộ. |
| `OMNIROUTE_ISSUE_AGENT_TIMEOUT_MS` | _(chưa thiết lập)_ | `src/lib/issueAgent/execution.ts` | Thời gian chờ (ms) cho một lần chạy recorded-triage của Issue Agent. Được giới hạn ở mức tối đa nội bộ; quay về giá trị mặc định tích hợp sẵn khi không thiết lập hoặc không hợp lệ. |
| `OMNIROUTE_CONTEXT` | _(context đang hoạt động)_ | `bin/cli/program.mjs`, `bin/cli/api.mjs` | Context/profile chế độ remote của CLI cho các lệnh `omniroute`; ghi đè context đang hoạt động trong kho lưu trữ contexts cục bộ. Tương đương với `--context `. |
| `OMNIROUTE_CONTEXT_KEYCHAIN_DISABLED` | `0` | `bin/cli/contexts.mjs` | Tắt backend OS-keychain tùy chọn `keytar` dùng cho thông tin xác thực context của CLI. Khi được bật, thông tin xác thực vẫn được lưu trong `config.json` với quyền `0600` và CLI sẽ đưa ra cảnh báo fallback một lần duy nhất; dành cho việc vận hành headless/container một cách có chủ đích. |
| `OMNIROUTE_MCP_ENFORCE_SCOPES` | `false` | `open-sse/mcp-server/server.ts` | Áp dụng cơ chế kiểm soát truy cập dựa trên scope cho các lệnh gọi công cụ MCP. |
| `OMNIROUTE_MCP_SCOPES` | _(tất cả)_ | `open-sse/mcp-server/server.ts` | Danh sách scope phân tách bằng dấu phẩy: `admin`, `combos`, `health`, `models`, `routing`, `budget`, `metrics`, `pricing`, `memory`, `skills`. |
| `OMNIROUTE_MCP_COMPRESS_DESCRIPTIONS` | `false` | `open-sse/mcp-server/descriptionCompressor.ts` | Nén mô tả công cụ MCP trước khi tuần tự hóa manifest. Giá trị bật: `1`, `true`, `on`. |
| `OMNIROUTE_MCP_DESCRIPTION_COMPRESSION` | `rtk` | `open-sse/mcp-server/descriptionCompressor.ts` | Thuật toán/profile nén. Giá trị tắt: `0`, `false`, `off`. |
| `OMNIROUTE_MCP_FETCH_TIMEOUT_MS` | `10000` | `open-sse/mcp-server/fetchTimeout.ts` | Ngân sách thời gian chờ (ms) cho các lượt đọc quản lý nội bộ của MCP server (health, resilience, combos, quota, usage). |
| `OMNIROUTE_MCP_UPSTREAM_TIMEOUT_MS` | `60000` | `open-sse/mcp-server/fetchTimeout.ts` | Ngân sách hủy (ms) cho các hop MCP phải chờ một provider (`route_request`, `web_search`, `web_fetch`). |
| `OMNIROUTE_CORPUS_CACHE_SIZE` | `5` | `src/lib/localCorpus/configured.ts` | Số lượng tối đa các instance chỉ mục corpus cục bộ được cache trong bộ nhớ (LRU, một instance cho mỗi thư mục gốc đã lập chỉ mục). Bị giới hạn tối thiểu là `1`. |
| `MODEL_SYNC_INTERVAL_HOURS` | `6` | `src/shared/services/modelSyncScheduler.ts` | Chu kỳ đồng bộ danh mục model, tính bằng giờ. |
| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | `src/lib/usage/providerLimits.ts` | Chu kỳ poll rate-limit và quota của provider. |
| `PROVIDER_LIMITS_SYNC_SPACING_MS` | `1500` | `src/lib/usage/providerLimits.ts` | Khoảng cách (ms) giữa các lần fetch quota OAuth liên tiếp trong một đợt đồng bộ hàng loạt; các kết nối OAuth được fetch lần lượt để tránh gây burst lên upstream. `0` để tắt (chạy đồng thời). |
| `OMNIROUTE_QUOTA_FETCH_MIN_INTERVAL_MS` | `250` | `open-sse/services/quotaFetchThrottle.ts` | Khoảng thời gian tối thiểu (ms) giữa các lần fetch quota upstream liên tiếp trên đường dẫn preflight/monitor theo từng request; giãn cách các cuộc gọi mạng đồng thời để nhiều tài khoản trên cùng một IP không gây burst lên upstream. Được tích hợp vào các bộ fetch quota của Codex (`/wham/usage`), DeepSeek, Bailian (cả hai điểm fetch), OpenCode và Crof (#6009, #6911). Đường dẫn dispatch chung `usage.ts::getUsageForProvider` (github/glm/minimax/nanogpt/xai/v.v.) chưa được hỗ trợ — đang được theo dõi riêng. Cache hit không bị ảnh hưởng. `0` để tắt; giới hạn trong khoảng `0..60000`. |
| `OMNIROUTE_QUOTA_FETCH_JITTER_MS` | `120` | `open-sse/services/quotaFetchThrottle.ts` | Khoảng giãn ngẫu nhiên bổ sung cho mỗi request (ms), được lấy mẫu tại mỗi lần fetch quota upstream đã đặt lịch. Mặc định là 120; giới hạn `0..60000`; `0` chỉ loại bỏ jitter. Đặt `OMNIROUTE_QUOTA_FETCH_MIN_INTERVAL_MS=0` để tắt toàn bộ cơ chế throttle. Jitter không đảm bảo ngăn được việc bị upstream cấm. |
| `PROVIDER_LIMITS_POST_USAGE_REFRESH_DELAY_MS` | `5000` | `src/lib/usage/providerLimits.ts` | Độ trễ (ms) trước khi làm mới giới hạn provider sau một sự kiện sử dụng thực tế, nhằm cho API quota upstream có thời gian ghi nhận mức tiêu thụ. |
| `OMNIROUTE_LOGIN_BROWSER_PATH` | tự động phát hiện | `open-sse/services/adobeFireflyBrowserLogin.ts` | Đường dẫn tuyệt đối đến file thực thi Chrome hoặc Edge của hệ thống, dùng cho việc đăng nhập Adobe Firefly tương tác và gia hạn off-screen. |
| `ADOBE_FIREFLY_BROWSER_REFRESH` | bật | `open-sse/services/adobeFireflySession.ts` | Giữ trạng thái IMS và browser-risk luôn mới bằng các phiên Chrome CDP theo phạm vi tài khoản. Đặt thành `0` để tắt gia hạn trình duyệt. |
| `ADOBE_FIREFLY_SESSION_DISK` | bật | `open-sse/services/adobeFireflySession.ts` | Lưu trữ các phiên Adobe đã được sửa chữa trong `DATA_DIR` qua các lần khởi động lại tiến trình. Đặt thành `0` để chỉ giữ phiên trong bộ nhớ. |
| `ADOBE_FIREFLY_MIN_SUBMIT_GAP_MS` | `12000` | `open-sse/services/adobeFireflySession.ts` | Khoảng cách tối thiểu tính bằng mili giây giữa các lần gửi generate của Adobe Firefly; `0` để tắt giãn cách. |
| `ADOBE_FIREFLY_BATCH_EXTRA_GAP_MS` | `15000` | `open-sse/services/adobeFireflySession.ts` | Khoảng thời gian nghỉ bổ sung tính bằng mili giây sau mỗi lần gửi Adobe thành công thứ ba. |
| `ADOBE_FIREFLY_SUBMIT_BASE_DELAY_MS` | `8000` | `open-sse/services/adobeFireflyClient.ts` | Thời gian backoff cơ bản tính bằng mili giây sau các phản hồi 408 tạm thời từ Adobe; kết hợp với giãn cách gửi trong tối đa năm lần thử. |
| `OMNIROUTE_DISABLE_BACKGROUND_SERVICES` | `false` | `src/instrumentation-node.ts` | Tắt tất cả các dịch vụ nền (đồng bộ, định giá, làm mới model). Hữu ích cho CI/test. |
| `OMNIROUTE_HEADLESS` | _(chưa đặt)_ | `src/lib/system/headless.ts` | Khởi động chỉ với proxy engine: bỏ qua các hệ thống con tùy chọn, `/dashboard` → 404. Tương đương với `omniroute serve --headless`. Xem [HEADLESS.md](../guides/HEADLESS.md). |
| `OMNIROUTE_ENABLE_RUNTIME_BACKGROUND_TASKS` | _(chưa đặt)_ | `src/lib/config/runtimeSettings.ts` | Buộc bật các tác vụ nền khi phát hiện đang chạy kiểm thử tự động. Đặt `1` để ghi đè heuristic phát hiện kiểm thử. |
| `OMNIROUTE_BUDGET_RESET_JOB_INTERVAL_MS` | `600000` | `src/lib/jobs/budgetResetJob.ts` | Chu kỳ kiểm tra đặt lại ngân sách (ms). Giá trị tối thiểu `10000`. |
| `OMNIROUTE_CONNECTION_RECOVERY_INTERVAL_MS` | `60000` | `src/lib/quota/connectionRecovery.ts` | Chu kỳ khôi phục chủ động thời gian chờ (cooldown) kết nối (ms): xác thực lại các kết nối mà `rate_limited_until` tạm thời đã hết hạn, nằm ngoài hot path của yêu cầu. Giá trị tối thiểu `5000`. |
| `OMNIROUTE_DISABLE_CONNECTION_RECOVERY` | `false` | `src/lib/quota/connectionRecovery.ts` | Tắt bộ lập lịch khôi phục chủ động cooldown kết nối (khôi phục lười trong `getProviderCredentials` vẫn được áp dụng). |
| `OMNIROUTE_REASONING_CACHE_CLEANUP_INTERVAL_MS` | `1800000` | `src/lib/jobs/reasoningCacheCleanupJob.ts` | Chu kỳ dọn dẹp bộ nhớ đệm suy luận (ms). Giá trị tối thiểu `60000`. |
| `OMNIROUTE_REASONING_MIN_BUDGET` | _chưa đặt_ (tắt) | `open-sse/services/reasoningTokenBuffer.ts` | Ngưỡng tối thiểu opt-in cho ngân sách đầu ra của mô hình suy luận: `max_tokens` của bên gọi nằm trong `[256, floor)` sẽ được nâng lên ngưỡng tối thiểu (bị chặn trên bởi giới hạn đầu ra của mô hình). Chưa đặt = ngân sách của client không bao giờ được nâng lên (#9507). |
| `OMNIROUTE_REASONING_EFFORT_PROBE_PROVIDERS` | _chưa đặt_ (tắt) | `open-sse/services/learnedReasoningEffortCaps.ts` | Opt-in, danh sách id nhà cung cấp phân tách bằng dấu phẩy (hoặc `*`): khi một lỗi 400/422 của `reasoning_effort` không nêu rõ tập giá trị được chấp nhận, thử lại một lần ở mức thấp hơn (không bao giờ dưới `low`) và chỉ học mức đó nếu lần thăm dò được phản hồi (#14895). |
| `OMNIROUTE_LOG_EXPORT_CRON` | `0 * * * *` | `src/lib/jobs/logExportJob.ts` | Biểu thức cron (UTC) cho tác vụ xuất nhật ký cuộc gọi, dùng để xả mọi đích xuất nhật ký đang bật. Nên dùng `*/5 * * * *` khi xuất cả phần thân. |
| `OMNIROUTE_LOG_EXPORT_RUN_TIMEOUT_MS` | `900000` | `src/lib/logExport/childRunner.ts` | Thời gian chờ wall-clock của tiến trình con cho mỗi đích, tính bằng mili giây. Khi hết thời gian chờ sẽ ghi nhận thất bại và kết thúc tiến trình mà không chuyển tiếp batch chưa được xác nhận. Giá trị không hợp lệ/không dương/không phải số nguyên sẽ dùng giá trị mặc định. |
| `OMNIROUTE_LOG_EXPORT_CHILD_MAX_OLD_SPACE_MB` | `1024` | `src/lib/logExport/childRunner.ts` | Giới hạn old-space V8 (tính bằng MB) của tiến trình con xuất Node (không phải tổng RSS). Giá trị mặc định chừa khoảng dư cho 500 hàng artifact đã bị giới hạn kèm phần thân; các batch quá lớn vẫn có thể làm cạn heap của tiến trình con. Khi thất bại, hãy giảm kích thước batch hoặc tăng giới hạn này. Giá trị không hợp lệ/không dương/không phải số nguyên sẽ dùng giá trị mặc định. Việc xuất bằng Bun sẽ fallback về chạy trong tiến trình (in-process) mà không có giới hạn này. |
| `OMNIROUTE_CONFIG_HOT_RELOAD_MS` | `5000` | `src/lib/config/hotReload.ts` | Khoảng thời gian polling (ms) cho tính năng hot-reload cấu hình. Thấp hơn `1000` sẽ bị từ chối. |
| `OMNIROUTE_DISABLE_REDIS_AUTH_CACHE` | _(bật)_ | `src/lib/db/apiKeys.ts` | Đặt `1` để bỏ qua bộ nhớ đệm xác thực khóa API dựa trên Redis (buộc đọc DB). |
| `OMNIROUTE_RTK_TRUST_PROJECT_FILTERS` | `0` | `open-sse/services/compression/engines/rtk/filterLoader.ts` | Tin cậy các quy tắc lọc dự án RTK do người dùng quản lý mà không cần kiểm tra chữ ký nghiêm ngặt. |
| `OMNIROUTE_LITE_MAX_TOOL_LENGTH` | `2000` | `open-sse/services/compression/lite.ts` | Giới hạn số ký tự cho việc cắt ngắn chủ động kết quả công cụ của Lite khi `lite.maxToolLength` chưa được đặt. Khoảng 256–1000000. Cài đặt trên Dashboard được ưu tiên hơn biến môi trường này. |
| `OMNI_COMPRESSION_WORKERS` | `2` | `open-sse/services/compression/compressionWorkerPool.ts` | Số worker đồng bộ RTK/Caveman chạy đồng thời tối đa; các tác vụ dư thừa sẽ chờ theo thứ tự FIFO. |
| `OMNI_COMPRESSION_WORKER_TIMEOUT_MS` | `120000` | `open-sse/services/compression/compressionWorkerPool.ts` | Thời gian chờ cho mỗi tác vụ, tính bằng mili giây. Worker hết thời gian chờ sẽ bị kết thúc và yêu cầu sẽ fail-open, giữ nguyên không thay đổi. |
| `OMNI_COMPRESSION_WORKER_IDLE_MS` | `60000` | `open-sse/services/compression/compressionWorkerPool.ts` | Thời gian nhàn rỗi tính bằng mili giây trước khi một worker nén không được dùng đến bị kết thúc. |
| `OMNI_COMPRESSION_WORKER_MAX_OLD_MB` | `1024` | `open-sse/services/compression/compressionWorkerPool.ts` | Giới hạn heap old-generation của V8 tính bằng MB cho mỗi compression worker, ở mọi chế độ (mức sàn `128`). Một job vượt quá giới hạn này sẽ fail open (không nén) thay vì làm tăng heap của gateway. |
| `COMPRESSION_PIPELINE_BREAKER_ENABLED` | `false` | `open-sse/services/compression/pipelineEngineBreaker.ts` | Công tắc chính của circuit-breaker theo từng engine cho stacked-pipeline T02. **Opt-in (mặc định tắt)** — khi bật, một engine liên tục ném lỗi qua nhiều request sẽ bị bỏ qua (fail-open) trong thời gian cooldown; tắt = hành vi legacy giữ nguyên từng byte. |
| `COMPRESSION_PIPELINE_BREAKER_THRESHOLD` | `3` | `open-sse/services/compression/pipelineEngineBreaker.ts` | Số lần thất bại liên tiếp qua nhiều request trước khi breaker của một engine mở. |
| `COMPRESSION_PIPELINE_BREAKER_COOLDOWN_MS` | `30000` | `open-sse/services/compression/pipelineEngineBreaker.ts` | Số mili-giây một engine đã mở breaker vẫn bị bỏ qua trước khi thử probe half-open. |
| `COMPRESSION_CCR_RETRIEVAL_RAMP_FACTOR` | `2` | `open-sse/services/compression/engines/ccr/index.ts` | Ramp phản hồi truy xuất CCR T08/H8: mỗi lần truy xuất trước đó của một block đã lưu sẽ tăng `minChars` hiệu dụng của nó một cách tuyến tính (nội dung được truy xuất thường xuyên sẽ ít bị nén hơn; `>=3` lần truy xuất = không bao giờ nén). `1` tắt ramp (chỉ bỏ qua nhị phân tại ngưỡng). |
| `COMPRESSION_CCR_DURABLE_STORE` | `true` | `open-sse/services/compression/engines/ccr/index.ts` | Kho lưu block bền vững của CCR (#9061). Hỗ trợ kho in-memory bằng SQLite để một block tồn tại qua việc loại bỏ LRU, TTL, khởi động lại, hoặc một lần truy xuất rơi vào instance khác. Đặt `false` để chỉ giữ các block trong bộ nhớ. Các block trên 512KB và các cloud runtime vẫn chỉ nằm trong bộ nhớ bất kể thế nào. |
| `COMPRESSION_PREFIX_FREEZE_ENABLED` | `false` | `open-sse/services/compression/prefixFreeze.ts` | Công tắc chính đóng băng tiền tố theo quan sát sử dụng T08/H5. **Opt-in (mặc định tắt)** — khi bật, một system prompt được quan sát `>=` ngưỡng sẽ được coi là tiền tố ổn định có thể cache và được bảo toàn khỏi việc nén ngay cả với các provider mà heuristic cache tĩnh bỏ sót (freeze chỉ _bảo toàn_, không bao giờ thay đổi). |
| `COMPRESSION_PREFIX_FREEZE_THRESHOLD` | `3` | `open-sse/services/compression/prefixFreeze.ts` | Số lần quan sát một system prompt trước khi nó được coi là tiền tố ổn định đã đóng băng. |
| `OMNIROUTE_BOOTSTRAPPED` | `false` | `src/app/(dashboard)/dashboard/page.tsx` | Được đặt `true` bởi script bootstrap sau khi cài đặt ban đầu. Kiểm soát hiển thị của trình hướng dẫn cài đặt (setup wizard). |
| `OMNIROUTE_ALLOW_BODY_PROJECT_OVERRIDE` | `0` | `open-sse/executors/antigravity.ts` | Lối thoát: cho phép body của request ghi đè trường project của Antigravity. |
| `ANTIGRAVITY_CREDITS` | `off` | `open-sse/services/antigravityCredits.ts` | Chính sách credits Google One AI: `off` không bao giờ chèn credits, `retry` chèn một lần sau khi gặp lỗi 429 hết quota đủ điều kiện, và `always` chèn ngay từ request đầu tiên. |
| `ANTIGRAVITY_ALLOW_SIGNATURE_BYPASS` | `0` | `open-sse/translator/request/openai-to-gemini.ts` | Cho phép trình dịch request Antigravity bỏ qua việc xác thực chữ ký request CLI nghiêm ngặt khi upstream từ chối chữ ký thật (chế độ debug/CLI lỗi thời). Giá trị khác 0 sẽ bật bypass. |
| `AGY_TOKEN_FILE` | `~/.gemini/antigravity-cli/antigravity-oauth-token` | `src/app/api/providers/agy-auth/apply-local/route.ts` | Ghi đè đường dẫn file token của Antigravity CLI (agy) cho việc import đăng nhập local tự động phát hiện. |
### OAuth CLI Bridge (Nội bộ)
| Biến | Mặc định | File nguồn | Mô tả |
| ------------------- | ----------------- | ------------------------------- | ---------------------------------------------- |
| `OMNIROUTE_SERVER` | tự động phát hiện | `src/lib/oauth/config/index.ts` | URL server cho cầu nối xác thực CLI↔OmniRoute. |
| `OMNIROUTE_TOKEN` | _(chưa đặt)_ | `src/lib/oauth/config/index.ts` | Token xác thực cho cầu nối CLI. |
| `OMNIROUTE_USER_ID` | `cli` | `src/lib/oauth/config/index.ts` | ID người dùng cho các phiên của cầu nối CLI. |
| `SERVER_URL` | _(chưa đặt)_ | `src/lib/oauth/config/index.ts` | Bí danh legacy của `OMNIROUTE_SERVER`. |
| `CLI_TOKEN` | _(chưa đặt)_ | `src/lib/oauth/config/index.ts` | Bí danh legacy của `OMNIROUTE_TOKEN`. |
| `CLI_USER_ID` | _(chưa đặt)_ | `src/lib/oauth/config/index.ts` | Bí danh legacy của `OMNIROUTE_USER_ID`. |
---
## 11. Thông tin xác thực nhà cung cấp OAuth
Thông tin xác thực tích hợp sẵn dành cho **phát triển trên localhost**. Với các triển khai từ xa, hãy đăng ký thông tin xác thực của riêng bạn tại bảng điều khiển dành cho nhà phát triển của từng nhà cung cấp.
| Biến | Nhà cung cấp | Ghi chú |
| ------------------------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CLAUDE_OAUTH_CLIENT_ID` | Claude Code (Anthropic) | Client công khai — không cần secret. |
| `CLAUDE_CODE_REDIRECT_URI` | Claude Code | Ghi đè redirect URI. Mặc định: `https://platform.claude.com/oauth/code/callback` |
| `CODEX_OAUTH_CLIENT_ID` | Codex / OpenAI | Client công khai. |
| `GEMINI_OAUTH_CLIENT_ID` | Gemini (Google) | Yêu cầu `_SECRET` tương ứng. |
| `GEMINI_OAUTH_CLIENT_SECRET` | Gemini (Google) | — |
| `KIMI_CODING_OAUTH_CLIENT_ID` | Kimi Coding (Moonshot) | Client công khai. |
| `MUSE_CODE_OAUTH_CLIENT_ID` | Muse Code (Meta) | Tùy chọn ghi đè cho client id device-flow công khai của Muse CLI. Để trống để sử dụng client công khai tích hợp sẵn. |
| `ANTIGRAVITY_OAUTH_CLIENT_ID` | Antigravity (Google) | Yêu cầu `_SECRET` tương ứng. |
| `ANTIGRAVITY_OAUTH_CLIENT_SECRET` | Antigravity (Google) | — |
| `GITHUB_OAUTH_CLIENT_ID` | GitHub Copilot | Client công khai. |
| `GHE_COPILOT_OAUTH_CLIENT_ID` | GHE Copilot | Tùy chọn ghi đè cho OAuth client id của GitHub Enterprise Copilot. Khi không thiết lập, sẽ sử dụng giá trị công khai mặc định của `GITHUB_OAUTH_CLIENT_ID`. |
| `COPILOT_INTEGRATION_ID` | GitHub Copilot | Tùy chọn ghi đè cho integration ID của client GitHub Copilot được gửi trong các header `Copilot-Integration-Id` và `Editor-Plugin-Version`. Mặc định là `copilot-developer-cli`. |
| `WINDSURF_API_KEY` | Windsurf / Devin (v3.8) | API key dự phòng được sử dụng bởi `open-sse/executors/devin-cli.ts` khi không có thông tin xác thực theo từng kết nối. Tùy chọn. |
| `CLI_DEVIN_BIN` | Devin CLI (v3.8) | Đường dẫn tùy chỉnh tới binary của Devin CLI (`devin`). Được phân giải bởi `open-sse/executors/devin-cli.ts`. |
| `GITLAB_DUO_OAUTH_CLIENT_ID` | GitLab Duo (v3.8) | OAuth client ID cho GitLab Duo. Đăng ký một ứng dụng tại `https://gitlab.com/-/profile/applications` với redirect URI `/callback` và các scope `api, read_user, openid, profile, email`. Dự phòng về `GITLAB_OAUTH_CLIENT_ID`. |
| `GITLAB_DUO_OAUTH_CLIENT_SECRET` | GitLab Duo (v3.8) | OAuth client secret cho GitLab Duo. Tùy chọn — luồng PKCE không yêu cầu secret. Dự phòng về `GITLAB_OAUTH_CLIENT_SECRET`. |
| `GITLAB_DUO_BASE_URL` | GitLab Duo (v3.8) | Ghi đè base URL của GitLab (GitLab tự lưu trữ). Mặc định là `https://gitlab.com`. Dự phòng về `GITLAB_BASE_URL`. |
| `GITLAB_BASE_URL` | GitLab Duo (v3.8) | Phương án dự phòng cũ (legacy) cho `GITLAB_DUO_BASE_URL`. Được sử dụng khi biến thể `_DUO_` chưa được thiết lập. |
| `GITLAB_OAUTH_CLIENT_ID` | GitLab Duo (v3.8) | Phương án dự phòng cũ cho `GITLAB_DUO_OAUTH_CLIENT_ID`, được sử dụng bởi `src/lib/oauth/constants/oauth.ts`. |
| `GITLAB_OAUTH_CLIENT_SECRET` | GitLab Duo (v3.8) | Phương án dự phòng cũ cho `GITLAB_DUO_OAUTH_CLIENT_SECRET`, được sử dụng bởi `src/lib/oauth/constants/oauth.ts`. |
| `QODER_OAUTH_CLIENT_SECRET` | Qoder | — |
| `QODER_OAUTH_AUTHORIZE_URL` | Qoder | Thiết lập để bật Qoder OAuth. |
| `QODER_OAUTH_TOKEN_URL` | Qoder | — |
| `QODER_OAUTH_USERINFO_URL` | Qoder | — |
| `QODER_OAUTH_CLIENT_ID` | Qoder | — |
| `QODER_PERSONAL_ACCESS_TOKEN` | Qoder | Phương án dự phòng dùng API key trực tiếp (bỏ qua OAuth). |
| `QODER_CLI_WORKSPACE` | Qoder | ID workspace cho Qoder CLI. |
| `OMNIROUTE_QODER_WORKSPACE` | Qoder | Bí danh của `QODER_CLI_WORKSPACE`. |
| `QODER_CLI_CONFIG_DIR` | Qoder | Ghi đè thư mục cấu hình của Qoder CLI (phiên PAT tách biệt, tránh ghi đè phiên đăng nhập trình duyệt). |
| `QODER_CLI_MAX_CONCURRENCY` | Qoder | Số lượt chạy qodercli đồng thời tối đa (các tiến trình spawn print hoặc prompt ACP); các yêu cầu vượt quá sẽ xếp hàng FIFO. Không thiết lập (mặc định) = không giới hạn. |
| `QODER_CLI_QUEUE_TIMEOUT_MS` | Qoder | Thời gian một yêu cầu Qoder chờ slot qodercli (chỉ khi đã đặt giới hạn) trước khi thất bại với 429 `qodercli_busy` + `Retry-After`. Mặc định `120000`. |
| `QODER_CLI_TRANSPORT` | Qoder | `print` (mặc định) khởi tạo `qodercli --print` cho mỗi yêu cầu; `acp` duy trì một tiến trình `qodercli --acp` thường trực cho mỗi PAT. |
| `QODER_CLI_ACP_IDLE_TIMEOUT_MS` | Qoder | Transport ACP: hủy tiến trình qodercli thường trực sau khoảng thời gian nhàn rỗi này. Mặc định `600000`. |
| `QODER_CLI_ACP_STARTUP_TIMEOUT_MS` | Qoder | Transport ACP: thời hạn để qodercli phản hồi lệnh `initialize` của ACP. Mặc định `60000`. |
| `QODER_CLI_ACP_MAX_SESSIONS_PER_PROCESS` | Qoder | Transport ACP: tái chế tiến trình qodercli thường trực sau số phiên này. Mặc định `500`. |
| `BLACKBOX_WEB_VALIDATED_TOKEN` | Blackbox Web | Token `tk` của frontend để gửi dưới dạng `validated` tới `/api/chat`. Bắt buộc khi Blackbox áp dụng đối chiếu token; nếu không OmniRoute sẽ dùng một UUID ngẫu nhiên. Xem issue #2252. |
| `VISION_BRIDGE_BASE_URL` | Vision Bridge guardrail | Base URL tương thích OpenAI cho các lệnh gọi vision-bridge không phải Anthropic. Mặc định dùng biến môi trường URL OpenAI cũ hoặc api.openai.com. Trỏ tới self-loop `/v1` của OmniRoute hoặc bất kỳ endpoint tương thích OpenAI nào (Gemini tương thích OpenAI, OpenRouter). Issue #2232. Khi URL là `/v1` của chính OmniRoute, sub-request describe sẽ gửi `x-omniroute-admission-bypass: internal` và xác thực bằng credential self-loop đã được phân giải (sentinel `sk_omniroute` ở chế độ local, hoặc `OMNIROUTE_API_KEY` / `ROUTER_API_KEY` — #1350) để các triển khai có `REQUIRE_API_KEY=true` hoạt động được. |
| `VISION_BRIDGE_API_KEY` | Vision Bridge guardrail | Khóa API cho URL ở trên. Ghi đè các biến môi trường OpenAI / Google theo từng provider cho các lệnh gọi vision-bridge không phải Anthropic. Các model Anthropic vẫn giữ đường dẫn khóa Anthropic riêng của chúng. Issue #2232. |
| `OMNIROUTE_VISION_BRIDGE_NEGATIVE_CACHE_MS` | Vision Bridge guardrail | Khoảng thời gian một kết quả định tuyến "không có ứng viên khả dụng" được lưu trong cache, tính bằng ms (mặc định `30000`). Giá trị không hợp lệ hoặc giá trị âm sẽ quay về mặc định; `0` sẽ tắt cache âm. Nguồn: `src/lib/guardrails/visionBridgeRouter.ts`. |
> [!WARNING]
>
> 1. Vào [Google Cloud Console → Credentials](https://console.cloud.google.com/apis/credentials)
> 2. Tạo một OAuth 2.0 Client ID (loại: "Ứng dụng web")
> 3. Thêm URL máy chủ của bạn làm URI chuyển hướng được ủy quyền (Authorized redirect URI)
> 4. Thay thế các giá trị credential trong `.env`.
---
## 12. Ghi đè User-Agent của nhà cung cấp
Ghi đè header `User-Agent` được gửi đến từng nhà cung cấp upstream. Giá trị này được phân giải động tại runtime bởi lớp executor cơ sở:
```
process.env[`${PROVIDER_ID}_USER_AGENT`]
```
> **Nguồn:** `open-sse/executors/base.ts` → `buildHeaders()`
| Biến | Giá trị mặc định | Khi nào cần cập nhật |
| -------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.280 (external, cli)` | Khi Anthropic phát hành phiên bản CLI mới |
| `CLAUDE_DISABLE_TOOL_NAME_CLOAK` | `false` | `executors/base.ts` + `executors/cliproxyapi.ts` | Đặt thành `1`/`true` để chuyển tiếp nguyên văn tên công cụ của harness bên thứ ba đến Anthropic trên cả hai đường đi về Anthropic (native OAuth và CLIProxyAPI). Theo mặc định, executor tạo bí danh mang tính xác định cho các tên công cụ không thuộc Claude Code (dùng ánh xạ chuẩn của Claude Code nếu có, nếu không thì dùng PascalCase) và đảo ngược chúng trong phản hồi thông qua `_toolNameMap`, nhờ đó các harness có công cụ dạng snake_case không bị từ chối như các client bên thứ ba bị nhận diện dấu vân tay. Chỉ dùng để debug. |
| `CODEX_USER_AGENT` | `codex-cli/0.155.0 (Windows 10.0.26200; x64)` | Khi OpenAI cập nhật Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.155.0` | Ghi đè phiên bản client Codex độc lập với chuỗi UA đầy đủ |
| `GROK_CLI_CLIENT_VERSION` | `1.0.41` | Ghi đè `x-grok-client-version` cho inference, đồng bộ model và OAuth device-code, cùng với User-Agent mặc định của Grok CLI cho inference và đồng bộ model. Chấp nhận SemVer với metadata prerelease/build tùy chọn, tối đa 128 ký tự sau khi cắt khoảng trắng đầu cuối. Giá trị chưa đặt, rỗng, không hợp lệ hoặc chứa ký tự xuống dòng sẽ dùng giá trị ghim đi kèm. Ghi đè User-Agent inference đầy đủ hiện có vẫn được ưu tiên. |
| `CLAUDE_CODE_CLIENT_VERSION` | `2.1.280` | Ghi đè phiên bản Claude Code được khai báo, độc lập với `CLAUDE_USER_AGENT`. Anthropic giới hạn một số model dựa trên giá trị này (#12417). |
| `CLAUDE_CODE_CLIENT_BUILD_REVISION` | `1e2` | Ghi đè hậu tố 3 ký tự mà OmniRoute thêm vào `cc_version=` trong khối billing của Claude. Tăng cùng với `CLAUDE_CODE_CLIENT_VERSION` — chỉ ghim phiên bản sẽ khai báo một cặp `version.revision` mà không có binary thật nào phát ra. |
| `GITHUB_COPILOT_CLI_VERSION` | `1.0.91` | Ghi đè phiên bản Copilot CLI được khai báo, độc lập với `GITHUB_USER_AGENT` |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.54.0` | Khi GitHub Copilot Chat cập nhật |
| `ANTIGRAVITY_USER_AGENT` | `antigravity/2.0.1 darwin/arm64` | Khi Antigravity IDE cập nhật |
| `KIRO_USER_AGENT` | `AWS-SDK-JS/3.0.0 kiro-ide/1.0.0` | Khi Kiro IDE cập nhật |
| `KIRO_OAUTH_CLIENT_ID` | `kiro-cli` | Ghi đè `clientId` device-code social của Kiro (id công khai) |
| `KIRO_VERIFY_FULL_CRC` | `false` | Tùy chọn bật: xác thực CRC đầy đủ cho từng frame message trên luồng sự kiện Kiro (debug các luồng bị lỗi) |
| `KIRO_CREDIT_PRICE_USD` | `0.02` | USD cho mỗi credit Kiro; chuyển đổi các credit `meteringEvent` thành chi phí chính xác cho mỗi request |
| `KIRO_REQUIRE_CREDITS` | `false` | Báo lỗi phản hồi Kiro không báo cáo đo lường credit thay vì ghi nhận nó ở trạng thái chưa tính phí |
| `QODER_USER_AGENT` | `Qoder-Cli` | Khi Qoder CLI cập nhật |
| `CURSOR_USER_AGENT` | `Cursor/3.3` | Khi Cursor cập nhật |
> [!TIP]
> Bạn có thể thêm ghi đè User-Agent cho **bất kỳ** nhà cung cấp nào bằng mẫu `{PROVIDER_ID}_USER_AGENT`. Executor sẽ tự động tạo tên biến môi trường một cách linh động.
---
## 13. Khả năng tương thích dấu vân tay CLI
Khi được bật, OmniRoute sắp xếp lại các header HTTP và trường trong phần thân JSON để khớp với chữ ký chính xác của các công cụ CLI chính thức. Điều này giúp giảm nguy cơ tài khoản bị gắn cờ trong khi vẫn giữ nguyên IP proxy của bạn.
**Nguồn:** `open-sse/config/cliFingerprints.ts`, `open-sse/executors/base.ts`
### Theo từng nhà cung cấp
| Biến | Kích hoạt | Tác dụng |
| ------------------------ | --------- | ------------------------------------------ |
| `CLI_COMPAT_CODEX` | `=1` | Mô phỏng chữ ký yêu cầu của Codex CLI |
| `CLI_COMPAT_CLAUDE` | `=1` | Mô phỏng chữ ký yêu cầu của Claude Code |
| `CLI_COMPAT_GITHUB` | `=1` | Mô phỏng chữ ký yêu cầu của GitHub Copilot |
| `CLI_COMPAT_ANTIGRAVITY` | `=1` | Mô phỏng chữ ký yêu cầu của Antigravity |
| `CLI_COMPAT_CURSOR` | `=1` | Mô phỏng chữ ký yêu cầu của Cursor |
| `CLI_COMPAT_KIMI_CODING` | `=1` | Mô phỏng chữ ký yêu cầu của Kimi Coding |
| `CLI_COMPAT_KILOCODE` | `=1` | Mô phỏng chữ ký yêu cầu của Kilo Code |
| `CLI_COMPAT_CLINE` | `=1` | Mô phỏng chữ ký yêu cầu của Cline |
### Toàn cục
| Biến | Kích hoạt | Tác dụng |
| ---------------- | --------- | -------------------------------------------------------------------------- |
| `CLI_COMPAT_ALL` | `=1` | Bật khả năng tương thích dấu vân tay cho **tất cả** nhà cung cấp cùng lúc. |
### Ghi đè danh tính Kimi Coding CLI
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ----------------------- | -------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------ |
| `KIMI_CLI_VERSION` | `1.36.0` | `src/lib/oauth/providers/kimi-coding.ts` | Ghi đè phiên bản Kimi CLI được gửi trong các lệnh gọi OAuth/API. |
| `KIMI_CODING_DEVICE_ID` | _(giá trị mặc định đã thu thập)_ | `src/lib/oauth/providers/kimi-coding.ts` | Ghi đè ID thiết bị Kimi đã thu thập được sử dụng trong header máy khách. |
> [!NOTE]
> Tính năng này hoạt động cùng với các thiết lập ghi đè User-Agent (§12). Hệ thống dấu vân tay xử lý thứ tự header và thứ tự trường trong phần thân, còn các thiết lập ghi đè User-Agent xử lý chuỗi UA cụ thể. Cả hai có thể được bật độc lập.
---
## 14. Nhà cung cấp khóa API
Khóa API dành cho các nhà cung cấp sử dụng xác thực trực tiếp. **Thiết lập ưu tiên:** Dashboard → Providers → Add API Key.
Thiết lập thông qua biến môi trường là phương án thay thế cho các bản triển khai Docker hoặc không có giao diện.
Mẫu được nhận diện: `{PROVIDER_ID}_API_KEY`
| Biến | Nhà cung cấp |
| ------------------ | ------------------------------------------------------------------------- |
| `DEEPSEEK_API_KEY` | DeepSeek |
| `NVIDIA_API_KEY` | NVIDIA NIM |
| `JINA_AI_API_KEY` | Jina AI (Foundation API + phương án dự phòng Reader) |
| `JINA_API_KEY` | Jina AI (bí danh của `JINA_AI_API_KEY`) |
| `GEMINI_API_KEY` | Gemini (Google AI Studio), embeddings + phương án dự phòng cho trò chuyện |
| `GOOGLE_API_KEY` | Gemini (bí danh của `GEMINI_API_KEY`) |
> [!NOTE]
> Các mục `${PROVIDER}_API_KEY` tĩnh dành cho Groq, xAI, Mistral, Perplexity, Together AI, Fireworks, Cerebras, Cohere, Nebius và Qianfan đã bị loại bỏ trong v3.8.0 vì môi trường chạy không còn đọc chúng — các nhà cung cấp đó hoàn toàn phụ thuộc vào Dashboard / `data/provider-credentials.json` / cơ sở dữ liệu được mã hóa. Xem phần _Kiểm tra: Các biến đã loại bỏ / không còn sử dụng_ ở cuối tài liệu này để biết lộ trình di chuyển.
> [!TIP]
> Các khóa được thiết lập qua Dashboard được lưu trữ dưới dạng mã hóa trong SQLite và được ưu tiên hơn các biến môi trường.
>
> **Jina:** embeddings `jina-ai/…`, rerank, classify, segment và `jina-search` **không** tính phí khóa môi trường của cụm khi có kết nối `jina-ai` (hoặc `jina-reader` dùng chung) trên dashboard — `getProviderCredentials` điền theo nguyên tắc ưu tiên giá trị đầu tiên. `JINA_AI_API_KEY` / `JINA_API_KEY` chỉ được sử dụng khi không có khóa dashboard khả dụng. Nhật ký lệnh gọi ghi nhận phương án dự phòng từ biến môi trường là `connection_id=env:JINA_AI_API_KEY`. Thẻ Reader (`jina-reader`, `r.jina.ai`) không bao giờ phục vụ `/v1/embeddings` hoặc `/v1/rerank`.
>
> **Gemini:** `gemini/gemini-embedding-2` (bí danh `google/gemini-embedding-2`) sử dụng kết nối `gemini` trên dashboard trước. `GEMINI_API_KEY` / `GOOGLE_API_KEY` chỉ được sử dụng khi không có khóa dashboard khả dụng. Nhật ký lệnh gọi ghi nhận phương án dự phòng từ biến môi trường là `connection_id=env:GEMINI_API_KEY`. Lưu lượng đa phương thức nguyên bản sử dụng `x-goog-api-key` với `:embedContent` / `:batchEmbedContents` — N mục `input` của OpenAI tạo thành N vector.
---
## 15. Cài đặt Timeout
Tất cả giá trị đều tính bằng **mili giây**. Được phân giải tập trung tại `src/shared/utils/runtimeTimeouts.ts`.
### Phân cấp Timeout
```
REQUEST_TIMEOUT_MS (ghi đè toàn cục)
├─→ FETCH_TIMEOUT_MS (các lệnh gọi đến nhà cung cấp upstream, mặc định: 600000)
│ ├─→ FETCH_HEADERS_TIMEOUT_MS (kế thừa từ FETCH_TIMEOUT_MS)
│ ├─→ FETCH_BODY_TIMEOUT_MS (kế thừa từ FETCH_TIMEOUT_MS)
│ ├─→ TLS_CLIENT_TIMEOUT_MS (kế thừa từ FETCH_TIMEOUT_MS)
│ │ └── TLS_FIRST_BYTE_WATCHDOG_MS (độc lập, mặc định: 10000)
│ ├── RESPONSES_FIRST_BYTE_TIMEOUT_MS (độc lập, mặc định: 15000)
│ ├── OPENCODE_RESPONSES_HEADERS_WAIT_MS (độc lập, mặc định: 0 = tắt, đề xuất: 30000)
│ ├── OPENCODE_RESPONSES_HEADERS_WAIT_MAX_ROTATIONS (độc lập, mặc định: 2)
│ ├── FETCH_CONNECT_TIMEOUT_MS (độc lập, mặc định: 30000)
│ └── FETCH_KEEPALIVE_TIMEOUT_MS (độc lập, mặc định: 4000)
├─→ STREAM_IDLE_TIMEOUT_MS (kế thừa từ REQUEST_TIMEOUT_MS, mặc định: 600000)
├─→ STREAM_ACTIVE_TIMEOUT_MS (độc lập, mặc định: 1260000; 0 để tắt)
├─→ STREAM_READINESS_TIMEOUT_MS (kế thừa từ REQUEST_TIMEOUT_MS, mặc định: 80000)
├─→ STREAM_READINESS_MAX_TIMEOUT_MS (giới hạn tối đa cho các lần gia hạn readiness thích ứng, mặc định: 180000)
└─→ API_BRIDGE_PROXY_TIMEOUT_MS (kế thừa từ REQUEST_TIMEOUT_MS, mặc định: 30000)
├─→ API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS (suy ra, mặc định: 300000)
├── API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS (mặc định: 60000)
├── API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS (mặc định: 5000)
└── API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS (mặc định: 0 = vô hiệu hóa)
```
| Variable | Default | Description |
| ----------------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `REQUEST_TIMEOUT_MS` | _(chưa đặt)_ | Phím tắt toàn cục — ghi đè giá trị mặc định của cả `FETCH_TIMEOUT_MS` và `STREAM_IDLE_TIMEOUT_MS`. |
| `FETCH_TIMEOUT_MS` | `600000` | Tổng thời gian chờ (timeout) của yêu cầu HTTP cho các lệnh gọi đến nhà cung cấp upstream. |
| `STREAM_IDLE_TIMEOUT_MS` | `600000` | Khoảng im lặng tối đa giữa các byte thô từ upstream trước khi hủy. Các mô hình extended-thinking hiếm khi tạm dừng quá 90 giây. |
| `STREAM_ACTIVE_TIMEOUT_MS` | `1260000` | Thời gian tồn tại tối đa của luồng SSE đang hoạt động; không bao giờ reset khi nhận byte từ upstream và độc lập với `REQUEST_TIMEOUT_MS`. Được suy ra từ giá trị `timeoutMs` lớn nhất theo từng mô hình trong registry (1200000, Codex) cộng thêm biên an toàn 60000, để một mô hình được phép chạy hết ngân sách thời gian sẽ không bị kill giữa chừng khi đang trả lời. Đặt thành `0` để tắt. |
| `OMNIROUTE_SSE_COMMENTS` | _(đã tắt)_ | Quyết định OmniRoute có được phát các dòng comment SSE `:` hay không (ví dụ heartbeat `: keepalive` và các trailer metadata `x-omniroute-*`). Mặc định tắt (#10524) vì các client nghiêm ngặt tương thích OpenAI sẽ JSON.parse mọi dòng SSE và crash khi gặp comment `:`; heartbeat dạng `data:` không bị ảnh hưởng. Đặt `on`/`true`/`1`/`yes` để bật lại. Được dùng bởi `open-sse/utils/sseHeartbeat.ts`. |
| `SSE_COALESCE_MS` | `0` (tắt) | Tùy chọn bật: gộp các sự kiện `content_block_delta` liên tiếp của Claude (cùng chỉ số block và cùng loại delta) gửi đến client Claude, flush ít nhất mỗi N ms. Không mất dữ liệu; `signature_delta` và các sự kiện ranh giới không bao giờ bị gộp. Áp dụng cho mọi loại delta trừ khi một biến theo từng loại bên dưới được đặt. Được dùng bởi `open-sse/utils/sseDeltaCoalesce.ts`. |
| `SSE_COALESCE_THINKING_MS` | `0` (tắt) | Ghi đè theo từng loại của `SSE_COALESCE_MS` cho `thinking_delta`. |
| `SSE_COALESCE_TEXT_MS` | `0` (tắt) | Ghi đè theo từng loại của `SSE_COALESCE_MS` cho `text_delta`. |
| `SSE_COALESCE_INPUT_JSON_MS` | `0` (tắt) | Ghi đè theo từng loại của `SSE_COALESCE_MS` cho `input_json_delta`. |
| `SSE_FRAME_COALESCE_MS` | `0` (tắt) | Tùy chọn bật: gom các khung SSE được chuyển tiếp trong vòng N ms thành một lần ghi tới client. Khung đầu tiên và các khung kết thúc (`[DONE]`, `message_stop`, `error`, `response.completed`/`failed`/`incomplete`) không bao giờ bị trì hoãn; khi bật gom, ITL đo khoảng cách giữa các lô. Được dùng bởi `open-sse/utils/sseOutputSink.ts`. |
| `SSE_STALL_WATCHDOG` | `timer` | Cài đặt watchdog phát hiện đình trệ byte cho các phản hồi dạng stream. `timer` đặt lại một bộ đếm cho mỗi chunk từ upstream (kích hoạt đúng tại ngưỡng ngân sách đình trệ); `interval` giữ một lần kiểm tra cho mỗi luồng với chu kỳ `clamp(budget/4, 1s, 5s)`, nên một lần đình trệ sẽ được phát hiện trong khoảng ngân sách + chu kỳ. Được dùng bởi `open-sse/utils/streamStallWatchdog.ts`. |
| `STREAM_READINESS_TIMEOUT_MS` | `80000` | Thời gian chờ nhận sự kiện SSE đầu tiên không phải ping. Kế thừa `REQUEST_TIMEOUT_MS` khi biến này được đặt. |
| `STREAM_READINESS_MAX_TIMEOUT_MS` | `180000` | Cửa sổ sẵn sàng chờ sự kiện đầu tiên thích ứng tối đa cho các yêu cầu streaming lớn, dùng nhiều công cụ hoặc suy luận nặng. |
| `OMNIROUTE_AGENT_GOAL_POLICY_ENABLED` | `true` | Công tắc tắt khẩn cấp cho heuristic `/goal`. Đặt `false`/`0`/`off` để tắt hoàn toàn việc phát hiện — timeout sẵn sàng và khôi phục luồng sẽ không bao giờ bị nâng lên bởi body/headers của yêu cầu, giúp giảm thiểu việc client tự khuếch đại timeout. |
| `OMNIROUTE_AGENT_GOAL_READINESS_MAX_TIMEOUT_MS` | `600000` | Cửa sổ sẵn sàng chờ sự kiện đầu tiên tối đa cho các lần chạy agent `/goal` được phát hiện hoặc các yêu cầu bị ép bằng `x-omniroute-agent-goal`. |
| `OMNIROUTE_AGENT_GOAL_STREAM_RECOVERY` | `true` | Tự động bật khôi phục luồng sớm cho các lần chạy agent `/goal` được phát hiện. Đặt `false`/`0`/`off` để tắt tùy chọn riêng cho goal. Tính năng này chỉ có thể THÊM khôi phục lên trên mặc định của người vận hành — nó không bao giờ ghi đè lựa chọn tắt rõ ràng qua `STREAM_RECOVERY_ENABLED`/cài đặt DB. |
| `OMNIROUTE_CODEX_DROP_NONSTANDARD_EVENTS` | `true` | Loại bỏ các sự kiện SSE `codex.*` không chuẩn (ví dụ `codex.rate_limits`) vốn làm hỏng `responses.stream()` của OpenAI SDK với lỗi 502. Mặc định BẬT (#11014). Đặt `0`/`false`/`no`/`off` để chuyển tiếp chúng. |
| `OMNIROUTE_CODEX_APPSERVER_WS` | _(chưa đặt)_ | Tùy chọn bật transport Codex app-server. Endpoint WebSocket (`ws://`/`wss://`) của một sidecar `codex app-server` cục bộ. Khi được đặt cùng với token, các yêu cầu Codex được định tuyến qua JSON-RPC tới sidecar thay vì HTTP Responses API. Cũng có thể đặt theo từng kết nối qua `providerSpecificData.codexAppServerUrl`. Được dùng bởi `open-sse/executors/codex/appServerConfig.ts`. |
| `OMNIROUTE_CODEX_APPSERVER_WS_TOKEN` | _(chưa đặt)_ | Token capability/bearer nội tuyến được trình cho app-server. Ghi đè theo từng kết nối: `providerSpecificData.codexAppServerToken`. |
| `OMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE` | _(unset)_ | Đường dẫn đến tệp chứa token năng lực của app-server (từ `codex app-server --ws-token-file`). Được dùng khi `OMNIROUTE_CODEX_APPSERVER_WS_TOKEN` chưa được đặt. Ghi đè theo từng kết nối: `providerSpecificData.codexAppServerTokenFile`. |
| `OMNIROUTE_CODEX_APPSERVER_CWD` | `/tmp` | Thư mục làm việc mà lượt chạy của app-server thực thi trong đó. Ghi đè theo từng kết nối: `providerSpecificData.codexAppServerCwd`. |
| `OMNIROUTE_CODEX_APPSERVER_APPROVAL` | _(unset)_ | Chính sách phê duyệt truyền vào lượt chạy của app-server (ví dụ `never`, `on-request`). Ghi đè theo từng kết nối: `providerSpecificData.codexAppServerApprovalPolicy`. |
| `OMNIROUTE_CODEX_APPSERVER_SANDBOX` | _(unset)_ | Chính sách sandbox truyền vào lượt chạy của app-server (ví dụ `read-only`, `workspace-write`, `danger-full-access`). Khi chưa đặt, executor mặc định là `workspace-write` (đã tăng cường bảo mật; trước đây là `danger-full-access`). Ghi đè theo từng kết nối: `providerSpecificData.codexAppServerSandbox`. |
| `OMNIROUTE_CODEX_APPSERVER_AUTO_APPROVE` | `false` | Tự động phê duyệt các lời nhắc phê duyệt của chính app-server (thực thi lệnh/tệp/quyền trên máy chủ). Mặc định tắt — các lời nhắc bị tự động từ chối; các lệnh gọi công cụ của harness không bị ảnh hưởng (chúng đi qua đường truyền passthrough `item/tool/call` riêng). Chấp nhận `true`/`1`/`yes`. Ghi đè theo từng kết nối: `providerSpecificData.codexAppServerAutoApprove`. |
| `FETCH_HEADERS_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | Thời gian nhận header phản hồi. |
| `OMNIROUTE_FETCH_START_TIMEOUT_CAP_MS` | `110000` | Thời gian chờ tối đa cho header phản hồi trên các yêu cầu streaming (ms). `0` tắt giới hạn này; giá trị `fetchStartTimeoutCapMs` được chỉ định rõ của provider sẽ được ưu tiên. |
| `OMNIROUTE_DIRECT_HEADERS_TIMEOUT_MS` | `30000` (30s) | Thời gian chờ tối đa cho phản hồi bắt đầu (ms) cho mỗi lần thử kết nối trực tiếp không qua proxy. Khi hết thời gian sẽ thử lại một lần trên socket mới; đặt `0` để tắt giới hạn này và giữ nguyên hành vi trước đó. |
| `OMNIROUTE_LOCAL_DIRECT_HEADERS_TIMEOUT_MS` | `300000` (5 phút) | Ngưỡng sàn cho thời gian chờ phản hồi bắt đầu (ms) cho các lần thử kết nối trực tiếp không qua proxy có máy chủ đích là private/LAN/loopback (ví dụ `localhost`, `host.docker.internal`, `192.168.x.x`), để việc khởi động nguội của Ollama gốc không bị cắt ngang bởi mặc định 30s ở trên. Hoạt động như một ngưỡng sàn: thời gian chờ hiệu dụng là giá trị lớn hơn giữa giá trị này và `OMNIROUTE_DIRECT_HEADERS_TIMEOUT_MS`; `0` hoặc giá trị không hợp lệ sẽ loại bỏ ngưỡng sàn cục bộ. Các máy chủ từ xa không bị ảnh hưởng. |
| `OMNIROUTE_DIRECT_RESPONSE_RETRY_TIMEOUT_MS` | `600000` (10 phút) | Ngưỡng trần (ms) cho lần thử LẠI trên socket mới sau khi lần thử dùng pooled connection hết thời gian chờ phản hồi bắt đầu ở trên (#13703). Chỉ áp dụng khi phía gọi đã gắn tín hiệu deadline riêng (chuỗi cascade connection/model/provider/`FETCH_TIMEOUT_MS` đã được phân giải); tín hiệu đó mới là giới hạn thực và sẽ kích hoạt trước trong luồng dự kiến, vì vậy đây là cơ chế bảo vệ dự phòng hào phóng chứ không phải ngưỡng trần cứng — nếu không có nó, lần thử lại sẽ dùng lại cùng cửa sổ `OMNIROUTE_DIRECT_HEADERS_TIMEOUT_MS` ngắn như lần thử pooled và trả về 504 cho các mô hình reasoning khỏe mạnh nhưng TTFB chậm. Không bao giờ được phép thấp hơn ngưỡng sàn cứng ở trên; khi phía gọi không cung cấp tín hiệu deadline nào, lần thử lại giữ nguyên ngưỡng sàn cứng. |
| `FETCH_BODY_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | Thời gian nhận toàn bộ nội dung phản hồi. |
| `FETCH_CONNECT_TIMEOUT_MS` | `30000` | Thời gian chờ thiết lập kết nối TCP. |
| `FETCH_KEEPALIVE_TIMEOUT_MS` | `4000` | Thời gian chờ khi socket keep-alive không hoạt động. |
| `TLS_CLIENT_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | Thời gian chờ của proxy TLS fingerprint (wreq-js). |
| `TLS_FIRST_BYTE_WATCHDOG_MS` | `10000` | Giới hạn thời gian đến byte đầu tiên (time-to-first-byte) riêng cho phần body của transport TLS-fingerprint wreq-js; một mình `TLS_CLIENT_TIMEOUT_MS` không thể phát hiện body bị đình trệ vì nó hoàn thành ngay khi header đến (#12656). Khi hết thời gian sẽ hủy wreq reader và quay về dispatcher trực tiếp/proxy; `0` tắt watchdog. |
| `RESPONSES_FIRST_BYTE_TIMEOUT_MS` | `15000` | Chỉ dành cho OpenCode executor, và chỉ khi cờ tính năng `OPENCODE_RESPONSES_STALL_ROTATION` được bật (mặc định tắt): giới hạn thời gian chờ byte body đầu tiên của một phản hồi Responses dạng stream sau khi header đã đến (#13484). Một stream Responses mở đầu bằng `response.created`, nên im lặng quá cửa sổ này là bị đình trệ: tài khoản bị cooldown và yêu cầu được chuyển sang tài khoản tiếp theo một lần; nếu đình trệ lần thứ hai sẽ thất bại nhanh. `0` tắt cơ chế bảo vệ này ngay cả khi cờ đang bật. |
| `OPENCODE_RESPONSES_HEADERS_WAIT_MS` | `0` (= tắt) | Chỉ dành cho OpenCode executor: giới hạn thời gian chờ header phản hồi từ upstream trên một lệnh gọi Responses dạng stream khi vẫn còn tài khoản khả dụng khác — một yêu cầu đang xếp hàng sẽ ngừng chờ và chuyển đi thay vì giữ toàn bộ cửa sổ chờ header. Chỉ các lệnh gọi Responses dạng stream bị ảnh hưởng (stream Responses mở đầu bằng `response.created`, nên im lặng ở đó là đang xếp hàng, không phải đang sinh nội dung); chat completions và các lệnh gọi không stream không bị ảnh hưởng, và cửa sổ này chỉ rút ngắn ngưỡng trần fetch-start hiệu dụng, không bao giờ kéo dài nó. Giá trị đề xuất khi bật: `30000`. `0` tắt. |
| `OPENCODE_RESPONSES_HEADERS_WAIT_MAX_ROTATIONS` | `2` | Chỉ dành cho trình thực thi OpenCode: số lần trong mỗi yêu cầu mà giới hạn chờ header ở trên được phép chuyển sang tài khoản tiếp theo. Tài khoản cuối cùng còn lại luôn giữ nguyên toàn bộ cửa sổ chờ header. |
| `OPENCODE_PARK_AND_RESUME` | `false` | Chỉ dành cho trình thực thi OpenCode: tạm dừng (park) yêu cầu kèm theo heartbeat sau các lỗi 429 tạm thời lặp lại (hoặc một điểm đánh dấu quá tải pool còn mới), sau đó phát lại một nhánh bị giới hạn gồm tối đa 3 tài khoản tuần tự thay vì phân tán ra toàn bộ fleet (#13924). Tắt theo mặc định: mỗi lỗi 429 sẽ chuyển sang tài khoản tiếp theo y hệt như trước. |
| `OPENCODE_PARK_REPLAY_SERVE_SETASIDE` | `false` | Chỉ dành cho trình thực thi OpenCode: khi mọi tài khoản đã sẵn sàng sau cooldown trong nhánh phát lại park-and-resume đều bị bộ nhớ từ chối proxy gạt sang một bên, vẫn phục vụ chúng thay vì không phát lại gì (#14851, tiếp nối #14750). Tắt theo mặc định: nhánh phát lại sẽ rỗng trong trường hợp đó, như trước #14750. |
| `STREAM_READINESS_STALL_RETRY` | `false` | Chỉ dành cho chat dạng streaming: khi phần thân (body) đầu tiên từ upstream bị đình trệ trước khi tạo ra một sự kiện dùng được, thực hiện một lần thử thứ hai có giới hạn qua cùng đường định tuyến với cùng ngân sách sẵn sàng và không phạt tài khoản. Tắt theo mặc định: phần thân đầu tiên bị đình trệ sẽ làm yêu cầu thất bại mà không thử lại. |
| `OPENCODE_POOL_RESELECT` | `false` | Chỉ dành cho trình thực thi OpenCode: sau lỗi 429 từ một nhà cung cấp được phân nhóm theo egress trên một tài khoản không có proxy trong ngữ cảnh pool môi trường, yêu cầu connection pool cung cấp một thành viên khác cho lần thử tiếp theo thay vì thử lại cùng một địa chỉ egress. Chỉ sắp xếp thứ tự, không bao giờ loại trừ: một pool đã cạn sẽ giữ nguyên hành vi hiện tại. Tắt theo mặc định: mỗi lỗi 429 sẽ chuyển sang tài khoản tiếp theo y hệt như trước. |
| `OPENCODE_POOL_STRAIN_MARKER_PATH` | _(chưa đặt)_ | Chỉ dành cho trình thực thi OpenCode: ghi đè đường dẫn của điểm đánh dấu quá tải pool được đọc trước khi tạm dừng (`{since, reason, ttl_s}`, mặc định `/tmp/opencode-pool-strain.json`, #13924). Một điểm đánh dấu còn mới sẽ tạm dừng mà không cần đếm lại; nếu không có hoặc đã cũ sẽ quay về bộ đếm burst. |
| `API_BRIDGE_PROXY_TIMEOUT_MS` | `30000` | Thời gian chờ của bước nhảy proxy cho các yêu cầu bridge `/v1`. |
| `FIRECRAWL_BASE_URL` | `https://api.firecrawl.dev` | Trỏ trình thực thi tải web Firecrawl tới một instance tự lưu trữ (khóa API là tùy chọn khi ngoài cloud). |
| `FIRECRAWL_TIMEOUT_MS` | `30000` | Thời gian chờ cho mỗi yêu cầu của trình thực thi tải web Firecrawl. |
| `TAVILY_BASE_URL` | _(chưa đặt)_ | URL cơ sở cho trình lấy hạn mức `/usage` của Tavily (Provider Limits); bị bỏ qua khi trỏ tới `api.tavily.com`. Nếu chưa đặt sẽ quay về URL cơ sở của kết nối. |
| `API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS` | `300000` | Thời gian chờ tổng thể của yêu cầu server cho bridge. |
| `API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS` | `60000` | Thời gian gửi header phản hồi qua bridge. |
| `API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS` | `5000` | Thời gian chờ nhàn rỗi keep-alive của bridge. |
| `API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS` | `0` | Thời gian chờ socket thô (0 = tắt). |
| `SHUTDOWN_TIMEOUT_MS` | `30000` | Thời gian ân hạn khi nhận SIGTERM/SIGINT trước khi buộc thoát. |
| `OMNIROUTE_DEFAULT_FETCH_TIMEOUT_MS` | `120000` | Giá trị dự phòng được `src/shared/utils/fetchTimeout.ts` sử dụng khi `FETCH_TIMEOUT_MS` chưa được đặt. |
| `OMNIROUTE_PROVIDER_PROBE_TIMEOUT_MS` | `8000` | Thời gian chờ (ms) cho các preset `validationRead` và `modelsProbe` trong `src/shared/network/safeOutboundFetch.ts`. Tăng lên cho các endpoint chậm (Cerebras, Cloudflare AI, Groq) để tránh dao động liên tục giữa active/error trên dashboard. Quay về 8000ms cho các giá trị không hợp lệ (<1000) hoặc không phải số. |
| `OMNIROUTE_RELAY_FETCH_TIMEOUT_MS` | `25000` | Thời gian chờ fetch dành riêng cho relay trong `open-sse/utils/proxyFetch.ts` (#9158). Một relay bị treo phải thất bại trước thời gian chờ của client/agent (~30s) để phía gọi thấy lỗi dành riêng cho relay thay vì một lỗi timeout upstream chung chung. Giới hạn ở `29000` để nó luôn kích hoạt trước. |
| `OMNIROUTE_RETRY_BACKOFF_MS` | `10` | Độ trễ backoff khi thử lại dùng chung cho các đường thử-lại-một-lần direct/relay/proxy trong `open-sse/utils/proxyFetch.ts` (#9158). `0` = thử lại ngay lập tức. |
| `OMNIROUTE_CLAUDE_TLS_TIMEOUT_MS` | `60000` | Thời gian chờ yêu cầu gốc của wreq-js (`claudeTlsClient.ts`). |
| `OMNIROUTE_CLAUDE_TLS_GRACE_MS` | `10000` | Thời gian ân hạn hard-deadline tuyệt đối của JS được cộng thêm lên trên thời gian chờ gốc. |
| `OMNIROUTE_PPLX_TLS_TIMEOUT_MS` | `30000` | Thời gian chờ yêu cầu gốc của wreq-js (`perplexityTlsClient.ts`). |
| `OMNIROUTE_PPLX_TLS_GRACE_MS` | `10000` | Khoảng gia hạn hard-deadline tuyệt đối của JS, được cộng thêm vào timeout gốc. |
| `OMNIROUTE_PPLX_SEARCH_HINT` | `0` (tắt) | Thêm câu "You have built-in web search. Answer questions directly using search results." vào system message của phía gọi (`perplexity-web/protocol.ts`). Tắt theo mặc định — Perplexity vẫn tự tìm kiếm, và câu này có thể lộ vào các phản hồi dưới dạng meta-commentary đối với các coding client. Đặt `1`/`true`/`yes`/`on` để khôi phục. |
| `OMNIROUTE_GROK_TLS_TIMEOUT_MS` | `60000` | Timeout request wreq-js gốc (`grokTlsClient.ts`). |
| `OMNIROUTE_GROK_TLS_GRACE_MS` | `10000` | Khoảng gia hạn hard-deadline tuyệt đối của JS, được cộng thêm vào timeout gốc. |
| `OMNIROUTE_NOTION_TLS_TIMEOUT_MS` | `30000` | Timeout request wreq-js gốc (`notionTlsClient.ts`); `notion-web` nâng giá trị này lên `180000` theo từng request cho các lượt sinh dài. |
| `OMNIROUTE_NOTION_TLS_GRACE_MS` | `10000` | Khoảng gia hạn hard-deadline tuyệt đối của JS, được cộng thêm vào timeout gốc. |
| `OMNIROUTE_BROWSER_POOL` | `on` | Pool trình duyệt Playwright dùng chung cho chat web-cookie qua trình duyệt (`browserPool.ts`); đặt `off` để tắt. |
| `OBSCURA_BIN` | `auto-detect` | Đường dẫn tới binary `obscura` được browser pool và executor Cloudflare Playground dùng làm engine chính (`open-sse/services/obscura.ts`); tự động phát hiện từ PATH của hệ thống khi không được đặt. |
| `OBSCURA_CDP_ENDPOINT` | _(chưa đặt)_ | Trỏ tới một Obscura đang chạy sẵn (`http://host:port`) thay vì tự khởi chạy; module không sở hữu tiến trình đó (`open-sse/services/obscura.ts`). |
| `OBSCURA_PORT` | `random free port` | Cổng chỉ định rõ cho tiến trình `obscura serve` được khởi chạy; một cổng trống sẽ được chọn tự động khi không được đặt (`open-sse/services/obscura.ts`). |
| `WEB_COOKIE_USE_BROWSER` | `0` | Đưa một request chat web-cookie vào đường xử lý qua trình duyệt (`browserBackedChat.ts`); `1` để bật. |
| `KIMI_WEB_BASE_URL` | `https://www.kimi.ai` | URL cơ sở cho executor Kimi Web (Connect-RPC kimi.ai quốc tế) (`kimi-web.ts`); chỉ ghi đè cho các endpoint mirror/proxy. |
| `KIMI_WEB_CHAT_URL` | `/apiv2/kimi.gateway.chat.v1.ChatService/Chat` | Endpoint chat đầy đủ cho executor Kimi Web (`kimi-web.ts`). |
| `OMNIROUTE_LOGIN_BROWSER_PATH` | _(tự động phát hiện)_ | Đường dẫn tới file thực thi Chrome/Edge của hệ thống cho đăng nhập qua trình duyệt tương tác của Adobe Firefly (`adobeFireflyBrowserLogin.ts`); ghi đè cơ chế tự động phát hiện theo từng hệ điều hành. |
| `OMNIROUTE_STANDALONE_DIR` | _thư mục output standalone .build/_ | Ghi đè tại thời điểm build cho thư mục output standalone mà bước colocation sau build sử dụng (`scripts/build/colocate-standalone.mjs`); công cụ build, không phải runtime. |
Các lần thử target của combo kế thừa timeout request upstream đã được phân giải
(`FETCH_TIMEOUT_MS`, hoặc `REQUEST_TIMEOUT_MS` khi nó cung cấp giá trị mặc định cho fetch).
Chỉ đặt `targetTimeoutMs` trong một combo, trong cấu hình mặc định của combo, hoặc
provider override khi muốn fallback của combo nhanh hơn; các giá trị cao hơn timeout
upstream hiện tại sẽ bị chặn về bằng timeout upstream.
`comboTimeoutMs` là một ngân sách thời gian thực (wall-clock) riêng, áp cho toàn bộ combo
trên tất cả các target failover. Để trống hoặc đặt `0` để giữ việc lặp không giới hạn
(cơ chế dừng-treo 10 phút được hardcode trong `comboPredicates.ts` vẫn áp dụng).
Một giá trị dương sẽ thay thế cơ chế bảo vệ đó cho combo. Giữ `comboTimeoutMs` lớn hơn
`targetTimeoutMs` để failover vẫn còn thời gian sau khi target đầu tiên chạy chậm.
### Ngưỡng Circuit Breaker
Tinh chỉnh circuit breaker ở cấp provider. Các giá trị mặc định phản ánh các giá trị đã được scale và sử dụng từ v3.6 cho 500+ kết nối.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------------------------------- | --------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_CIRCUIT_BREAKER_OAUTH_THRESHOLD` | `8` | `open-sse/config/constants.ts` | Ngưỡng số lần lỗi liên tiếp đối với các nhà cung cấp OAuth trước khi cầu dao (circuit breaker) ngắt. |
| `OMNIROUTE_CIRCUIT_BREAKER_OAUTH_RESET_MS` | `60000` | `open-sse/config/constants.ts` | Cửa sổ đặt lại (ms) cho cầu dao của nhà cung cấp OAuth. |
| `OMNIROUTE_CIRCUIT_BREAKER_API_KEY_THRESHOLD` | `12` | `open-sse/config/constants.ts` | Ngưỡng số lần lỗi liên tiếp đối với các nhà cung cấp dùng API key. |
| `OMNIROUTE_CIRCUIT_BREAKER_API_KEY_RESET_MS` | `30000` | `open-sse/config/constants.ts` | Cửa sổ đặt lại (ms) cho cầu dao của nhà cung cấp dùng API key. |
| `OMNIROUTE_CIRCUIT_BREAKER_LOCAL_THRESHOLD` | `2` | `open-sse/config/constants.ts` | Ngưỡng số lần lỗi liên tiếp đối với các nhà cung cấp cục bộ (Ollama, LM Studio, ...). |
| `OMNIROUTE_CIRCUIT_BREAKER_LOCAL_RESET_MS` | `15000` | `open-sse/config/constants.ts` | Cửa sổ đặt lại (ms) cho cầu dao của nhà cung cấp cục bộ. |
| `OMNIROUTE_PROVIDER_BREAKER_OAUTH_FAILURE_THRESHOLD` | `10` | `open-sse/config/constants.ts` | Cầu dao cấp nhà cung cấp: số lần lỗi trong cửa sổ trước khi toàn bộ nhà cung cấp OAuth bước vào giai đoạn tạm ngưng (cooldown). |
| `OMNIROUTE_PROVIDER_BREAKER_OAUTH_FAILURE_WINDOW_MS` | `900000` | `open-sse/config/constants.ts` | Cầu dao cấp nhà cung cấp: cửa sổ trượt đếm số lần lỗi (ms) đối với các nhà cung cấp OAuth. |
| `OMNIROUTE_PROVIDER_BREAKER_OAUTH_COOLDOWN_MS` | `300000` | `open-sse/config/constants.ts` | Cầu dao cấp nhà cung cấp: thời gian tạm ngưng (ms) khi đạt ngưỡng của nhà cung cấp OAuth. |
| `OMNIROUTE_PROVIDER_BREAKER_OAUTH_DEGRADATION_THRESHOLD` | `5` | `open-sse/config/constants.ts` | Nhà cung cấp OAuth chuyển sang trạng thái DEGRADED khi số lần lỗi đạt mức này. |
| `OMNIROUTE_PROVIDER_BREAKER_OAUTH_MAX_BACKOFF_MULTIPLIER` | `8` | `open-sse/config/constants.ts` | Hệ số leo thang resetTimeout tối đa của nhà cung cấp OAuth. |
| `OMNIROUTE_PROVIDER_BREAKER_OAUTH_BACKOFF_ESCALATION_COUNT` | `2` | `open-sse/config/constants.ts` | Nhà cung cấp OAuth leo thang sau số chu kỳ mở này. |
| `OMNIROUTE_PROVIDER_BREAKER_API_KEY_FAILURE_THRESHOLD` | `15` | `open-sse/config/constants.ts` | Cầu dao cấp nhà cung cấp: số lần lỗi trong cửa sổ trước khi toàn bộ nhà cung cấp dùng API key bước vào giai đoạn tạm ngưng. |
| `OMNIROUTE_PROVIDER_BREAKER_API_KEY_FAILURE_WINDOW_MS` | `1800000` | `open-sse/config/constants.ts` | Cầu dao cấp nhà cung cấp: cửa sổ trượt đếm số lần lỗi (ms) đối với các nhà cung cấp dùng API key. |
| `OMNIROUTE_PROVIDER_BREAKER_API_KEY_COOLDOWN_MS` | `600000` | `open-sse/config/constants.ts` | Cầu dao cấp nhà cung cấp: thời gian tạm ngưng (ms) khi đạt ngưỡng của nhà cung cấp dùng API key. |
| `OMNIROUTE_PROVIDER_BREAKER_API_KEY_DEGRADATION_THRESHOLD` | `7` | `open-sse/config/constants.ts` | Nhà cung cấp dùng API key chuyển sang trạng thái DEGRADED khi số lần lỗi đạt mức này. |
| `OMNIROUTE_PROVIDER_BREAKER_API_KEY_MAX_BACKOFF_MULTIPLIER` | `4` | `open-sse/config/constants.ts` | Hệ số leo thang resetTimeout tối đa của nhà cung cấp dùng API key. |
| `OMNIROUTE_PROVIDER_BREAKER_API_KEY_BACKOFF_ESCALATION_COUNT` | `3` | `open-sse/config/constants.ts` | Nhà cung cấp dùng API key leo thang sau số chu kỳ mở này. |
| `OMNIROUTE_PROVIDER_BREAKER_LOCAL_FAILURE_THRESHOLD` | `2` | `open-sse/config/constants.ts` | Cầu dao cấp nhà cung cấp: số lần lỗi trước khi toàn bộ nhà cung cấp cục bộ bước vào giai đoạn tạm ngưng. |
| `OMNIROUTE_PROVIDER_BREAKER_LOCAL_FAILURE_WINDOW_MS` | `300000` | `open-sse/config/constants.ts` | Cầu dao cấp nhà cung cấp: cửa sổ trượt đếm số lần lỗi (ms) đối với các nhà cung cấp cục bộ. |
| `OMNIROUTE_PROVIDER_BREAKER_LOCAL_COOLDOWN_MS` | `60000` | `open-sse/config/constants.ts` | Cầu dao cấp nhà cung cấp: thời gian tạm ngưng (ms) khi đạt ngưỡng của nhà cung cấp cục bộ. |
| `OMNIROUTE_API_KEY_COOLDOWN_MS` | `60000` | `open-sse/services/apiKeyRotator.ts` | Thời gian tạm ngưng (ms) cho từng key do cơ chế luân chuyển nhiều API key áp dụng khi phản hồi 429 từ upstream không kèm `Retry-After` (#14573). Giá trị không dương hoặc không phải số sẽ quay về giá trị mặc định. |
| `PIN_DROP_BACKOFF_LEVEL` | `2` | `open-sse/services/combo.ts` | Độ sâu backoff mà tại đó nhà cung cấp của một pin context-cache được coi là không lành mạnh lâu dài và pin bị loại bỏ để chuyển sang dự phòng (failover). |
| `PIN_DROP_GRACE_MS` | `20000` | `open-sse/services/combo.ts` | Cửa sổ chống rung (ms) cho phép chịu đựng các đợt tạm ngưng ngắn thoáng qua trước khi loại bỏ một pin context-cache. |
### Kịch bản
| Kịch bản | Cấu hình |
| --------------------------------------------- | ------------------------------------------------------- |
| **Sinh mã chạy dài** | `REQUEST_TIMEOUT_MS=900000` (15 phút) |
| **Giới hạn tổng thời gian tồn tại của luồng** | `STREAM_ACTIVE_TIMEOUT_MS=1260000` (21 phút) |
| **Fail nhanh cho API production** | `API_BRIDGE_PROXY_TIMEOUT_MS=10000` |
| **Các mô hình extended thinking** | `STREAM_IDLE_TIMEOUT_MS=300000` (5 phút giữa các chunk) |
---
## 16. Ghi nhật ký
Hệ thống ghi nhật ký ghi vào cả stdout và các tệp nhật ký được xoay vòng. Toàn bộ cấu hình được đọc bởi `src/lib/logEnv.ts`.
| Biến | Mặc định | Mô tả |
| ----------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `APP_LOG_LEVEL` | `info` | Mức nhật ký tối thiểu: `debug`, `info`, `warn`, `error`. |
| `APP_LOG_FORMAT` | `text` | Định dạng đầu ra: `text` (con người có thể đọc được) hoặc `json` (có cấu trúc). |
| `APP_LOG_TO_FILE` | `true` | Ghi nhật ký vào tệp bên cạnh stdout. |
| `APP_LOG_FILE_PATH` | `logs/application/app.log` | Đường dẫn tệp nhật ký (tương đối với thư mục gốc của dự án hoặc `DATA_DIR`). |
| `APP_LOG_MAX_FILE_SIZE` | `50M` | Kích thước tệp tối đa trước khi xoay vòng. Chấp nhận: `50M`, `1G`, `512K` hoặc số byte thuần túy. |
| `APP_LOG_RETENTION_DAYS` | `7` | Số ngày lưu giữ các tệp nhật ký ứng dụng đã xoay vòng. |
| `APP_LOG_MAX_FILES` | `20` | Số lượng bản sao lưu tệp nhật ký đã xoay vòng tối đa. |
| `CALL_LOG_RETENTION_DAYS` | `7` | Số ngày lưu giữ các mục nhật ký yêu cầu/lệnh gọi trong cơ sở dữ liệu. |
| `CALL_LOG_MAX_ENTRIES` | `10000` | Số lượng mục nhật ký lệnh gọi tối đa trong bộ đệm trong bộ nhớ. |
| `CALL_LOGS_TABLE_MAX_ROWS` | `100000` | Số hàng tối đa trong bảng SQLite `call_logs` trước khi lược bỏ. |
| `ENABLE_REQUEST_LOGS` | _(chưa đặt)_ | Buộc bật hoặc tắt ghi nhật ký yêu cầu chi tiết, ghi đè cài đặt trên bảng điều khiển. |
| `MAX_PENDING_REQUEST_AGE_MS` | `3600000` (1 giờ) | Tuổi tối đa của các mục nhật ký yêu cầu đang hoạt động bị bỏ rơi trước khi dọn dẹp khỏi bộ nhớ. |
| `CALL_LOG_PIPELINE_CAPTURE_STREAM_CHUNKS` | `false` | Lưu các phân đoạn luồng trong cấu phần quy trình khi `call_log_pipeline_enabled=true`. Phải chủ động bật (`true`) — mặc định tắt để tiết kiệm dung lượng đĩa. |
| `CALL_LOG_PIPELINE_MAX_SIZE_KB` | `512` | Kích thước tối đa tính bằng KB của cấu phần nhật ký lệnh gọi trong quy trình khi `call_log_pipeline_enabled=true`. |
| `PROXY_LOGS_TABLE_MAX_ROWS` | `100000` | Số hàng tối đa trong bảng SQLite `proxy_logs` trước khi lược bỏ. |
| `PROXY_LOG_INCLUDE_IPS` | `false` | Bao gồm IP máy khách/đầu ra và tiền tố tài khoản trong nhật ký bảng điều khiển `[ProxyEgress]`. Các bản ghi nhật ký proxy trên bảng điều khiển/trong cơ sở dữ liệu vẫn giữ lại đầy đủ thông tin chi tiết. |
| `PROXY_LOG_FIRST_CHUNK_TIMING` | `false` | Đặt thành `"true"` hoặc `"1"` để ghi lại `first_chunk_ms` (từ lúc bắt đầu gửi đến byte nội dung hữu ích đầu tiên) trên các hàng nhật ký proxy. Bao bọc mỗi nội dung đầu vào bằng một luồng truyền xuyên lười và cập nhật hàng khi byte đến; mặc định tắt để phản hồi được truyền qua mà không bị thay đổi. |
| `APP_LOG_ROTATION_CHECK_INTERVAL_MS` | `60000` (1 phút) | Tần suất `src/lib/logRotation.ts` kiểm tra lại kích thước tệp nhật ký đang hoạt động. |
| `CHAT_LOG_TEXT_LIMIT` | `65536` | Độ dài chuỗi tối đa được giữ lại trong các cấu phần nhật ký trò chuyện (mặc định 64 KB). |
| `CHAT_LOG_ARRAY_TAIL_ITEMS` | `128` | Số lượng phần tử mảng được giữ lại từ cuối mảng khi cắt bớt tải trọng nhật ký trò chuyện. |
| `CHAT_LOG_MAX_DEPTH` | `6` | Độ sâu lồng nhau tối đa trước khi tải trọng nhật ký trò chuyện bị cắt bớt. |
| `CHAT_LOG_MAX_OBJECT_KEYS` | `80` | Số lượng khóa đối tượng tối đa được giữ lại trong tải trọng nhật ký trò chuyện (0 = không giới hạn). |
| `CHAT_LOG_MAX_BODY_KB` | `1024` | Kích thước toàn bộ nội dung yêu cầu/phản hồi (KB) mà khi vượt quá, nội dung sẽ được thay thế bằng một bản tóm tắt đơn giản thay vì bản sao đầy đủ. Hãy tăng giá trị này nếu các cuộc hội thoại tác tử dài hiển thị phần giữ chỗ thay vì các tin nhắn thực trên bảng điều khiển. |
| `CHAT_DEBUG_FILE` | `false` | Khi là true, `serializeArtifactForStorage` bỏ qua việc cắt bớt dựa trên kích thước. Chỉ dùng để gỡ lỗi. |
---
## 17. Tối ưu hóa bộ nhớ
| Biến | Mặc định | Mô tả |
| ----------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_MEMORY_MB` | _tự động_ (bare metal); **`1024` trong image Docker** | Giới hạn heap V8 **khuyến nghị** cho Docker/standalone (MB). Khi không được đặt, được hiệu chỉnh động (~35% RAM hệ thống, giới hạn trong khoảng `[512, 4096]`); `512` chỉ là mức sàn khi không đọc được tổng bộ nhớ. Trên `run-standalone.mjs` (Docker CMD), một giá trị **tường minh** được thêm vào dưới dạng `--max-old-space-size` và **thắng** so với flag heap NODE_OPTIONS xung đột (flag cuối cùng của V8 có hiệu lực). `omniroute serve` vẫn ưu tiên heap NODE_OPTIONS hiện có (#5238). Không đặt cả hai với các số khác nhau — tiến trình sẽ ghi log cảnh báo nêu rõ cả hai giá trị và giá trị thắng. **Image Docker chính thức luôn đặt `1024`, nên việc hiệu chỉnh không bao giờ chạy ở đó.** Coding-agent `/v1/responses` cần `8192`–`12288` cộng thêm khoảng dự phòng cgroup — xem [Hướng dẫn Docker — RAM runtime](../guides/DOCKER_GUIDE.md#runtime-ram-for-coding-agents). |
| `OMNIROUTE_RSS_PRESSURE_MB` | _tự động_ (`max(3072, 2 × OMNIROUTE_MEMORY_MB)`; tắt khi `OMNIROUTE_MEMORY_MB` không được đặt) | `open-sse/utils/resourcePressure.ts` | Cầu chì RSS tiến trình tuyệt đối (MB) cho bộ nhớ native/bên ngoài mà `heapUsed` của V8 không nhìn thấy; khi vượt ngưỡng, các request mới sẽ nhận 503 `resource_pressure`. RSS hiếm khi giảm sau một đợt tăng đột biến, nên hãy kết hợp với `OMNIROUTE_PRESSURE_SELF_RESTART`. |
| `PROMPT_CACHE_MAX_SIZE` | `50` | Số mục prompt hệ thống được cache tối đa. |
| `PROMPT_CACHE_MAX_BYTES` | `2097152` (2 MB) | Tổng dung lượng cache prompt tối đa. |
| `PROMPT_CACHE_TTL_MS` | `300000` (5 phút) | TTL của mục cache prompt. |
| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Số phản hồi temperature=0 được cache tối đa. |
| `SEMANTIC_CACHE_MAX_BYTES` | `4194304` (4 MB) | Tổng dung lượng cache ngữ nghĩa tối đa. |
| `SEMANTIC_CACHE_TTL_MS` | `1800000` (30 phút) | TTL của mục cache ngữ nghĩa. |
| `OMNIROUTE_CORPUS_CACHE_SIZE` | `5` | Số root corpus cục bộ đồng thời giữ một chỉ mục trong bộ nhớ đang hoạt động (`src/lib/localCorpus/configured.ts`). LRU: khi đạt giới hạn, chỉ mục của root ít được dùng gần đây nhất sẽ bị loại bỏ và được xây dựng lại ở truy vấn tiếp theo. Giới hạn tối thiểu là `1`; giá trị không phải số sẽ quay về mặc định. |
| `STREAM_HISTORY_MAX` | `50` | Số sự kiện stream gần đây tối đa trong bộ đệm xem trực tiếp của Dashboard. |
| `CONTEXT_LENGTH_DEFAULT` | _(chưa đặt)_ | Ghi đè độ dài ngữ cảnh toàn cục (token) cho mọi provider không có biến `CONTEXT_LENGTH_`. Khi được đặt, nó **thay thế** các giá trị catalog, ghi đè dashboard và registry cho các provider đó; khi không đặt, OmniRoute dùng chuỗi tích hợp sẵn của mình, với phương án cuối cùng là `128000`. Xem [Độ dài ngữ cảnh theo provider](#per-provider-context-length-context_length_provider). |
| `USAGE_TOKEN_BUFFER` | `100` | Khoảng token dự phòng bổ sung khi theo dõi hạn ngạch sử dụng. |
### Độ dài ngữ cảnh theo provider (`CONTEXT_LENGTH_`)
`open-sse/services/contextManager.ts` (`getEnvOverride()` / `resolveTokenLimit()`) cũng đọc một
dạng **theo provider** có tên được tạo từ provider ID tại runtime, vì vậy không thể
liệt kê từng hàng trong bảng trên hoặc trong `.env.example`.
**Tên.** `CONTEXT_LENGTH_`, trong đó `` là ID nhà cung cấp được viết hoa, với
mọi ký tự ngoài `A-Z` / `0-9` được thay bằng `_`. ID nhà cung cấp là ID chuẩn sau khi
phân giải bí danh (phần `provider` của chuỗi `provider/model` sau khi một bí danh ngắn đã được
phân giải). Các node tùy chỉnh tương thích OpenAI hoặc Anthropic dùng node ID được sinh ra, vì vậy
UUID là một phần của tên biến. Giá trị là một số nguyên dương chỉ số token; mọi giá trị
khác (rỗng, `0`, âm, không phải số) đều bị bỏ qua và quá trình phân giải chuyển sang bước tiếp theo.
| ID nhà cung cấp | Tên biến |
| ----------------------------------------------------------- | -------------------------------------------------------------------------- |
| agentrouter | CONTEXT_LENGTH_AGENTROUTER |
| openrouter | CONTEXT_LENGTH_OPENROUTER |
| openai-compatible-chat-0f8e2c1a-5b7d-4e3f-9a6c-2d1b8e4f7a90 | CONTEXT_LENGTH_OPENAI_COMPATIBLE_CHAT_0F8E2C1A_5B7D_4E3F_9A6C_2D1B8E4F7A90 |
**Thứ tự ưu tiên.** Với một cặp `provider/model`, bước đầu tiên cho ra giá trị sẽ thắng:
1. `CONTEXT_LENGTH_` cho nhà cung cấp đó.
2. `CONTEXT_LENGTH_DEFAULT` (ghi đè môi trường toàn cục).
3. Cửa sổ theo từng model: một ghi đè context đã được lưu (đặt trong dashboard, hoặc được
discovery reconciler tự động ghim, xem `CONTEXT_WINDOW_RECONCILE_INTERVAL`), nếu không thì dùng
giá trị từ catalog đã đồng bộ / models.dev.
4. `defaultContextLength` trong registry của nhà cung cấp.
5. Heuristic theo tên model (`claude` 200000, `gemini` 1000000, `gpt` / `o1` / `o3` / `o4` /
`codex` 400000).
6. Mặc định tích hợp sẵn theo từng nhà cung cấp, rồi đến `128000`.
Cả hai bước môi trường đều áp dụng cho **toàn bộ nhà cung cấp**: mọi model của nhà cung cấp đó nhận
cùng một giới hạn, và chúng thắng các ghi đè theo model trong dashboard. Khi chỉ một model của nhà cung cấp
cần một cửa sổ khác, hãy dùng ghi đè theo model trong dashboard.
**Phạm vi.** Chuỗi này điều khiển việc kiểm tra cửa sổ context lúc request (lỗi từ chối
`context_length_exceeded` / "Input exceeds context window" trong
`open-sse/handlers/chatCore.ts`), ngân sách nén prompt và giới hạn context của combo. Giá trị
`context_length` mà `GET /v1/models` công bố vẫn có thể đến từ metadata của catalog hoặc registry
và không được đảm bảo phản ánh ghi đè môi trường.
**Ví dụ.** Một nhà cung cấp có model chấp nhận cửa sổ 1.050.000 token trong khi catalog báo
128.000:
```dotenv
CONTEXT_LENGTH_AGENTROUTER=1050000
```
Khởi động lại server sau khi thay đổi: giá trị được đọc từ môi trường của tiến trình server.
Trên **ứng dụng desktop**, server chạy như một tiến trình con và không thấy biến hệ thống
được đặt sau khi ứng dụng đã khởi chạy; hãy đặt dòng đó trong file `.env` mà ứng dụng tải (thứ tự tra cứu trong
[Hướng dẫn Electron: Tra cứu file môi trường](../guides/ELECTRON_GUIDE.md#environment-file-lookup)),
rồi thoát hẳn và khởi chạy lại ứng dụng.
### Nén
| Biến | Mặc định | Mô tả |
| ------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_RTK_TRUST_PROJECT_FILTERS` | chưa đặt | Tin tưởng `.rtk/filters.json` của dự án mà không cần hash `.rtk/trust.json`. Chỉ dùng trong phát triển local có kiểm soát. |
### Memory Engine (kế hoạch 21)
### Chi phí event loop của memory, skills và token refresh (#10349)
OmniRoute là **một tiến trình Node duy nhất**. Việc trích xuất/truy xuất memory, chèn skills và làm mới token của nhà cung cấp chạy trên **cùng một event loop** với `GET /healthz` và dashboard. Chúng không phải là worker thread.
| Tác vụ | Mã nguồn | Mặc định | Kiểm soát bởi người vận hành |
| ----------------------------- | ---------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Trích xuất / truy xuất memory | `src/lib/memory/` | **memoryEnabled** trong dashboard (mặc định bật) | Tắt trong **Settings → Memory**. Không có công tắc env riêng nào ngoài việc tắt tính năng trong cài đặt. |
| Chèn skills | `src/lib/skills/injection.ts` | **skillsEnabled** trong dashboard (mặc định bật) | Tắt trong **Settings → Memory/Skills** (`skillsEnabled`). Các núm sandbox bên dưới chỉ giới hạn việc thực thi sau khi việc chèn đã được bật. |
| Làm mới token | `src/sse/services/tokenRefresh.ts` | Bật cho các nhà cung cấp OAuth/web đã kết nối | Ngắt kết nối nhà cung cấp hoặc để token tiếp tục còn hiệu lực; hiện chưa có env `TOKEN_REFRESH=0`. |
Nếu `/healthz` chậm trên một máy đang rảnh, hãy tắt memory + skills trước, rồi kiểm tra tải của catalog/nén (#10303, #9685). Các tính năng này có nhường tại các điểm `await` nhưng vẫn tranh chấp trên cùng một thread.
Các núm điều chỉnh tầng embedding, vector store và reranking cho hệ thống con bộ nhớ bền (`src/lib/memory/`).
| Biến | Mặc định | Mô tả |
| ------------------------------------ | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MEMORY_EMBEDDING_CACHE_TTL_MS` | `300000` (5 phút) | TTL cho bộ nhớ cache embedding trong RAM (theo chữ ký nguồn/mô hình/số chiều). |
| `MEMORY_EMBEDDING_CACHE_MAX` | `1000` | Số mục LRU tối đa được giữ trong bộ nhớ cache embedding. |
| `MEMORY_TRANSFORMERS_MODEL` | `Xenova/all-MiniLM-L6-v2` | ID repo HF cho pipeline MiniLM cục bộ dạng opt-in `@huggingface/transformers` (~23 MB int8, ~400 MB RAM). |
| `MEMORY_STATIC_MODEL` | `minishlab/potion-base-8M` | ID repo HF cho bộ tạo embedding bảng tra cứu tĩnh potion/Model2Vec. Được tải lười (lazy) vào thư mục cache. |
| `MEMORY_STATIC_CACHE_DIR` | `/embeddings` | Thư mục dùng để cache các tệp mô hình potion tĩnh. Mặc định nằm dưới `DATA_DIR` khi chưa được đặt. |
| `HF_HUB_ENDPOINT` | `https://huggingface.co` | Ghi đè URL cơ sở của Hugging Face Hub được `staticPotion.ts` sử dụng (ví dụ: endpoint mirror cho các môi trường air-gapped). |
| `MEMORY_VEC_TOP_K` | `20` | Top-K mặc định được tìm kiếm vector brute-force của `sqlite-vec` sử dụng bên trong `src/lib/memory/vectorStore.ts`. |
| `MEMORY_RRF_K` | `60` | Hằng số `k` của Reciprocal Rank Fusion cho truy xuất lai FTS5 + vector (công thức sqlite-vec). |
| `VECTOR_STORE_DISABLE_VEC` | `false` | Điểm nối kiểm thử/chẩn đoán trong `getVectorStore()` (`src/lib/memory/vectorStore.ts`): khi là `true`, buộc vector store thành `null` (mô phỏng môi trường cloud/WASM không có `sqlite-vec`), hạ cấp truy xuất bộ nhớ xuống tìm kiếm từ khóa FTS5. Không đặt giá trị này trong môi trường production. |
| `NOTION_API_KEY` | _(chưa đặt)_ | Khóa API cho backend Notion (được preset backend có sẵn trong `genericBackend.ts` sử dụng). |
| `NOTION_API_URL` | `https://api.notion.com/v1` | URL cơ sở cho Notion API (có thể ghi đè cho các phương án thay thế Notion tự lưu trữ). |
| `OBSIDIAN_API_KEY` | _(chưa đặt)_ | Khóa API cho backend Obsidian Vault (được preset backend có sẵn trong `genericBackend.ts` sử dụng). |
| `OBSIDIAN_API_URL` | `http://localhost:27123` | URL cơ sở cho Obsidian Vault API (có thể ghi đè cho vault từ xa). |
| `MEMORY_TYPED_DECAY_ENABLED` | `false` | Công tắc chính cho cơ chế suy giảm bộ nhớ có kiểu TV6. **Opt-in (mặc định tắt)** — quá trình quét **xóa** các bộ nhớ đã suy giảm. Khi tắt, `access_count`/`last_accessed_at` chỉ là dữ liệu telemetry thuần túy và không có gì bị xóa. |
| `MEMORY_TYPED_DECAY_EPISODIC_DAYS` | `30` | TTL (ngày) sau đó một bộ nhớ `episodic` không được dùng sẽ suy giảm. `0` cũng khiến episodic được miễn. Các kiểu bền vững (`factual`/`procedural`/`semantic`) luôn được miễn. Đồng hồ suy giảm được đặt lại mốc dựa trên `last_accessed_at`. |
| `MEMORY_TYPED_DECAY_ACCESS_IMMUNITY` | `3` | Một bộ nhớ được chèn `>=` số lần này sẽ được miễn suy giảm bất kể kiểu. `0` vô hiệu hóa miễn truy cập. |
| `MEMORY_TYPED_DECAY_SWEEP_INTERVAL` | `0` (tắt) | Khoảng thời gian (giây) cho quá trình quét suy giảm định kỳ tùy chọn trong `src/lib/memory/typedDecay.ts`. `0`/chưa đặt = không quét định kỳ. Opt-in kép: cũng yêu cầu `MEMORY_TYPED_DECAY_ENABLED=true`. |
| `OMNIROUTE_STRICT_SYSTEM_PROVIDERS` | _(chưa đặt)_ | Danh sách ID provider phân tách bằng dấu phẩy (không phân biệt hoa thường) chỉ chấp nhận tin nhắn `system` **tại index 0** (`src/lib/memory/injection.ts`). Với các provider này, việc chèn bộ nhớ vào giữa mảng (an toàn với cache) là không an toàn trong các cuộc hội thoại nhiều lượt, nên bộ nhớ được hợp nhất/thêm vào đầu thành tin nhắn system dẫn đầu. Mặc định chỉ có `xiaomi-mimo`/`mimo`; hãy mở rộng cho các endpoint tự lưu trữ tương thích OpenAI (ví dụ: Qwen3.5+/3.6) có chat template áp dụng cùng ràng buộc chỉ một tin nhắn system dẫn đầu. |
### Ví dụ Docker cho máy RAM thấp
`128` chỉ dành cho dashboard. Các coding agent chạy trên heap này sẽ gặp `FATAL ERROR` trong các `/v1/responses` dài. Không dùng ví dụ này làm gateway cho Claude/Codex/Grok.
```bash
OMNIROUTE_MEMORY_MB=128
PROMPT_CACHE_MAX_SIZE=20
PROMPT_CACHE_MAX_BYTES=524288 # 512 KB
SEMANTIC_CACHE_MAX_SIZE=25
SEMANTIC_CACHE_MAX_BYTES=1048576 # 1 MB
STREAM_HISTORY_MAX=10
```
---
## 18. Đồng bộ giá
Tự động đồng bộ dữ liệu giá mô hình từ các nguồn bên ngoài.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ----------------------- | ------------- | ------------------------ | ----------------------------------------------- |
| `PRICING_SYNC_ENABLED` | `false` | `src/lib/pricingSync.ts` | Cho phép bật tính năng đồng bộ giá định kỳ. |
| `PRICING_SYNC_INTERVAL` | `86400` (24h) | `src/lib/pricingSync.ts` | Khoảng thời gian đồng bộ tính bằng giây. |
| `PRICING_SYNC_SOURCES` | `litellm` | `src/lib/pricingSync.ts` | Các nguồn dữ liệu được phân tách bằng dấu phẩy. |
---
## Đồng bộ ELO của Arena
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ---------------------------- | ------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ARENA_ELO_SYNC_ENABLED` | `true` | `src/shared/constants/featureFlagDefinitions.ts` | Đồng bộ ELO định kỳ từ bảng xếp hạng Arena AI, có thể cấu hình trong phần Feature Flags của Dashboard hoặc đặt thành `false` để tắt. |
| `MODELS_CATALOG_PREFIX_MODE` | `dual` | `src/shared/constants/featureFlagDefinitions.ts`, `src/app/api/v1/models/catalog.ts` | Dạng tiền tố được dùng cho ID mô hình trong `GET /v1/models`. `dual` công bố cả tiền tố bí danh ngắn và tiền tố nhà cung cấp chính tắc cho mọi mô hình (để tương thích ngược — gần như làm số lượng mục trong danh mục tăng gấp đôi); `alias` xuất một ID cho mỗi mô hình; `canonical` chỉ xuất tiền tố ID đầy đủ của nhà cung cấp (các nhà cung cấp có bí danh vốn đã là ID chính tắc sẽ giữ nguyên một mục duy nhất). Máy khách có thể ghi đè theo từng yêu cầu bằng `?prefix=alias`. Xem [API_REFERENCE](API_REFERENCE.md#model-id-prefixes-prefix). |
| `ARENA_ELO_SYNC_INTERVAL` | `86400` (24h) | `src/lib/arenaEloSync.ts` | Khoảng thời gian đồng bộ tính bằng giây. |
---
## Nhà cung cấp PromptQL Playground (Không chính thức/Thử nghiệm)
Cầu nối phiên GraphQL được thiết kế ngược cho prompt.ql.app (`src/shared/constants/providers/web-cookie.ts`). Tất cả đều là tùy chọn — các giá trị mặc định trỏ đến những endpoint playground công khai; chỉ ghi đè khi sử dụng một bản triển khai PromptQL tự lưu trữ hoặc thay thế.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ---------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `PROMPTQL_GRAPHQL_ENDPOINT` | `https://data.prompt.ql.app/promptql/playground-v2-hge/v1/graphql` | `open-sse/executors/promptql.ts` | Endpoint GraphQL được dùng cho các thao tác trò chuyện/phiên. |
| `PROMPTQL_CREDITS_ENDPOINT` | `https://data.pro.ql.app/v1/graphql` | `open-sse/executors/promptql.ts`, `open-sse/services/usage/promptql.ts` | Endpoint GraphQL được dùng để truy vấn số dư/mức sử dụng tín dụng. |
| `PROMPTQL_TOKEN_REFRESH_URL` | `https://auth.pro.ql.app/ddn/project/token` | `open-sse/executors/promptql.ts` | Endpoint được dùng để cố gắng làm mới token. |
| `PROMPTQL_POLL_TIMEOUT_MS` | `180000` | `open-sse/executors/promptql.ts` | Thời gian tối đa (ms) để thăm dò `thread_events` trước khi hết thời gian chờ. |
---
## Nhà cung cấp web HyperAgent (Không chính thức/Thử nghiệm)
Cầu nối phiên được thiết kế ngược cho hyperagent.com (`src/shared/constants/providers/web-cookie.ts`). Không bắt buộc — mặc định trỏ đến endpoint thanh toán/mức sử dụng công khai; chỉ ghi đè đối với bản triển khai HyperAgent tự lưu trữ/thay thế.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ---------------------- | --------------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------- |
| `HYPERAGENT_USAGE_URL` | `https://hyperagent.com/api/settings/billing/usage` | `open-sse/services/usage/hyperagent.ts` | Endpoint dùng để truy xuất các khối tín dụng thanh toán/mức sử dụng. |
---
## Hạn mức sử dụng Kilo Code
Tra cứu số dư USD cá nhân và mức sử dụng Kilo Pass cho nhà cung cấp Kilo Code. Không bắt buộc — mặc định trỏ đến Kilo API công khai; chỉ ghi đè đối với relay/fixture kiểm thử. Quá trình xác thực sử dụng mã thông báo truy cập OAuth hiện có của kết nối.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| -------------- | --------------------- | ------------------------------------- | ----------------------------------------------------------------------------- |
| `KILO_API_URL` | `https://api.kilo.ai` | `open-sse/services/usage/kilocode.ts` | URL cơ sở dùng để truy xuất số dư Kilo Code cá nhân và mức sử dụng Kilo Pass. |
---
## Nhà cung cấp web Adobe Firefly (Không chính thức/Thử nghiệm)
Làm mới phiên thông qua trình duyệt cho nhà cung cấp web Adobe Firefly
(`open-sse/services/adobeFireflyBrowserLogin.ts`, `open-sse/services/adobeFireflySession.ts`,
`open-sse/services/adobeFireflyClient.ts`). Không bắt buộc — tất cả giá trị mặc định đều được tinh chỉnh
cho bản cài đặt máy tính để bàn thông thường.
> **Đã bị loại bỏ trong #9255.** Môi trường chạy Chrome cũ được đính kèm qua CDP (adobeFireflyChromeRuntime.ts) đã
> được thay thế bằng dịch vụ đăng nhập qua trình duyệt Playwright và các tùy chọn cấu hình của nó không còn tồn tại. Các biến
> ADOBE_FIREFLY_CHROME_ CDP_PORT / VISIBLE / HEADED / PING / FORCE_RESTART, cùng với
> ADOBE_FIREFLY_LOGIN_WAIT_MS và ADOBE_FIREFLY_FORTER_WAIT_MS, không được đọc ở bất kỳ đâu trong
> cơ sở mã — việc thiết lập chúng không có tác dụng.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------ | ------------ | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `ADOBE_FIREFLY_CHROME_HEADLESS` | `0` | `open-sse/services/adobeFireflyBrowserLogin.ts` | Đặt thành `1` để sử dụng Chrome headless thực sự (được biết là không hoạt động với thao tác tạo; chỉ dùng để gỡ lỗi). |
| `ADOBE_FIREFLY_BROWSER_REFRESH` | `1` | `open-sse/services/adobeFireflySession.ts` | Bật/tắt chủ động làm ấm trình duyệt. `0` tắt làm ấm chủ động (khôi phục lỗi 408 giữa lô vẫn được áp dụng). |
| `ADOBE_FIREFLY_SESSION_DISK` | `1` | `open-sse/services/adobeFireflySession.ts` | Đặt thành `0` để tắt việc lưu phiên Adobe Firefly vào ổ đĩa. |
| `ADOBE_FIREFLY_MIN_SUBMIT_GAP_MS` | _(chưa đặt)_ | `open-sse/services/adobeFireflySession.ts` | Khoảng cách tối thiểu (ms) bắt buộc giữa các lần gửi liên tiếp, ghi đè giá trị mặc định tích hợp sẵn. |
| `ADOBE_FIREFLY_BATCH_EXTRA_GAP_MS` | _(chưa đặt)_ | `open-sse/services/adobeFireflySession.ts` | Khoảng cách bổ sung (ms) được thêm sau một lô thành công, ghi đè giá trị mặc định tích hợp sẵn. |
| `ADOBE_FIREFLY_SUBMIT_BASE_DELAY_MS` | _(chưa đặt)_ | `open-sse/services/adobeFireflyClient.ts` | Độ trễ cơ sở (ms) trước khi gửi yêu cầu tạo, ghi đè giá trị mặc định tích hợp sẵn. |
---
## 19. Đồng bộ mô hình (Dev)
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ----------------------------------- | ------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MODELS_DEV_SYNC_ENABLED` | _(chưa đặt)_ | `src/lib/modelsDevSync.ts` | Ghi đè cứng việc đồng bộ giá từ models.dev. Chưa đặt = tuân theo Cài đặt > AI (`modelsDevSyncEnabled`). `0`/`false`/`off`/`no` **được ưu tiên hơn DB** và bỏ qua cả đồng bộ định kỳ lẫn các lần quét SQL/JSON của `getModelsDevPricing()` (dùng để khôi phục khi bảng điều khiển bị treo trên cùng một vòng lặp sự kiện). `1`/`true`/`on`/`yes` buộc bật đồng bộ. Việc lưu/xóa giá vẫn gọi `backupDbFile("pre-write")`; thao tác này không làm gì khi đang trong khoảng giới hạn 60 phút hoặc khi có `DISABLE_SQLITE_AUTO_BACKUP`. |
| `MODELS_DEV_SYNC_INTERVAL` | `86400` (24h) | `src/lib/modelsDevSync.ts` | Khoảng thời gian đồng bộ danh mục mô hình trong quá trình phát triển, tính bằng giây. |
| `CONTEXT_WINDOW_RECONCILE_INTERVAL` | `86400` (24h) | `src/lib/contextWindowResolver.ts` | Khoảng thời gian (giây) cho trình đối soát cửa sổ ngữ cảnh tự hiệu chỉnh (5004): ghim các cửa sổ do nhà cung cấp khai báo từ quá trình khám phá `/models` dưới dạng các ghi đè `auto:discovery` khi chúng khác với danh mục. Đặt thành `0` để tắt. Tái sử dụng dữ liệu đã được đồng bộ (không tìm nạp mới); không bao giờ ghi đè các ghi đè `manual`. |
---
## 20. Cài đặt theo từng nhà cung cấp
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ---------------------------------------------- | -------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `OPENROUTER_CATALOG_TTL_MS` | `86400000` (24h) | `src/lib/catalog/openrouterCatalog.ts` | TTL của bộ nhớ đệm danh mục mô hình OpenRouter. |
| `MODEL_CATALOG_INCLUDE_NAMES` | `true` | `src/shared/constants/featureFlagDefinitions.ts` | Bao gồm các trường `name` thân thiện khi hiển thị trong phản hồi `/v1/models`. Tắt tùy chọn này cho các client chỉ mong đợi ID. |
| `CATALOG_BUILD_TIMEOUT_MS` | `8000` (8s) | `src/app/api/v1/models/catalogCache.ts` | Giới hạn thời gian chờ ở đường dẫn nguội (cold-path) cho một lần dựng lại danh mục `GET /v1/models` đã được hợp nhất (#12627). Khi hết thời gian, một phản hồi 200 tốt gần nhất sẽ được trả về nếu có. |
| `OMNIROUTE_SYNCED_CATALOG_STALE_AFTER_MS` | `2592000000` (30 ngày) | `src/lib/db/models/activeSyncedCatalog.ts` | Độ tuổi mà sau đó danh sách mô hình đã đồng bộ của một kết nối không còn được coi là chuẩn cho việc định tuyến và sẽ fail-open về registry (#12849). Các hàng chưa từng được gắn dấu thời gian được tính là đã cũ. |
| `OMNIROUTE_ANALYTICS_CACHE_TTL_MS` | `60000` (60s) | `src/lib/usage/analyticsResponseCache.ts` | Thời gian một phản hồi chậm của `GET /api/usage/analytics` được tái sử dụng cho cùng một chuỗi truy vấn (#15629). `0` để tắt bộ nhớ đệm. |
| `OMNIROUTE_ANALYTICS_CACHE_MIN_COMPUTE_MS` | `1000` (1s) | `src/lib/usage/analyticsResponseCache.ts` | Chỉ những phản hồi phân tích mất ít nhất khoảng thời gian này để dựng mới được đưa vào bộ nhớ đệm, để các instance nhỏ luôn thấy dữ liệu mới. |
| `OMNIROUTE_CACHE_METRICS_MIN_COMPUTE_MS` | chưa đặt (tắt) | `src/app/api/cache/route.ts` qua `src/lib/usage/analyticsResponseCache.ts` | Tùy chọn bật thủ công (#16361). Khi được đặt thành một số nguyên không âm N, phần lịch sử sử dụng của `GET /api/cache` (tổng prompt-cache + xu hướng) được phục vụ từ bộ nhớ đệm phản hồi phân tích dùng chung nếu việc dựng mất ít nhất N mili giây, theo từng cửa sổ `trendHours` đã được kẹp giới hạn, trong khoảng `OMNIROUTE_ANALYTICS_CACHE_TTL_MS` (lịch sử có thể trễ tối đa bằng TTL đó; `DELETE /api/cache` sẽ vô hiệu hóa nó). Chưa đặt hoặc giá trị không hợp lệ = lịch sử được đọc trực tiếp ở mỗi yêu cầu. |
| `NANOBANANA_POLL_TIMEOUT_MS` | `120000` | `open-sse/handlers/imageGeneration.ts` | Thời gian chờ tối đa cho các tác vụ tạo ảnh NanoBanana. |
| `NANOBANANA_POLL_INTERVAL_MS` | `2500` | `open-sse/handlers/imageGeneration.ts` | Tần suất thăm dò tác vụ NanoBanana. |
| `ADOBE_FIREFLY_SUBMIT_BASE_DELAY_MS` | `8000` | `open-sse/services/adobeFireflyUpscale.ts` | Độ trễ cơ sở cho cơ chế backoff lũy tiến khi thử lại gửi yêu cầu upscale của Adobe Firefly. |
| `AWS_REGION` | _(chưa đặt)_ | `src/lib/providers/validation.ts`, `open-sse/handlers/audioSpeech.ts` | Vùng dùng để xây dựng các endpoint AWS Bedrock (Kiro, audio). |
| `AWS_DEFAULT_REGION` | _(chưa đặt)_ | `src/lib/providers/validation.ts`, `open-sse/handlers/audioSpeech.ts` | Giá trị dự phòng khi `AWS_REGION` chưa được đặt. |
| `CLOUDFLARE_ACCOUNT_ID` | _(chưa đặt)_ | `open-sse/executors/cloudflare-ai.ts` | Account ID cho Cloudflare Workers AI. |
| `CLOUDFLARE_PLAYGROUND_CHROME_PATH` | _(chưa đặt)_ | `open-sse/executors/cloudflare-playground.ts` | Đường dẫn đầy đủ tới file nhị phân Chrome desktop cho trình thực thi Cloudflare AI Playground, dùng khi bước kiểm tra fingerprint headless chặn Chromium đi kèm Playwright. |
| `CODEBUDDY_SYSTEM_PROMPT_MAX_LEN` | ∅ (∞) — _(chưa đặt = không giới hạn độ dài)_ | `open-sse/executors/codebuddy/shared.ts` | Giới hạn độ dài tùy chọn cho các system prompt của caller gửi tới CodeBuddy (CN và International). Theo mặc định, chỉ những prompt mang dấu hiệu nhận diện của coding-agent mới bị thay bằng một prompt trung lập (bộ lọc nội dung của Tencent từ chối những prompt đó); các prompt dài vẫn được giữ nguyên. Một số nguyên > 0 cũng sẽ thay thế bất kỳ system prompt nào dài hơn số ký tự đó; chưa đặt, `0` hoặc giá trị không phải số nguyên sẽ tắt giới hạn. Mỗi lần thay thế đều ghi log quy tắc nào đã kích hoạt (dấu hiệu nhận diện hoặc độ dài). |
| `CLOUDFLARE_API_BASE` | `https://api.cloudflare.com/client/v4` | `src/app/api/settings/proxy/cloudflare-deploy/route.ts` | Ghi đè base của Cloudflare REST API được dùng bởi trình triển khai relay Workers của proxy-pool (#4640 / 9router#1360). |
| `NEXT_PUBLIC_CLOUDFLARE_RELAY_DEFAULT_PROJECT` | `omniroute-relay` | `src/app/(dashboard)/dashboard/settings/components/proxy/CloudflareRelayModal.tsx` | Tên project worker mặc định được gợi ý trong modal "Deploy Relay" của proxy-pool. |
| `NEXT_PUBLIC_CLOUDFLARE_RELAY_ENABLED` | `true` | `src/app/(dashboard)/dashboard/settings/components/proxy/ProxyPoolTab.tsx` | Đặt thành `false` để ẩn tùy chọn relay Cloudflare Workers khỏi tab Proxy Pool. |
| `CLOUDFLARED_BIN` | tự động phát hiện | `src/lib/cloudflaredTunnel.ts` | Đường dẫn tùy chỉnh tới binary `cloudflared`. |
| `CLOUDFLARED_PROTOCOL` | `http2` | `src/lib/cloudflaredTunnel.ts` | Giao thức truyền tải tunnel: `http2` (mặc định), `quic`, hoặc `auto`. |
| `CLOUDFLARED_CONFIG` | _(chưa đặt)_ | `src/lib/cloudflaredTunnel.ts` | Đường dẫn tới file `config.yml` của cloudflared được quản lý cục bộ (với `tunnel:`, `credentials-file:`, `ingress:`). Khi được đặt, OmniRoute chạy `tunnel --config run` (named tunnel) thay vì quick tunnel tạm thời. |
| `CLOUDFLARED_HOSTNAME` | _(từ ingress trong config)_ | `src/lib/cloudflaredTunnel.ts` | Ghi đè hostname công khai của named tunnel (ví dụ `ai.example.com`), được báo cáo dưới dạng `publicUrl`/`apiUrl`. Khi không được đặt, giá trị này được đọc từ hostname `ingress` đầu tiên trong config. |
| `DENO_DEPLOY_API_BASE` | `https://api.deno.com/v2` | `src/app/api/settings/proxy/deno-deploy/route.ts` | Ghi đè base URL REST API của Deno Deploy được trình triển khai relay của proxy-pool sử dụng (#4643 / 9router#1437). |
| `NEXT_PUBLIC_DENO_RELAY_DEFAULT_PROJECT` | `omniroute-deno-relay` | `src/app/(dashboard)/dashboard/settings/components/proxy/DenoRelayModal.tsx` | Tên app Deno Deploy mặc định được gợi ý trong modal "Deploy Relay" của proxy-pool. |
| `NEXT_PUBLIC_DENO_RELAY_ENABLED` | `true` | `src/app/(dashboard)/dashboard/settings/components/proxy/ProxyPoolTab.tsx` | Đặt thành `false` để ẩn tùy chọn relay Deno Deploy khỏi tab Proxy Pool. |
| `SEARCH_CACHE_TTL_MS` | `300000` (5 phút) | `open-sse/services/searchCache.ts` | TTL cho việc cache phản hồi của API tìm kiếm (Perplexity, Brave, v.v.). |
| `ENABLE_CC_COMPATIBLE_PROVIDER` | `false` | `src/shared/utils/featureFlags.ts` | Hiển thị giao diện provider tương thích CC thử nghiệm dành cho các relay chỉ hỗ trợ Claude Code. |
| `NINEROUTER_HOST` | `127.0.0.1` | `open-sse/executors/ninerouter.ts` | Ghi đè host mà instance 9router nhúng lắng nghe. |
| `NINEROUTER_PORT` | `20130` | `open-sse/executors/ninerouter.ts` | Ghi đè cổng mà instance 9router nhúng lắng nghe. |
| `EMBED_WS_PROXY_HOST` | `127.0.0.1` | `src/lib/services/embedWsProxy.ts` | Host liên kết cho proxy WebSocket của dịch vụ nhúng (mặc định chỉ loopback). |
| `EMBED_WS_PROXY_PORT` | `20131` | `src/lib/services/embedWsProxy.ts` | Cổng cho server proxy WebSocket của dịch vụ nhúng. |
| `CLIPROXYAPI_HOST` | `127.0.0.1` | `open-sse/executors/cliproxyapi.ts` | Host bridge CLIProxyAPI (tích hợp legacy). |
| `CLIPROXYAPI_PORT` | `5544` | `open-sse/executors/cliproxyapi.ts` | Cổng bridge CLIProxyAPI. |
| `CLIPROXYAPI_API_KEY` | _(trống)_ | `open-sse/handlers/chatCore/cliproxyapiCredentials.ts` | Khóa data-plane dự phòng khi thiếu thiết lập `cliproxyapi_api_key`. |
| `CLIPROXYAPI_MANAGEMENT_KEY` | _(trống)_ | `src/lib/services/cliproxyAccountHealth.ts` | Khóa quản lý để đọc tình trạng tài khoản từ một instance CLIProxyAPI được quản lý bên ngoài. |
| `CLIPROXYAPI_CONFIG_DIR` | `~/.cli-proxy-api` | `src/lib/versionManager/processManager.ts` | Thư mục config của CLIProxyAPI. |
| `CLIPROXY_BIND_HOST` | `127.0.0.1` | `docker-compose.yml` | Giao diện host mà docker-compose publish sidecar `cliproxyapi` (#12578). Volume dữ liệu của nó chứa thông tin xác thực OAuth/API của provider và image được ghim không có tùy chọn ghi đè `api-keys` data-plane qua biến môi trường (chỉ có một `config.yaml` được mount), vì vậy `0.0.0.0` sẽ để lộ một dịch vụ chứa thông tin xác thực ra toàn bộ mạng LAN. |
| `MUX_SERVICE_PORT` | `8322` | `src/lib/services/bootstrap.ts` | Ghi đè cổng mà daemon điều phối agent Mux (coder/mux) nhúng lắng nghe (luôn là 127.0.0.1). |
| `OPENWA_SERVICE_PORT` | `8323` | `src/lib/services/bootstrap.ts` | Ghi đè cổng mà daemon open-wa (tự động hóa WhatsApp Web) nhúng lắng nghe (luôn là 127.0.0.1). |
| `DARIO_HOST` | `127.0.0.1` | `open-sse/executors/dario.ts` | Host bind/kết nối của dịch vụ nhúng Dario (mặc định chỉ loopback). |
| `DARIO_PORT` | `3456` | `open-sse/executors/dario.ts` | Cổng của dịch vụ nhúng Dario. |
| `DARIO_HOST` | `127.0.0.1` | `open-sse/executors/dario.ts` | Host bind/kết nối của dịch vụ nhúng Dario (mặc định chỉ loopback). |
| `DARIO_PORT` | `3456` | `open-sse/executors/dario.ts` | Cổng của dịch vụ nhúng Dario. |
| `LOCAL_HOSTNAMES` | _(trống)_ | `open-sse/config/providerRegistry.ts` | Danh sách hostname bổ sung phân tách bằng dấu phẩy được coi là "local" (tên dịch vụ Docker, v.v.). |
`ENABLE_CC_COMPATIBLE_PROVIDER` chỉ dành cho các relay bên thứ ba chỉ chấp nhận
client Claude Code. OmniRoute viết lại các request để những relay đó chấp nhận chúng.
Nếu bạn chỉ muốn sử dụng Claude Code CLI, hoặc bạn không chắc những relay này là gì,
hãy giữ tùy chọn này ở trạng thái tắt và thêm một provider tương thích Anthropic thông thường thay thế.
---
## 21. Sức khỏe Proxy
| Variable | Default | Source File | Description |
| ------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PROXY_FAST_FAIL_TIMEOUT_MS` | `2000` | `src/lib/proxyHealth.ts` | Thời gian chờ của lượt kiểm tra sức khỏe fast-fail. |
| `PROXY_LATENCY_WINDOW_HOURS` | `3` | `src/lib/db/proxies.ts` | Khoảng thời gian (giờ) dùng để tính độ trễ trung bình của các proxy ứng viên trong chiến lược pool tối ưu theo độ trễ. |
| `PROXY_HEALTH_CACHE_TTL_MS` | `30000` | `src/lib/proxyHealth.ts` | TTL của bộ nhớ đệm kết quả kiểm tra sức khỏe. |
| `PROXY_HEALTH_UNHEALTHY_CACHE_TTL_MS` | `2000` | `src/lib/proxyHealth.ts` | TTL bộ nhớ đệm cho các lần thăm dò sức khỏe proxy thất bại. Hãy giữ giá trị này ngắn hơn `PROXY_HEALTH_CACHE_TTL_MS` để các timeout proxy tạm thời khi mức độ đồng thời cao được thử lại nhanh chóng, mà không vô hiệu hóa cơ chế fast-fail đối với các proxy thực sự đã chết. |
| `PROXY_HEALTH_ENABLED` | `true` | `src/lib/proxyHealth/scheduler.ts` | Đặt thành `false` để tắt bộ lập lịch kiểm tra sức khỏe proxy chạy nền, vốn định kỳ thăm dò các proxy đã đăng ký. |
| `PROXY_HEALTH_INTERVAL_MS` | `600000` | `src/lib/proxyHealth/scheduler.ts` | Khoảng thời gian quét của bộ lập lịch sức khỏe chạy nền, tính bằng ms (tối thiểu `60000`). |
| `PROXY_HEALTH_RELAY_INTERVAL_MS` | `21600000` | `src/lib/proxyHealth/relayCadence.ts` | Khoảng thời gian thăm dò tính bằng ms cho các proxy edge-relay (`deno`/`vercel`/`cloudflare`), vốn có các lần thăm dò đánh thức một isolate serverless có tính phí (tối thiểu `60000`). |
| `PROXY_HEALTH_RECOVERY_INTERVAL_MS` | `600000` | `src/lib/proxyHealth/scheduler.ts` | Khoảng thời gian giữa các lượt khôi phục chạy nền tính bằng ms: tần suất thăm dò lại các proxy trước đó không khỏe mạnh để proxy đã khôi phục quay lại vòng luân chuyển mà không cần khởi động lại. Các giá trị dưới `60000` sẽ quay về mặc định. |
| `PROXY_HEALTH_TEST_URL` | `https://httpbin.org/ip` | `src/lib/proxyHealth/probeTarget.ts` | Mục tiêu thăm dò khả năng kết nối được bộ lập lịch và endpoint `/api/settings/proxies/auto-test` sử dụng. Trỏ nó tới một URL nội bộ/tự lưu trữ để tránh dùng địa chỉ công khai mặc định. |
| `PROXY_HEALTH_TEST_CONCURRENCY` | `10` | `src/lib/proxyHealth/probeTarget.ts` | Số lần thăm dò được khởi chạy đồng thời trong mỗi lô, dùng chung bởi bộ lập lịch và endpoint `/api/settings/proxies/auto-test`. Giới hạn dưới là 1 và giới hạn trên là 50. |
| `PROXY_HEALTH_TEST_STAGGER_MS` | `100` | `src/lib/proxyHealth/probeTarget.ts` | Độ trễ tính bằng ms giữa hai lần gửi thăm dò liên tiếp trong một lô. Nếu không có nó, toàn bộ lô sẽ được gửi đi cùng một lúc và một IP đầu ra dùng chung có thể kích hoạt giới hạn tốc độ ở mục tiêu. Đặt thành `0` để tắt khoảng cách này; giới hạn trên là 5000. |
| `PROXY_HEALTH_USE_PROVIDER_TARGET` | `true` | `src/lib/proxyHealth/providerProbeTarget.ts` | Đặt thành "false" để ngừng thăm dò máy chủ thật của nhà cung cấp được gán cho proxy (`GET /models`, không cần khóa API) và luôn dùng `PROXY_HEALTH_TEST_URL` thay thế. |
| `PROXY_HEALTH_AUTO_DEACTIVATE` | `false` | `src/lib/proxyHealth/statusPolicy.ts` | Khi `false` (mặc định), các lần thăm dò khả năng kết nối tự động (bộ lập lịch + nút "Test All" của `/api/settings/proxies/auto-test`) ở chế độ **chỉ đọc** và không bao giờ ghi trạng thái của proxy — chỉ người vận hành mới đặt active/inactive, vì vậy một lần thăm dò chập chờn sẽ không thể bỏ lơ một proxy đã được gán (#6246). Đặt `true` để khôi phục hành vi test-and-set cũ. |
| `FLUSH_EMPTY_RETRY_ENABLED` | `false` | `src/shared/utils/featureFlags.ts` | Cờ tính năng tự chọn bật (xem [FEATURE_FLAGS.md](./FEATURE_FLAGS.md); giá trị ghi đè từ DB của bảng điều khiển sẽ thắng). `true` (hoặc `1`, `yes`) sẽ thử lại các lượt streaming sau khi dịch bị rỗng qua đường dẫn thông tin xác thực thông thường (tối đa `STREAM_RECOVERY.EMPTY_TURN_RETRY_MAX` lần thử lại) thay vì trả về một phản hồi 200 rỗng hoặc một lỗi 502 nội dung rỗng. |
| `EMPTY_STREAM_SIBLING_RECOVERY_ENABLED` | `false` | `src/shared/utils/featureFlags.ts` | Cờ tính năng tự chọn bật (xem [FEATURE_FLAGS.md](./FEATURE_FLAGS.md); giá trị ghi đè từ DB của bảng điều khiển sẽ thắng). `true` (hoặc `1`, `yes`) kích hoạt bộ thăm dò nội dung stream rỗng của Claude/Codex và dùng lượt thử lại có giới hạn hiện có cho một kết nối đủ điều kiện khác sau một lượt `empty_content`, không áp dụng cooldown hay khóa mô hình. |
| `STREAM_LATE_OUTPUT_PROBE_ENABLED` | `false` | `src/shared/utils/featureFlags.ts` | Cờ tính năng tự chọn bật (xem [FEATURE_FLAGS.md](./FEATURE_FLAGS.md); giá trị ghi đè từ DB của bảng điều khiển sẽ thắng). `true` (hoặc `1`, `yes`) tiếp tục lấy mẫu một chunk đã chuyển tiếp trong mỗi 16 chunk sau 64 chunk đầu tiên để đầu ra hiển thị xuất hiện muộn vẫn đánh dấu stream là đã phát ra đầu ra (một lỗi 5xx đơn lẻ sau khi có đầu ra vẫn chỉ nằm trong phạm vi request thay vì khóa riêng mô hình). |
| `PROXY_POOL_EGRESS_OBSERVATION` | `false` | `src/shared/utils/featureFlags.ts` | Cờ tính năng opt-in (xem [FEATURE_FLAGS.md](./FEATURE_FLAGS.md); ghi đè DB từ dashboard được ưu tiên). `true` (hoặc `1`, `yes`) hiển thị phần quan sát egress của pool ở chế độ chỉ đọc bên dưới một proxy pool trong dashboard (các IP egress riêng biệt, số kết nối và số lượng thấy nhiều nhất sau một IP trong 24 giờ qua, lấy từ log proxy). Không bao giờ được dùng cho định tuyến. |
| `PROXY_OPERATOR_EGRESS_ENABLED` | `false` | `src/shared/utils/featureFlags.ts` | Cờ tính năng opt-in (xem [FEATURE_FLAGS.md](./FEATURE_FLAGS.md); ghi đè DB từ dashboard được ưu tiên). `true` (hoặc `1`, `yes`) chấp nhận các địa chỉ quan sát được kèm ngày do operator đẩy lên cho từng thành viên pool và hợp nhất chúng với dữ liệu đọc từ journal để hiển thị và sắp xếp thứ tự pool. |
| `PROXY_OPERATOR_EGRESS_WINDOW_HOURS` | `24` | `src/lib/db/proxyOperatorEgress.ts` | Cửa sổ quan sát tính bằng giờ cho các hàng egress do operator đẩy lên (được đọc lại ở mỗi lần đọc; không cần khởi động lại). Giới hạn trong khoảng 1..168; giá trị ngoài khoảng, không phải số hoặc rỗng sẽ quay về 24 với một cảnh báo duy nhất trong toàn tiến trình, không bao giờ ném lỗi. |
| `PROXY_AUTO_REMOVE` | `false` | `src/lib/proxyHealth/scheduler.ts` | Đặt `true` để cho phép scheduler tự động xóa proxy sau nhiều lần thất bại liên tiếp. |
| `PROXY_AUTO_REMOVE_AFTER` | `3` | `src/lib/proxyHealth/scheduler.ts` | Số lần thất bại liên tiếp trước khi scheduler tự động xóa một proxy (khi `PROXY_AUTO_REMOVE=true`). |
| `PROXY_AUTO_DISABLE` | `false` | `src/lib/proxyHealth/scheduler.ts` | Đặt `true` để cho phép scheduler vô hiệu hóa mềm (trạng thái `dead`, không bao giờ bị xóa) một proxy sau nhiều lần thất bại liên tiếp, thay vì xóa nó. Đây là phương án thay thế không phá hủy cho `PROXY_AUTO_REMOVE`: proxy lập tức bị loại khỏi việc phân giải pool/rotation (bộ lọc trạng thái alive mà việc phân giải scope-pool sử dụng vốn đã loại trừ nó) và được tự động kích hoạt lại ngay khi nó bắt đầu vượt qua các lần probe trở lại. Dùng chung ngưỡng `PROXY_AUTO_REMOVE_AFTER`. Nếu cả hai cờ đều là `true`, `PROXY_AUTO_REMOVE` được ưu tiên. |
| `PROXY_HEALTH_PASSIVE_SKIP` | `false` | `src/lib/proxyHealth/scheduler.ts` | Bỏ qua thụ động dạng opt-in: khi `true`, scheduler bỏ qua probe trực tiếp cho một endpoint mà lưu lượng production gần đây đã chứng minh được nó hoạt động (ít nhất một lần thành công và không có lỗi proxy nào được quy kết trong cửa sổ, đồng thời chỉ quan sát đúng một provider). Tắt theo mặc định: mọi proxy đều được probe. |
| `PROXY_PASSIVE_WINDOW_MS` | `300000` | `src/lib/proxyHealth/passiveVerdict.ts` | Cửa sổ tính bằng ms của lưu lượng production mà tính năng bỏ qua thụ động xem xét (giới hạn `60000..599999`). Ngắn hơn chu kỳ quét 10 phút để một lỗi gần đây chiếm ưu thế thay vì bị pha loãng. |
| `OMNIROUTE_CONTROL_PLANE_PROXY_DIRECT_FALLBACK` | `false` | `src/shared/constants/featureFlagDefinitions.ts` | Cho phép các luồng OAuth và xác thực provider bỏ qua proxy đã ghim và kết nối trực tiếp khi các bước kiểm tra trước về khả năng kết nối của proxy thất bại. Thứ tự ưu tiên hiệu lực là ghi đè Feature Flags DB > biến môi trường > mặc định. |
| `RATE_LIMIT_MAX_WAIT_MS` | `30000` (30s) | `src/lib/resilience/settings.ts` | Ngân sách **chờ-trong-hàng-đợi** mặc định: khoảng thời gian một yêu cầu có thể chờ để có slot của provider và nằm trong hàng đợi trước khi bị từ chối, không bao giờ đến được upstream. Bộ đếm thời gian được xóa khi job bắt đầu thực thi — việc thực thi được giới hạn riêng bởi `RATE_LIMIT_EXECUTION_MAX_WAIT_MS`. Env chỉ đặt giá trị mặc định: một `resilienceSettings.requestQueue.maxWaitMs` đã được lưu trữ, và sau đó là `rateLimitOverrides.maxWaitMs` theo từng kết nối, mỗi cái đều ghi đè lên nó. |
| `RATE_LIMIT_EXECUTION_MAX_WAIT_MS` | `600000` (10 phút) | `open-sse/services/rateLimitManager.ts` | Mức trần cho khoảng thời gian một yêu cầu đã được chấp nhận có thể ở trong trạng thái thực thi trước khi chỗ giữ rate-limit của nó hết hạn — tách biệt khỏi ngân sách chờ-trong-hàng-đợi để việc khởi động fetch chậm trên các gateway non-incremental không bị timeout (#12027). |
| `RATE_LIMIT_MAX_QUEUE_DEPTH` | `0` (tắt) | `open-sse/services/rateLimitManager.ts` | Giới hạn nhận vào hàng đợi: từ chối với mã 429 `queue_full` khi đã có từng này yêu cầu trong hàng đợi. `0` = không giới hạn (mặc định). |
| `RATE_LIMIT_AUTO_ENABLE` | _(chưa đặt)_ | `open-sse/services/rateLimitManager.ts` | Bắt buộc bật/tắt lưới an toàn tự động bật rate limit bất kể cài đặt Dashboard đã lưu (`resilienceSettings.requestQueue.autoEnableApiKeyProviders`). Chấp nhận `true`/`1`/`on` để bắt buộc bật, `false`/`0`/`off` để bắt buộc tắt. Khi hoạt động (mặc định), các kết nối API-key đang hoạt động sẽ tự động được bảo vệ bằng rate-limit. Đặt `rateLimitProtection: false` theo từng kết nối sẽ tắt bảo vệ tường minh nhưng không loại khỏi lưới an toàn này; đặt biến env này thành `false` là cơ chế toàn cục để chạy các kết nối API-key mà không có hàng đợi rate-limit. |
| `PROVIDER_COOLDOWN_ENABLED` | _(chưa đặt → tắt)_ | `open-sse/services/providerCooldownTracker.ts` | Theo dõi cooldown provider/kết nối toàn cục xuyên suốt các yêu cầu theo cơ chế opt-in. TẮT theo mặc định (trùng lặp với Connection Cooldown / Provider Circuit Breaker). Chấp nhận `true`/`1`/`on` để bật. |
| `PROVIDER_COOLDOWN_MIN_MS` | `5000` | `open-sse/services/providerCooldownTracker.ts` | Cooldown tối thiểu (ms) trước khi một provider/kết nối bị lỗi được thử lại. Tăng theo cấp số nhân với số lần thất bại liên tiếp. Chỉ được dùng khi `PROVIDER_COOLDOWN_ENABLED`. |
| `PROVIDER_COOLDOWN_MAX_MS` | `300000` (5 phút) | `open-sse/services/providerCooldownTracker.ts` | Mức trần cooldown tối đa (ms) — sau mức này một provider/kết nối bị lỗi sẽ được thử lại bất kể thế nào. Chỉ được dùng khi `PROVIDER_COOLDOWN_ENABLED`. |
| `STREAM_RECOVERY_ENABLED` | _(chưa đặt → tắt)_ | `src/lib/resilience/settings.ts` (seed) → `open-sse/services/streamRecovery.ts` (logic) | **Chức năng:** khôi phục trong suốt các stream upstream bị cắt ngắn (port từ free-claude-code). Giữ cửa sổ SSE mở đầu tối đa `STREAM_RECOVERY.HOLDBACK_MS` (750 ms) để một điểm cắt _pre-commit_ — tức điểm cắt xảy ra trước khi bất kỳ byte nào đến được client — được mở lại và thử lại một cách vô hình. **Khi nào nên bật:** các upstream không ổn định thường xuyên bị cắt về 0 byte ngay khi bắt đầu stream; để TẮT nếu bạn không thể chấp nhận thêm tối đa 750 ms vào thời gian đến token đầu tiên (time-to-first-token) trên mọi stream. Chấp nhận `true`/`1`/`on`. Gieo giá trị ban đầu cho cài đặt Resilience đã lưu; cài đặt Dashboard sẽ thắng khi đã được đặt. |
| `STREAM_RECOVERY_MIDSTREAM_ENABLED` | _(chưa đặt → tắt)_ | `src/lib/resilience/settings.ts` (khởi tạo) → `open-sse/services/streamRecovery.ts` (logic) | **Gì:** tiếp nối giữa luồng (Fase 4.4) — sau khi bị cắt cụt _post-commit_ (các byte đã đến được client), gửi lại yêu cầu với phần văn bản một phần làm prefill của assistant và ghép nối phần hậu tố còn thiếu. Chỉ áp dụng cho các luồng văn bản thuần tương thích OpenAI; không bao giờ kích hoạt khi đang có tool call dang dở. **Khi nào bật:** các lần sinh dài bị cắt giữa câu trả lời và bạn chấp nhận phần đuôi được khôi phục đến dưới dạng một cụm thay vì từng token một. Độc lập với `STREAM_RECOVERY_ENABLED` (mức độ rủi ro khác). Chấp nhận `true`/`1`/`on`. |
| `STREAM_THROUGHPUT_WATCHDOG_ENABLED` | _(chưa đặt → tắt)_ | `src/lib/resilience/settings.ts` → `open-sse/services/throughputWatchdog.ts` | Watchdog opt-in giám sát đầu ra hữu ích của luồng đang hoạt động. Phát hiện các luồng vẫn liên tục gửi chunk nhưng duy trì dưới tốc độ đầu ra assistant đã cấu hình; heartbeat, sự kiện usage, delta rỗng và các giai đoạn tool/reasoning không bị tính nhầm là tiến triển. Tách biệt với các timeout idle và hard-deadline. |
| `STREAM_THROUGHPUT_WATCHDOG_WARMUP_MS` | `30000` | `src/lib/resilience/settings/normalize.ts` | Thời gian gia hạn trước khi đánh giá thông lượng, giới hạn trong khoảng 0–600000 ms. |
| `STREAM_THROUGHPUT_WATCHDOG_WINDOW_MS` | `30000` | `src/lib/resilience/settings/normalize.ts` | Cửa sổ trượt tính đầu ra hữu ích, giới hạn trong khoảng 1000–600000 ms; cần một cửa sổ hoàn chỉnh trước khi hủy. |
| `STREAM_THROUGHPUT_WATCHDOG_MIN_BYTES_PER_SECOND` | `4` | `src/lib/resilience/settings/normalize.ts` | Tốc độ byte đầu ra assistant UTF-8 tối thiểu (ước lượng token thận trọng), giới hạn trong khoảng 1–1000000. |
| `STREAM_THROUGHPUT_WATCHDOG_MIN_USEFUL_BYTES` | `1` | `src/lib/resilience/settings/normalize.ts` | Mẫu đầu ra hữu ích khác không tối thiểu được coi là có thể đo lường, giới hạn trong khoảng 1–1000000 byte. |
| `HEALTHCHECK_STAGGER_MS` | `3000` | `src/lib/tokenHealthCheck.ts` | Khoảng giãn cách (ms) giữa các lần healthcheck token của provider khi khởi động. |
| `HEALTHCHECK_JITTER_MIN_MS` | `500` | `src/lib/tokenHealthCheck.ts` | Độ jitter ngẫu nhiên tối thiểu (ms) cộng thêm vào `HEALTHCHECK_STAGGER_MS` giữa các lần healthcheck token của provider, nhằm tránh dồn cục (Issue #1220). |
| `HEALTHCHECK_JITTER_MAX_MS` | `5000` | `src/lib/tokenHealthCheck.ts` | Độ jitter ngẫu nhiên tối đa (ms) cộng thêm vào `HEALTHCHECK_STAGGER_MS` giữa các lần healthcheck token của provider, nhằm tránh dồn cục (Issue #1220). |
| `HEALTHCHECK_BATCH_SIZE` | `20` | `src/lib/tokenHealthCheck.ts` | Kích thước lô kiểm tra đồng thời cho đợt quét healthcheck token khi khởi động; giá trị lớn hơn kiểm tra được nhiều kết nối song song hơn, giá trị nhỏ hơn giảm tải dồn cục (Issue #7875, hồi quy của #7719). |
| `REQUEST_RETRY` | `2` | `src/sse/services/cooldownAwareRetry.ts` | Số lần thử lại tự động khi nhận phản hồi cooldown ở cấp model trước khi trả lỗi về client. |
| `MAX_RETRY_INTERVAL_SEC` | `30` | `src/sse/services/cooldownAwareRetry.ts` | Khoảng thời gian backoff tối đa (giây) giữa các lần thử lại cooldown. Luôn bị giới hạn bởi giá trị này bất kể `Retry-After` từ upstream. |
| `HEADROOM_URL` | `http://localhost:8787` | `src/lib/headroom/detect.ts` | URL proxy tiết kiệm token Headroom. Vòng đời dashboard (`api/headroom/*`) theo mặc định sẽ khởi chạy một CLI `headroom-ai` cục bộ trên loopback; chỉ ghi đè khi cần trỏ tới một proxy sidecar Docker bên ngoài. |
### Các hằng số tinh chỉnh khôi phục stream
Hành vi holdback khi khôi phục được tinh chỉnh bởi các hằng số hardcode trong
`open-sse/config/constants.ts` (`STREAM_RECOVERY`), được liệt kê ở đây để tham khảo —
việc thay đổi chúng đòi hỏi chỉnh sửa mã nguồn, không phải biến môi trường:
- `STREAM_RECOVERY.HOLDBACK_MS = 750` — khoảng thời gian cửa sổ SSE mở đầu bị giữ lại
để có thể thử lại một lần cắt cụt sớm trước khi bất kỳ byte nào được commit tới client.
- `STREAM_RECOVERY.BUFFER_MAX_BYTES = 65536` — giới hạn cứng của cửa sổ được giữ lại; commit
(flush + passthrough) ngay khi tích lũy đủ số byte này, bất kể bộ đếm thời gian.
- `STREAM_RECOVERY.EARLY_RETRY_MAX = 4` — số lần mở lại stream upstream một cách trong suốt
tối đa trong khi holdback vẫn chưa được commit.
> **Giới hạn tốc độ sliding-window theo từng provider (không có biến môi trường):** bộ giới hạn
> tốc độ sliding-window theo từng provider _dự phòng_ được port từ FCC tồn tại trong mã nguồn
> (`open-sse/services/providerDefaultRateLimit.ts`, được nối qua
> `open-sse/services/rateLimitManager.ts`) nhưng được phát hành với một **map mặc định rỗng**
> và hiện tại **không có biến môi trường nào cho operator** — nó chỉ được bật thông qua một test hook /
> chỉnh sửa mã nguồn. Nó cố ý không được liệt kê trong bảng trên. Bộ giới hạn relay theo từng `(token, IP)`
> mà _thực sự_ có núm điều chỉnh là `RELAY_IP_PER_MINUTE` (§3 Mạng & Cổng).
---
## 22. Gỡ lỗi
> [!CAUTION]
> Các biến này tạo ra **đầu ra chi tiết** và có thể làm rò rỉ dữ liệu nhạy cảm. **Tuyệt đối không bật trong môi trường production.**
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CURSOR_DEBUG` | _(chưa đặt)_ | `open-sse/executors/cursor.ts` | Đặt thành `1` để bật nhật ký chi tiết của trình thực thi Cursor (các đoạn SSE đã giải mã, v.v.). |
| `CURSOR_STREAM_DEBUG` | _(chưa đặt)_ | `open-sse/executors/cursor.ts` | Bí danh tương thích ngược của `CURSOR_DEBUG`. |
| `CURSOR_DUMP_FILE` | _(chưa đặt)_ | `open-sse/executors/cursor.ts` | Đường dẫn tệp tùy chọn để nhận các đoạn Cursor thô đã giải mã khi `CURSOR_DEBUG=1`. |
| `CURSOR_STREAM_TIMEOUT_MS` | `300000` | `open-sse/executors/cursor.ts` | Thời gian chờ khi luồng không hoạt động (ms) dành cho trình thực thi Cursor. |
| `CURSOR_KV_GRACE_MS` | `2000` | `open-sse/executors/cursor.ts` | Khoảng gia hạn (ms) sau dấu kết thúc mềm `composer kv_after_text` khi vẫn còn byte trong bộ đệm — cho phép lệnh gọi công cụ `exec_mcp` ở cuối có thời gian hoàn tất khung của nó. |
| `CURSOR_TOOL_DIRECTIVE` | đã bật (`!== "0"`) | `open-sse/executors/cursor.ts` | Chỉ thị cam kết dùng công cụ giúp composer-2.5 phát lệnh gọi công cụ một cách đáng tin cậy. Đặt thành `0` để tắt. |
| `OMNIROUTE_SYSTEM_INSTRUCTION_APPEND` | _(chưa đặt)_ | `open-sse/translator/request/claude-to-openai.ts`, `open-sse/translator/response/openai-to-claude.ts` | Văn bản lời nhắc hệ thống do người vận hành xác định, được nối vào thông báo hệ thống SAU khi dịch (chèn hậu dịch), truyền đến các đường dẫn codex/Responses và `/v1/messages`. Cũng được dùng làm tiền tố chỉ thị để loại bỏ khỏi các khối lời mở đầu hệ thống bị phản hồi lại. Để chưa đặt nhằm tắt tính năng này. |
| `OMNIROUTE_STRIP_SYSTEM_PREAMBLE` | `0` (tắt) | `open-sse/translator/response/openai-to-claude.ts`, `open-sse/utils/directivePreambleStripper.ts` | Đặt thành `1` để loại bỏ các khối lời mở đầu của lời nhắc hệ thống bị phản hồi lại khỏi phần đầu của luồng openai→claude. Mặc định là tắt — các phương pháp suy nghiệm được thiết kế theo văn xuôi tiếng Anh và làm thay đổi tải trọng phản hồi, vì vậy một câu trả lời thực sự bắt đầu bằng phần như vậy sẽ bị mất phần đó. |
| `CURSOR_IMAGE_FETCH_TIMEOUT_MS` | `15000` | `open-sse/utils/cursorImages.ts` | Thời gian chờ tải từng hình ảnh (ms) đối với đầu vào thị giác `image_url` từ xa. |
| `CURSOR_STATE_DB_PATH` | _(được dò tìm)_ | `open-sse/utils/cursorVersionDetector.ts` | Ghi đè quá trình tra cứu cơ sở dữ liệu trạng thái của Cursor dùng để phát hiện phiên bản IDE. |
| `CURSOR_AGENT_CLI_VERSION` | _(phát hiện / ghim)_ | `open-sse/utils/cursorAgentCliVersion.ts` | ID bản dựng Agent CLI (`YYYY.MM.DD-`) cho `x-cursor-client-version: cli-…` trên Agent Run. |
| `CURSOR_AGENT_BIN` | _(chưa đặt)_ | `open-sse/handlers/imageGeneration/providers/cursorAgentImage.ts` | Đường dẫn đến tệp nhị phân Cursor Agent dùng để tạo hình ảnh. Khi chưa đặt, trình xử lý sử dụng `providerSpecificData.agentBin`, sau đó đến PATH. |
| `CURSOR_IMG_TIMEOUT_MS` | `210000` | `open-sse/handlers/imageGeneration/providers/cursorAgentImage.ts` | Thời gian thực tối đa cho mỗi hình ảnh (ms) đối với các tác vụ hình ảnh của Cursor Agent. |
| `CURSOR_IMG_MAX_CONCURRENT` | `2` | `open-sse/handlers/imageGeneration/providers/cursorAgentImage.ts` | Cổng giới hạn số tác vụ đồng thời trên tài nguyên dùng chung dành cho các tác vụ hình ảnh Cursor. |
| `CURSOR_IMG_MODEL` | yêu cầu / `auto` | `open-sse/handlers/imageGeneration/providers/cursorAgentImage.ts` | Ghi đè `--model` của Cursor CLI cho các tác vụ hình ảnh. |
| `UC_IMAGE_POLL_INTERVAL_MS` | `2000` | `open-sse/handlers/imageGeneration/providers/ucImage.ts` | Nhịp thăm dò kết quả tạo hình ảnh UC (uncensored.com) (ms). |
| `UC_IMAGE_POLL_TIMEOUT_MS` | `60000` | `open-sse/handlers/imageGeneration/providers/ucImage.ts` | Thời gian thực tối đa để thăm dò kết quả tạo hình ảnh UC (ms). |
| `UC_VIDEO_POLL_INTERVAL_MS` | `3000` | `open-sse/handlers/videoGeneration/providers/ucVideo.ts` | Nhịp thăm dò kết quả tạo video UC (uncensored.com) (ms). |
| `UC_VIDEO_POLL_TIMEOUT_MS` | `300000` | `open-sse/handlers/videoGeneration/providers/ucVideo.ts` | Thời gian thực tối đa để thăm dò kết quả tạo video UC (ms). |
| `CURSOR_DATA_DIR` | _(được dò tìm)_ | `open-sse/utils/cursorAgentCliVersion.ts` | Ghi đè thư mục dữ liệu Cursor Agent CLI (`…/versions/`); đây cũng là biến mà agent chính thức sử dụng. |
| `CURSOR_TOKEN` | _(chưa đặt)_ | `scripts/ad-hoc/cursor-tap.cjs` | Token bearer trực tiếp của Cursor được các công cụ dành cho nhà phát triển sử dụng. |
| `OMNIROUTE_LOG_REQUEST_SHAPE` | đã tắt (chọn bật qua `"1"`) | `src/app/api/v1/chat/completions/route.ts` | Ghi nhật ký các dấu hiệu về loại/độ dài nội dung cho tải trọng trò chuyện lớn khi đặt thành `"1"`. Mặc định là tắt để giảm nhiễu nhật ký. |
| `DEBUG_RESPONSES_SSE_TO_JSON` | _(chưa đặt)_ | `open-sse/handlers/responseTranslator.ts` | Đặt thành `true` để ghi nhật ký chi tiết về quá trình chuyển đổi SSE→JSON của Responses API. |
| `DEBUG_CLAUDE_NONSTREAM` | _(chưa đặt)_ | `open-sse/handlers/responseTranslator.ts` | Đặt thành `true` để hiển thị các đoạn textContent trống trong đường dẫn chuyển đổi phản hồi Claude (chỉ dành cho gỡ lỗi). |
| `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` | _(chưa đặt)_ | Bộ kiểm thử E2E | Đặt thành `true` để bật chế độ kiểm thử E2E (xác thực được nới lỏng, các hook kiểm thử). |
---
## 23. Tích hợp GitHub
Cho phép người dùng báo cáo sự cố trực tiếp từ Dashboard.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| --------------------- | ------------------ | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GITHUB_ISSUES_REPO` | _(chưa thiết lập)_ | `src/app/api/v1/issues/report/route.ts` | Kho lưu trữ theo định dạng `owner/repo`. |
| `GITHUB_ISSUES_TOKEN` | _(chưa thiết lập)_ | `src/app/api/v1/issues/report/route.ts` | GitHub Personal Access Token có phạm vi `issues:write`. |
| `GITHUB_TOKEN` | _(chưa thiết lập)_ | trợ giúp phân loại sự cố / tác tử đám mây | Token truy cập GitHub chung được dùng làm phương án dự phòng cho `GITHUB_ISSUES_TOKEN` và được các tiện ích hỗ trợ tác tử đám mây trong `src/lib/cloudAgent/*` sử dụng. |
---
## Các kịch bản triển khai
Để biết hướng dẫn SRE cho backend chuyển tiếp (hành vi ts/bifrost/auto, vị trí triển khai 9router so với CLIProxyAPI và chiến lược dự phòng cho thông lượng cao), hãy xem [Chiến lược backend chuyển tiếp](/docs/reference/RELAY_BACKEND_STRATEGY.md).
### Phát triển cục bộ tối thiểu
```bash
JWT_SECRET=$(openssl rand -base64 48)
API_KEY_SECRET=$(openssl rand -hex 32)
INITIAL_PASSWORD=dev123
PORT=20128
NODE_ENV=development
```
### Môi trường production bằng Docker
```bash
JWT_SECRET=<được-tạo>
API_KEY_SECRET=<được-tạo>
INITIAL_PASSWORD=<được-tạo>
STORAGE_ENCRYPTION_KEY=<được-tạo>
DATA_DIR=/data
PORT=20128
API_PORT=20129
NODE_ENV=production
AUTH_COOKIE_SECURE=true
REQUIRE_API_KEY=true
NEXT_PUBLIC_BASE_URL=https://omniroute.example.com
BASE_URL=http://localhost:20128
OMNIROUTE_MEMORY_MB=8192
CORS_ORIGIN=https://your-frontend.example.com
```
### Môi trường cách ly mạng / CI
```bash
JWT_SECRET=test-jwt-secret-for-ci
API_KEY_SECRET=test-api-key-secret-for-ci
INITIAL_PASSWORD=testpass
NODE_ENV=production
OMNIROUTE_DISABLE_BACKGROUND_SERVICES=true
APP_LOG_TO_FILE=false
```
### VPS với reverse proxy (nginx + Cloudflare)
```bash
JWT_SECRET=<được-tạo>
API_KEY_SECRET=<được-tạo>
STORAGE_ENCRYPTION_KEY=<được-tạo>
PORT=20128
AUTH_COOKIE_SECURE=true
REQUIRE_API_KEY=true
NEXT_PUBLIC_BASE_URL=https://omniroute.example.com
BASE_URL=http://127.0.0.1:20128
CORS_ORIGIN=https://omniroute.example.com
ENABLE_TLS_FINGERPRINT=true
CLI_COMPAT_ALL=1
```
---
## 24. Sandbox cho Skills (v3.8.0+)
Các giới hạn và tùy chọn an toàn được áp dụng khi framework Skills (`src/lib/skills/`) thực thi các quy trình tự động hóa do người dùng định nghĩa trong môi trường sandbox.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| --------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SKILLS_SANDBOX_TIMEOUT_MS` | `10000` (10 giây) | `src/lib/skills/builtins.ts` | Thời gian chờ thực tế cho mỗi lần thực thi mã skill trong sandbox. Đây là giới hạn cứng; mọi tiến trình chạy lâu hơn sẽ bị dừng. |
| `SKILLS_EXECUTION_TIMEOUT_MS` | _(dùng `SKILLS_SANDBOX_TIMEOUT_MS` nếu không có)_ | `src/lib/skills/` | Thời gian chờ điều phối skill ở cấp cao. Đặt cao hơn `SKILLS_SANDBOX_TIMEOUT_MS` để cho phép quy trình làm việc nhiều bước. |
| `SKILLS_MAX_FILE_BYTES` | `1048576` (1 MB) | `src/lib/skills/builtins.ts` | Số byte tối đa mà một skill có thể đọc từ bất kỳ tệp riêng lẻ nào trong sandbox. |
| `SKILLS_MAX_HTTP_RESPONSE_BYTES` | `256000` (250 KB) | `src/lib/skills/builtins.ts` | Số byte tối đa được thu thập từ bất kỳ phản hồi HTTP riêng lẻ nào bên trong một skill. |
| `SKILLS_MAX_SANDBOX_OUTPUT_CHARS` | `100000` | `src/lib/skills/builtins.ts` | Giới hạn cứng đối với số ký tự stdout/stderr được trả về từ một lần gọi sandbox. |
| `SKILLS_SANDBOX_NETWORK_ENABLED` | `false` | `src/lib/skills/builtins.ts` | Đặt thành `1`/`true` để cho phép truy cập mạng ra ngoài từ bên trong sandbox. Mặc định là **cách ly** để đảm bảo an toàn. |
| `SKILLS_ALLOWED_SANDBOX_IMAGES` | _(trống)_ | `src/lib/skills/builtins.ts` | Danh sách cho phép, phân tách bằng dấu phẩy, gồm các image container được phép dùng để thực thi sandbox. Để trống nghĩa là chỉ sử dụng mặc định tích hợp sẵn. |
| `SKILLS_SANDBOX_DOCKER_IMAGE` | _(mặc định tích hợp sẵn)_ | `src/lib/skills/` | Image container được sử dụng khi khởi tạo sandbox dựa trên Docker. Ghi đè để ghim một image nền tùy chỉnh đã được tăng cường bảo mật. |
| `SKILLS_SANDBOX_RUNTIME` | `auto` | `src/lib/skills/sandbox.ts`, `src/lib/skills/containerProvider.ts` | Runtime container dùng để chạy skill trong sandbox: `auto` \| `docker` \| `apple` \| `wsl` \| `orbstack` \| `podman`. `auto` chọn runtime tốt nhất đã cài đặt theo hệ điều hành máy chủ (Apple Container/OrbStack trên macOS, WSL Container trên Windows, Podman trên Linux), và dùng Docker làm phương án dự phòng. |
> [!CAUTION]
> Việc bật `SKILLS_SANDBOX_NETWORK_ENABLED=true` sẽ mở một đường truyền ra ngoài cho mã skill tùy ý. Trong các môi trường triển khai dùng chung, hãy kết hợp với `OUTBOUND_SSRF_GUARD_ENABLED=true` và chính sách `CORS_ORIGIN`/proxy nghiêm ngặt.
---
## 25. Hạn mức Provider, Tunnel, Sao lưu & Runtime khác
Các endpoint hạn mức của provider, các tunnel mạng (Tailscale, Ngrok, proxy gỡ lỗi MITM), pool egress 1Proxy, sao lưu cơ sở dữ liệu và các override nhỏ theo từng tính năng được lớp executor hoặc các script tham chiếu.
| Variable | Default | Source File | Description |
| ---------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `REDIS_URL` | `redis://localhost:6379` | `src/shared/utils/rateLimiter.ts` | Chuỗi kết nối Redis cho backend giới hạn tốc độ (rate limiter). |
| `ALIBABA_CODING_PLAN_HOST` | _(host production)_ | `open-sse/services/bailianQuotaFetcher.ts` | Ghi đè host dùng để lấy hạn ngạch coding-plan của Alibaba Bailian. |
| `ALIBABA_CODING_PLAN_QUOTA_URL` | lấy từ host | `open-sse/services/bailianQuotaFetcher.ts` | Ghi đè toàn bộ URL hạn ngạch cho Alibaba Bailian. |
| `QWEN_CLOUD_COOKIE` | _(chưa thiết lập)_ | `open-sse/services/qwenTokenPlanQuotaFetcher.ts` | Cookie phiên console cho cổng hạn ngạch Token Plan cá nhân của Qwen Cloud / Model Studio (API key inference không đọc được). Sao chép toàn bộ header `Cookie` của request — nó chứa `login_qwencloud_ticket` — từ bất kỳ lệnh gọi `api.json` nào tới `cs-data.qwencloud.com` trên home.qwencloud.com › Billing › Subscription (F12 › Network). Thông tin nhạy cảm và giới hạn theo phiên; nên ưu tiên trường `qwenCloudCookie` trên Dashboard cho từng kết nối. |
| `QWEN_CLOUD_SEC_TOKEN` | _(chưa thiết lập)_ | `open-sse/services/qwenTokenPlanQuotaFetcher.ts` | Ghi đè thủ công `sec_token` cho cổng console Token Plan. Thông tin nhạy cảm; khi không được thiết lập, trình lấy dữ liệu sẽ phân giải nó từ HTML của dashboard bằng cookie. |
| `QWEN_TOKEN_PLAN_HOST` | `https://cs-data.qwencloud.com` | `open-sse/services/qwenTokenPlanQuotaFetcher.ts` | Ghi đè host cổng cho trình lấy hạn ngạch Token Plan cá nhân (ví dụ: `bailian-singapore-cs.alibabacloud.com` cho console Model Studio). |
| `QWEN_TOKEN_PLAN_DASHBOARD_URL` | `https://home.qwencloud.com/` | `open-sse/services/qwenTokenPlanQuotaFetcher.ts` | URL dashboard dùng để phân giải `sec_token` từ HTML đã đăng nhập. |
| `XIAOMI_MIMO_CONSOLE_COOKIE` | _(chưa thiết lập)_ | `open-sse/services/usage/xiaomi-mimo.ts` | Cookie phiên console cho API hạn ngạch Token Plan của Xiaomi MiMo (`platform.xiaomimimo.com/api/v1/tokenPlan/usage` + `tokenPlan/detail` — API key inference không đọc được). Sao chép toàn bộ header `Cookie` của request — nó chứa `api-platform_serviceToken` và `userId` — từ bất kỳ request nào tới `platform.xiaomimimo.com` trên trang Token Plan (F12 › Network). Thông tin nhạy cảm và giới hạn theo phiên; nên ưu tiên trường `xiaomiMimoConsoleCookie` trên Dashboard cho từng kết nối. |
| `XIAOMI_MIMO_MONTHLY_TOKEN_LIMIT` | `4100000000` | `open-sse/services/usage/xiaomi-mimo.ts` | Ngân sách hàng tháng (Credits) cho fallback Xiaomi MiMo được OmniRoute theo dõi, dùng khi chưa cấu hình console cookie. Mặc định là mức 4.1B của gói Lite; hãy đặt thành số Credits của gói (Standard 11B / Pro 38B / Max 82B). Giá trị ghi đè `providerSpecificData.monthlyTokenLimit` theo từng kết nối sẽ được ưu tiên hơn biến môi trường này. |
| `ALIBABA_FREE_TIER_VISION_FE_PATH` | `/costing-balance/free-quota-image-video` | `open-sse/services/alibabaFreeTierQuotaFetcher.ts` | Ghi đè đường dẫn front-end của console để lấy hạn mức vision/media thuộc gói miễn phí của Alibaba Model Studio. |
| `ALIBABA_FREE_TIER_MULTIMODAL_FE_PATH` | `/costing-balance/free-quota-multimodal` | `open-sse/services/alibabaFreeTierQuotaFetcher.ts` | Ghi đè đường dẫn front-end của console để lấy hạn mức đa phương thức thuộc gói miễn phí của Alibaba Model Studio. |
| `ALIBABA_FREE_TIER_AUDIO_FE_PATH` | `/costing-balance/free-quota-audio` | `open-sse/services/alibabaFreeTierQuotaFetcher.ts` | Ghi đè đường dẫn front-end của console để lấy hạn mức âm thanh thuộc gói miễn phí của Alibaba Model Studio. |
| `ALIBABA_FREE_TIER_ALLOWLIST_PATH` | _(chưa đặt)_ | `open-sse/services/alibabaFreeTierAllowlist.ts` | Đường dẫn tùy chọn tới một tệp JSON ghi đè cục bộ cho danh sách cho phép (allowlist) mô hình văn bản gói miễn phí tích hợp sẵn của Alibaba. Nếu không có sẽ lần lượt dùng `$DATA_DIR/alibaba-free-tier-allowlist.json`, rồi đến `config/alibaba-free-tier-allowlist.json`. |
| `CONTEXT_RESERVE_TOKENS` | `1024` | `open-sse/services/contextManager.ts` | Số token dự trữ cho đầu ra hoàn thành khi tính toán ngân sách prompt. |
| `CONTEXT_KEEP_LATEST_IMAGES` | `2` | `open-sse/services/contextManager.ts` | Số lượng hình ảnh nội tuyến mới nhất được giữ lại khi cắt bớt các hình cũ hơn để vừa với cửa sổ ngữ cảnh (#8560). |
| `MODEL_ALIAS_COMPAT_ENABLED` | bật | `open-sse/services/model.ts` | Bật/tắt lớp tương thích bí danh mô hình kiểu cũ được các client đời trước sử dụng. |
| `OMNIROUTE_EMERGENCY_FALLBACK` | bật | `open-sse/services/emergencyFallback.ts` | Đặt thành `false` (hoặc `0`) để tắt fallback khẩn cấp khi cạn ngân sách — cơ chế định tuyến lại các yêu cầu thất bại sang mô hình miễn phí `nvidia`/`openai/gpt-oss-120b`. Thứ tự ưu tiên thực tế là: ghi đè từ Feature Flags DB > biến môi trường > giá trị mặc định; nếu không khả dụng, dịch vụ sẽ dùng giá trị thô của biến môi trường. |
| `COMMAND_CODE_CALLBACK_PORT` | _(chưa đặt)_ | `src/app/api/providers/command-code/auth/shared.ts` | Cổng cục bộ dùng cho các callback kiểu OAuth từ trình trợ giúp Command Code CLI. |
| `COMMAND_CODE_VERSION` | `0.33.2` | `open-sse/executors/commandCode.ts` | Giá trị được gửi làm header `x-command-code-version` tới upstream Command Code. Ghi đè để nâng phiên bản CLI. |
| `COMMANDCODE_API_URL` | `https://api.commandcode.ai` | `open-sse/services/usage/command-code.ts` | URL gốc cho upstream usage/quota của Command Code, được sử dụng bởi telemetry quota-fetcher trên smartphone. Ghi đè để dùng API Command Code tự lưu trữ/thay thế. |
| `MITM_LOCAL_PORT` | `443` | `src/mitm/server.cjs` | Cổng bind cục bộ cho proxy debug MITM. |
| `MITM_DISABLE_TLS_VERIFY` | `0` | `src/mitm/server.cjs` | Đặt `1` để tắt xác minh TLS upstream (chỉ dùng khi phát triển). |
| `MITM_IDLE_TIMEOUT_MS` | `60000` | `src/mitm/socketTimeouts.ts`, `src/mitm/server.cjs` | Thời gian chờ socket nhàn rỗi (ms) cho các kết nối qua proxy; các socket nhàn rỗi vượt quá ngưỡng này sẽ bị hủy để tránh rò rỉ các tunnel nửa mở. |
| `BRIDGE_PORT` | `20129` | `bin/antigravity-bridge.mjs` | Cổng mà bridge MITM Antigravity lắng nghe. |
| `ROUTER_URL` | `http://127.0.0.1:20128/v1/antigravity` | `bin/antigravity-bridge.mjs` | Endpoint router mà bridge chuyển tiếp lưu lượng Antigravity tới. |
| `CERT_DIR` | `/mitm` | `bin/antigravity-bridge.mjs` | Ghi đè thư mục mà bridge đọc vật liệu TLS. Mô hình chứng chỉ được chọn giống như server AgentBridge: `server.crt`/`server.key` cho cài đặt leaf legacy, nếu không thì `ca.crt`/`ca.key` (root CA, một leaf cho mỗi host bị chặn; bắt buộc bởi `MITM_ROOT_CA_ENABLED=true`). Bridge sẽ thoát khi khởi động nếu thiếu các tệp của mô hình đang hoạt động. |
| `MITM_VERBOSE` | `1` | `src/mitm/server.cjs`, `src/mitm/_internal/bypass.cjs` | Mức độ chi tiết của log quyết định định tuyến: `0` tắt log, giá trị cao hơn ghi thêm các quyết định bypass/route. |
| `MITM_ROOT_CA_ENABLED` | `false` | `src/mitm/manager.ts` | Đặt `true` để chọn tham gia mô hình chứng chỉ root-CA + leaf theo từng host (#6684). Cài đặt mới sẽ tự động có; các cài đặt đã có leaf legacy được tin cậy từ trước sẽ giữ chứng chỉ fixed-SAN legacy trừ khi chọn tham gia. |
| `MITM_CERT_MODE` | `legacy` | `src/mitm/manager.ts`, `src/mitm/server.cjs` | Được đặt BỞI trình quản lý MITM cho tiến trình proxy được sinh ra (`root-ca` \| `legacy`) — phản ánh quyết định di chuyển chứng chỉ; không nhằm mục đích đặt thủ công. |
| `OMNIROUTE_NO_SUDO` | `0` | `src/mitm/systemCommands.ts` | Đặt `1` (giá trị truthy) để loại bỏ `sudo` ở đầu các lệnh tin cậy chứng chỉ MITM — dành cho các triển khai không có root / dùng user namespace, nơi người vận hành tự tin cậy CA theo cách thủ công (ví dụ: thông qua cơ chế extra-CA-certs của Node). |
| `SKIP_ANTIGRAVITY_DNS` | _(chưa đặt)_ | `src/mitm/dns/provision.ts` | Đặt `true` để bỏ qua hoàn toàn việc cung cấp các mục DNS trong `/etc/hosts` cho các hostname proxy Antigravity — dành cho các container không có sudo/root. |
| `OMNIROUTE_SKIP_DNS_WRITE` | _(chưa đặt)_ | `src/mitm/dns/dnsConfig.ts` | Đặt `1` để bỏ qua việc ghi vào file hosts khi thêm/xóa các mục DNS — dành cho các môi trường kiểm thử bị sandbox hoặc chỉ đọc. |
| `OMNIROUTE_SKIP_SYSTEM_TRUST` | `0` | `src/mitm/cert/install.ts`, `src/mitm/tproxy/caTrust.ts` | Cơ chế bảo vệ chỉ dành cho test/CI: đặt `1` để biến việc cài đặt/gỡ cài đặt tin cậy chứng chỉ thành thao tác rỗng (no-op), nhờ đó bộ test không bao giờ thay đổi kho tin cậy của hệ điều hành. Được thiết lập tự động bởi phần thiết lập test và các workflow CI. |
| `CHANGELOG_BASE_REF` | _(tự động)_ | `scripts/check/check-changelog-integrity.mjs` | Base ref tường minh cho cổng kiểm tra chống "ăn mất" CHANGELOG (mặc định là nhánh gốc của PR trong CI, hoặc `release/v*` cao nhất). |
| `FREE_PROXY_AUTO_SYNC_ENABLED` | `false` | `src/lib/freeProxyProviders/scheduler.ts` | Đặt `true` để bật bộ lập lịch tự động đồng bộ pool proxy miễn phí chạy nền. Chế độ opt-in, mặc định tắt. |
| `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` | `1800000` | `src/lib/freeProxyProviders/scheduler.ts` | Khoảng thời gian tự động đồng bộ tính bằng mili giây (mặc định 30 phút). |
| `FREE_PROXY_1PROXY_ENABLED` | `true` | `src/lib/freeProxyProviders/oneproxy.ts` | Bật nguồn proxy miễn phí 1proxy. Đặt thành `false` để tắt. |
| `FREE_PROXY_1PROXY_API_URL` | _(xem oneproxy.ts)_ | `src/lib/freeProxyProviders/oneproxy.ts` | Ghi đè URL API của 1proxy. |
| `FREE_PROXY_1PROXY_MAX` | `500` | `src/lib/freeProxyProviders/oneproxy.ts` | Số proxy tối đa được lấy trong mỗi lần đồng bộ từ 1proxy. |
| `FREE_PROXY_1PROXY_MIN_QUALITY` | `50` | `src/lib/freeProxyProviders/oneproxy.ts` | Ngưỡng điểm chất lượng tối thiểu cho các lượt nhập từ 1proxy. |
| `FREE_PROXY_PROXIFLY_ENABLED` | `true` | `src/lib/freeProxyProviders/proxifly.ts` | Bật nguồn proxy miễn phí Proxifly. Đặt thành `false` để tắt. |
| `FREE_PROXY_PROXIFLY_QUANTITY` | `100` | `src/lib/freeProxyProviders/proxifly.ts` | Số lượng proxy cần lấy trong mỗi lần đồng bộ Proxifly. |
| `FREE_PROXY_PROXIFLY_ANONYMITY` | `elite` | `src/lib/freeProxyProviders/proxifly.ts` | Bộ lọc mức độ ẩn danh cho Proxifly (`elite`, `anonymous`, `transparent`). |
| `FREE_PROXY_IPLOCATE_ENABLED` | `false` | `src/lib/freeProxyProviders/iplocate.ts` | Bật nguồn proxy miễn phí IPLocate. Chỉ áp dụng khi chủ động chọn tham gia (opt-in). |
| `FREE_PROXY_IPLOCATE_BASE_URL` | `https://raw.githubusercontent.com/iplocate/free-proxy-list/main/protocols` | `src/lib/freeProxyProviders/iplocate.ts` | Ghi đè URL cơ sở của danh sách proxy IPLocate. |
| `FREE_PROXY_WEBSHARE_ENABLED` | `true` | `src/lib/freeProxyProviders/webshare.ts` | Bật nguồn pool proxy Webshare. Đặt thành `false` để tắt; đồng thời yêu cầu phải thiết lập `FREE_PROXY_WEBSHARE_API_KEY`. |
| `FREE_PROXY_WEBSHARE_API_KEY` | _(không có)_ | `src/lib/freeProxyProviders/webshare.ts` | Token API của tài khoản Webshare (`Authorization: Token `). Bắt buộc — nhà cung cấp sẽ vẫn bị vô hiệu hóa nếu thiếu token này. |
| `FREE_PROXY_WEBSHARE_API_URL` | `https://proxy.webshare.io/api/v2/proxy/list/` | `src/lib/freeProxyProviders/webshare.ts` | Ghi đè URL API danh sách proxy Webshare. |
| `FREE_PROXY_WEBSHARE_MAX` | `500` | `src/lib/freeProxyProviders/webshare.ts` | Số proxy tối đa được nhập trong mỗi lần đồng bộ Webshare. |
| `NEXT_PUBLIC_VERCEL_RELAY_ENABLED` | `true` | `src/app/(dashboard)/…/ProxyPoolTab.tsx` | Hiện/ẩn nút Deploy Vercel Relay trong tab Proxy Pool. |
| `VERCEL_API_BASE` | `https://api.vercel.com` | `src/app/api/settings/proxy/vercel-deploy/route.ts` | Ghi đè URL gốc của Vercel API (dùng để kiểm thử). |
| `NEXT_PUBLIC_VERCEL_RELAY_DEFAULT_PROJECT` | `omniroute-relay` | `src/app/(dashboard)/…/VercelRelayModal.tsx` | Tên dự án mặc định được điền sẵn trong modal triển khai Vercel Relay. |
| `TAILSCALE_BIN` | _(tự động phát hiện)_ | `src/lib/tailscaleTunnel.ts` | Đường dẫn tường minh đến tệp nhị phân `tailscale`. |
| `TAILSCALED_BIN` | _(tự động phát hiện)_ | `src/lib/tailscaleTunnel.ts` | Đường dẫn tường minh đến tệp nhị phân daemon `tailscaled`. |
| `TAILSCALE_AUTHKEY` | _(chưa thiết lập)_ | `src/lib/tailscaleTunnel.ts` | Khóa xác thực Tailscale được chia sẻ trước để chạy `tailscale up` không tương tác / headless (được truyền qua `--auth-key=`). Khi chưa thiết lập, việc đăng nhập sẽ quay về URL xác thực tương tác qua trình duyệt. |
| `NGROK_AUTHTOKEN` | _(chưa thiết lập)_ | `src/lib/ngrokTunnel.ts` | Xác thực các tunnel ngrok đi ra ngoài. |
| `DB_BACKUP_MAX_FILES` | `20` | `src/lib/db/backup.ts` | Số lượng tệp sao lưu SQLite tối đa được giữ lại bởi quá trình dọn dẹp bản sao lưu thủ công/theo lịch. Các snapshot migration được định địa chỉ theo nội dung và được tái sử dụng cho trạng thái DB giống hệt nhau; chúng không bị cắt tỉa trong cửa sổ migration đồng thời. Ghi đè giá trị đã lưu từ Cài đặt → Thời gian lưu giữ bản sao lưu cơ sở dữ liệu. |
| `DB_BACKUP_RETENTION_DAYS` | `0` | `src/lib/db/backup.ts` | Tuổi tối đa (ngày) được giữ lại bởi quá trình dọn dẹp bản sao lưu thủ công/theo lịch. `0` tắt việc cắt tỉa dựa trên tuổi. Các snapshot migration không bị cắt tỉa trong cửa sổ migration đồng thời. Ghi đè giá trị đã lưu từ Cài đặt → Thời gian lưu giữ bản sao lưu cơ sở dữ liệu. |
| `OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS` | `30000` | `src/lib/jobs/backupScheduleJob.ts` | Khoảng thời gian tick (ms) của job phía máy chủ thực thi `backup-schedule.json`. Phải nhỏ hơn đáng kể so với độ chi tiết cron 1 phút; các giá trị dưới `5000` hoặc không phân tích được sẽ quay về `30000`. |
| `CONTAINER_HOST` | `docker` | `scripts/check-permissions.sh` | Gợi ý về container runtime cho bước kiểm tra quyền của entrypoint. Đặt thành `podman` cho bất kỳ cấu trúc liên kết Podman nào. Vì container không thể xác định engine đang chạy cục bộ hay được truy cập thông qua Podman Machine, cảnh báo được giữ trung lập về cấu trúc liên kết và trỏ đến `contrib/podman/README.md`. |
| `QUOTA_STORE_DRIVER` | `sqlite` | `src/lib/quota/storeFactory.ts` | Backend lưu trữ mức tiêu thụ quota chia sẻ: `sqlite` (mặc định) hoặc `redis`. |
| `QUOTA_STORE_REDIS_URL` | _(chưa đặt)_ | `src/lib/quota/storeFactory.ts` | Chuỗi kết nối Redis được sử dụng khi `QUOTA_STORE_DRIVER=redis` (ví dụ: `redis://localhost:6379`). |
| `QUOTA_SATURATION_THRESHOLD` | `0.5` | `src/lib/quota/enforce.ts` | Tỷ lệ bão hòa của pool (0..1); khi đạt hoặc vượt ngưỡng này, pool chuyển sang chế độ nghiêm ngặt (không cho mượn). |
| `QUOTA_SOFT_DEPRIORITIZE_FACTOR` | `0.7` | `open-sse/services/combo.ts` | Hệ số nhân điểm (0..1) áp dụng cho một mục tiêu khi chính sách quota mềm giảm mức ưu tiên của nó. |
| `STATUS_SOFT_DEPRIORITIZE_FACTOR` | `0.5` | `open-sse/services/combo/autoStrategy.ts` | Hệ số nhân điểm (0..1) áp dụng cho một provider đã cạn kiệt (`credits_exhausted`/`rate_limited`) trong việc chấm điểm auto-combo khi tính năng cắt quota preflight đang TẮT (#4540). |
| `QUOTA_CONSUMPTION_RETENTION_DAYS` | `14` | `src/lib/db/quotaConsumption.ts` | Khoảng thời gian lưu giữ (ngày) cho các bucket `quota_consumption` trước khi GC (`gcQuotaConsumption`). |
| `QUOTA_PREFLIGHT_CUTOFF_ENABLED` | `false` | `src/lib/resilience/settings.ts` | Tùy chọn bật (mặc định TẮT): bật tính năng cắt quota cứng trong định tuyến tự động, loại bỏ các ứng viên có quota thấp trước khi chấm điểm. |
| `OMNIROUTE_AUTO_FREE_FALLBACK_TO_FULL_POOL` | `false` | `open-sse/services/autoCombo/virtualFactory.ts` | Tùy chọn bật (mặc định TẮT): khi bộ lọc `auto/:` không khớp với bất kỳ ứng viên nào đã kết nối, khôi phục hành vi cũ là quay về pool đầy đủ (không lọc) thay vì trả về pool rỗng. Mặc định TẮT khiến `:free` mang nghĩa "chỉ tầng miễn phí". |
| `OMNIROUTE_CHAOS_MAX_PANEL` | `5` | `open-sse/services/autoCombo/virtualFactory.ts` | Giới hạn kích thước panel (kẹp trong khoảng 1–10) cho biến thể broadcast `auto/*:chaos` — một yêu cầu được phân tán tối đa đến số lượng model đa dạng theo provider này. |
| `OMNIROUTE_CHAOS_MIN_PANEL` | _(mặc định của engine)_ | `open-sse/services/autoCombo/virtualFactory.ts` | Tinh chỉnh kích thước panel tối thiểu được chuyển tiếp đến trình xử lý broadcast chaos; để trống sẽ giữ giá trị mặc định của engine. |
| `OMNIROUTE_CHAOS_PANEL_TIMEOUT_MS` | _(mặc định của engine)_ | `open-sse/services/autoCombo/virtualFactory.ts` | Timeout cứng (ms) cho toàn bộ quá trình fan-out của chaos panel; để trống sẽ giữ giá trị mặc định của engine. |
| `GROK_AUTH_PATH` | `~/.grok/auth.json` | `open-sse/services/grokQuotaFetcher.ts` | Đường dẫn của tệp `auth.json` của Grok CLI dùng để lấy hạn ngạch hàng tuần của grok-web; ghi đè cho các bài kiểm thử hoặc cài đặt CLI không chuẩn. |
| `AGENTBRIDGE_UPSTREAM_CA_CERT` | _(chưa đặt)_ | `src/mitm/manager.ts` | Chứng chỉ CA bổ sung (PEM) được tin cậy cho các kết nối TLS upstream của AgentBridge. |
| `INSPECTOR_BUFFER_SIZE` | `1000` | `src/mitm/inspector/buffer.ts` | Số lượng request đã bắt tối đa được giữ trong ring buffer của Traffic Inspector. |
| `INSPECTOR_MAX_BODY_KB` | `1024` | `src/mitm/inspector/buffer.ts` | Kích thước body request/response đã bắt tối đa (KB) trước khi bị cắt bớt. |
| `INSPECTOR_HTTP_PROXY_PORT` | `8080` | `src/mitm/inspector/httpProxyServer.ts` | Cổng cục bộ cho HTTP proxy của Traffic Inspector. |
| `INSPECTOR_HTTP_PROXY_AUTOSTART` | `false` | `src/mitm/inspector/httpProxyServer.ts` | Tự động khởi động HTTP proxy của inspector khi khởi động hệ thống. |
| `INSPECTOR_LLM_HOSTS_EXTRA` | _(chưa đặt)_ | `src/lib/inspector/captureState.ts` | Các hostname bổ sung (phân tách bằng dấu phẩy) được coi là các endpoint LLM để bắt. |
| `INSPECTOR_MASK_SECRETS` | `true` | `src/mitm/inspector/buffer.ts` | Che giấu các thông tin bí mật (auth header / API key) trong lưu lượng đã bắt. |
| `INSPECTOR_SYSTEM_PROXY_GUARD_MINUTES` | `30` | `src/app/api/tools/traffic-inspector/capture-modes/system-proxy/route.ts` | Số phút trước khi bộ bảo vệ system-proxy tự động khôi phục cài đặt proxy của hệ điều hành. |
| `INSPECTOR_INTERNAL_INGEST_TOKEN` | _(tự động)_ | `src/app/api/tools/traffic-inspector/internal/ingest/route.ts` | Token xác thực việc tiếp nhận dữ liệu capture nội bộ vào inspector. |
| `PLAYGROUND_COMPARE_MAX_COLUMNS` | `4` | `src/app/(dashboard)/dashboard/playground/` | Số lượng cột song song tối đa trong chế độ so sánh của Playground. |
| `PLAYGROUND_IMPROVE_PROMPT_DEFAULT_MODEL` | _(chưa thiết lập)_ | `src/app/(dashboard)/dashboard/playground/` | Model mặc định cho hành động 'improve prompt' của Playground (quay về model đang hoạt động khi chưa được thiết lập). |
| `BIFROST_ENABLED` | `1` | `src/app/api/v1/relay/chat/completions/bifrost/route.ts` | Công tắc tắt khẩn cấp chính cho sidecar proxy bifrost. Khi đặt thành `0`, route trả về 503 kèm header `X-Bifrost-Killswitch` và operator được chuyển hướng sang đường dẫn TS. Dùng để vô hiệu hóa sidecar mà không cần triển khai lại (sự cố router tier-1, xoay vòng key). |
| `BIFROST_BASE_URL` | _(chưa thiết lập)_ | `src/app/api/v1/relay/chat/completions/bifrost/route.ts` | Khi được thiết lập, route sidecar proxy Bifrost sẽ chuyển tiếp lưu lượng `/v1/chat/completions` đến gateway Go này thay vì trình xử lý relay TS. Chưa thiết lập → 503 kèm fallback. Dấu gạch chéo ở cuối sẽ bị loại bỏ. |
| `BIFROST_PORT` | `8080` | `src/lib/services/bootstrap.ts` | Cổng mà dịch vụ nhúng Bifrost được giám sát sẽ liên kết tới (`127.0.0.1:`) khi OmniRoute quản lý vòng đời của sidecar Bifrost. Mặc định là `8080`. |
| `LLMLINGUA_PORT` | `20135` | `src/lib/services/bootstrap.ts` | Cổng mà dịch vụ nén LLMLingua được giám sát sẽ liên kết tới (`127.0.0.1:`). Mặc định là `20135`. |
| `LLMLINGUA_BASE_URL` | `http://127.0.0.1:20135` | `open-sse/services/compression/engines/llmlingua/index.ts` | URL cơ sở cho daemon microservice nén HTTP LLMLingua cục bộ. Mặc định là `http://127.0.0.1:20135`. |
| `LLMLINGUA_MODEL` | `atjsh/llmlingua-2-js-tinybert-meetingbank` | `src/lib/services/installers/llmlingua.ts` | ID model Hugging Face mà sidecar LLMLingua được giám sát sẽ tải (được truyền vào biến môi trường của tiến trình con). |
| `BIFROST_API_KEY` | _(chưa thiết lập)_ | `src/app/api/v1/relay/chat/completions/bifrost/route.ts` | API key cho gateway Bifrost (được gửi dưới dạng `Authorization: Bearer ...`). Nếu chưa thiết lập, route yêu cầu request phải mang theo một API key OmniRoute hợp lệ; key này chỉ dùng cho việc xác thực phía gateway. |
| `BIFROST_STREAMING_ENABLED` | `true` | `src/app/api/v1/relay/chat/completions/bifrost/route.ts` | Khi đặt thành true, route sidecar Bifrost truyền phản hồi về qua SSE thông qua gateway thay vì bộ thực thi streaming TS. Đặt thành `0` để buộc trả về phản hồi JSON không streaming qua gateway. |
| `BIFROST_TIMEOUT_MS` | `30000` | `src/app/api/v1/relay/chat/completions/bifrost/route.ts` | Thời gian chờ (timeout) cho mỗi yêu cầu khi proxy tới gateway Bifrost (ms). Khi hết thời gian chờ, route trả về đường dẫn relay TS qua header `X-Bifrost-Fallback`. |
| `OMNIROUTE_BIFROST_KEY` | _(chưa đặt)_ | `src/app/api/v1/relay/chat/completions/bifrost/route.ts` | Bí danh của `BIFROST_API_KEY` (được các script đọc env qua `OMNIROUTE_*` sử dụng). `BIFROST_API_KEY` được ưu tiên khi cả hai cùng được đặt. |
| `OMNIROUTE_RELAY_BACKEND` | `ts` / `auto` | `src/app/api/v1/relay/chat/completions/routingBackend.ts` | Backend relay cho `/api/v1/relay/chat/completions`: `ts \| bifrost \| auto`. `ts` = relay TypeScript (mặc định khi Bifrost chưa được cấu hình); `auto` chọn Bifrost khi `BIFROST_BASE_URL` được đặt và `BIFROST_ENABLED` ≠ `0`, kèm cơ chế tự động quay về TS nếu không kết nối được sidecar; `bifrost` buộc dùng Bifrost (nghiêm ngặt, không fallback). Xác thực/rate-limit/injection-guard/allowlist luôn chạy trước trong route Next. Phản hồi mang các header `X-Routing-Backend` / `X-Routing-Fallback` / `X-Routing-Fallback-Reason`. |
| `RELAY_ROUTING_BACKEND` | _(chưa đặt)_ | `src/app/api/v1/relay/chat/completions/routingBackend.ts` | Bí danh được chấp nhận của `OMNIROUTE_RELAY_BACKEND` (cùng các giá trị `ts \| bifrost \| auto`). `OMNIROUTE_RELAY_BACKEND` được ưu tiên khi cả hai cùng được đặt. |
| `OMNIROUTE_BIFROST_FAILURE_COOLDOWN_MS` | `5000` | `src/app/api/v1/relay/chat/completions/bifrostCooldown.ts` | Thời gian cooldown (ms) sau khi một lần chuyển tới sidecar Bifrost thất bại ở chế độ `auto`, trước khi relay thử lại sidecar; trong thời gian cooldown, nó định tuyến thẳng sang đường dẫn TS, sau đó dò thử lại. `0` để tắt. Chỉ áp dụng khi `OMNIROUTE_RELAY_BACKEND=auto`. |
| `OMNIROUTE_TLS_CERT` | _(chưa đặt)_ | `bin/cli/commands/serve.mjs` | Đường dẫn tới chứng chỉ TLS PEM để chạy `omniroute serve` qua HTTPS (tương đương `--tls-cert`). Phải đi kèm với `OMNIROUTE_TLS_KEY`; khi đó máy chủ độc lập sẽ kết thúc TLS trên cùng một listener (`wss://` vẫn hoạt động bình thường). Không đặt → HTTP thuần. Nếu chỉ cung cấp một trong hai cert/key, hoặc đường dẫn không đọc được, hệ thống sẽ ghi cảnh báo vào log và vẫn dùng HTTP. |
| `OMNIROUTE_TLS_KEY` | _(chưa đặt)_ | `bin/cli/commands/serve.mjs` | Đường dẫn tới khóa riêng TLS PEM cho HTTPS của `omniroute serve` (tương đương `--tls-key`). Phải đi kèm với `OMNIROUTE_TLS_CERT`. Xem `OMNIROUTE_TLS_CERT`. |
| `OMNIROUTE_LOCAL_ENDPOINTS_ENABLED` | `0` | `src/lib/security/localEndpoints.ts` | Công tắc tổng cho các route `/api/local/*`. Khi không đặt hoặc đặt `0`, tất cả các route `/api/local/*` trả về 503 trong môi trường production. Phải đặt `1` trong các triển khai không phải loopback để bật trình khởi chạy Redis và các trình khởi động dịch vụ cục bộ 1-click tương tự. Bảo vệ hai lớp cùng với cơ chế phân loại route-guard `isLocalOnlyPath()` (`LOCAL_ONLY_API_PREFIXES` trong `src/server/authz/routeGuard.ts`). |
| `OMNIROUTE_LOCAL_ENDPOINTS_TOKEN` | _(chưa đặt)_ | `src/lib/security/localEndpoints.ts` | Bearer token cho các lệnh gọi `/api/local/*` không nằm trên loopback (ví dụ: ứng dụng desktop). Khi được đặt, các yêu cầu từ IP không phải loopback phải mang header `Authorization: Bearer `. Bắt buộc khi `OMNIROUTE_LOCAL_ENDPOINTS_ENABLED=1` trong các triển khai không phải loopback. |
| `OMNIROUTE_REDIS_CONTAINER_NAME` | `omniroute-redis` | `bin/cli/commands/redis.mjs` | Tên container cho bộ khởi chạy Redis 1-chạm (`omniroute redis up`). Được dùng bởi cả CLI và GUI `RedisLauncherPanel`. |
| `OMNIROUTE_REDIS_HOST_PORT` | `6379` | `bin/cli/commands/redis.mjs` | Cổng host cho bộ khởi chạy Redis 1-chạm. Tăng lên nếu host đã bind cổng 6379. Cổng nội bộ của container vẫn giữ nguyên 6379. |
| `OMNIROUTE_REDIS_BIND_HOST` | `127.0.0.1` | `bin/cli/commands/redis.mjs` | Giao diện host mà bộ khởi chạy Redis 1-chạm publish lên. Bộ khởi chạy khởi động Redis KHÔNG có mật khẩu, vì vậy việc bind `0.0.0.0` sẽ trao cho mọi host trong LAN của bạn một Redis không xác thực — chỉ mở rộng giá trị này nếu bạn cũng tự đặt mật khẩu cho instance. |
| `REDIS_BIND_HOST` | `127.0.0.1` | `docker-compose.yml` | Giao diện host mà docker-compose publish Redis sidecar lên (#9286). Redis của compose chạy không có `requirepass`; các container ứng dụng truy cập nó qua mạng compose (`redis:6379`) — cổng được publish chỉ tồn tại để phục vụ các công cụ phía host. `0.0.0.0` sẽ để lộ một Redis không xác thực ra toàn bộ LAN. |
| `REDIS_PORT` | `6379` | `docker-compose.yml` | Cổng host cho Redis sidecar của compose. |
| `APP_BIND_HOST` | `127.0.0.1` | `docker-compose.yml`, `docker-compose.prod.yml` | Giao diện host mà docker-compose publish các cổng dashboard/API/live-WS của chính ứng dụng lên (#12568). Với `REQUIRE_API_KEY=false` là giá trị mặc định được phát hành trong `.env.example`, `0.0.0.0` sẽ để lộ proxy LLM `/v1` ẩn danh ra toàn bộ LAN/WAN — chỉ mở rộng khi `REQUIRE_API_KEY=true` hoặc khi một reverse proxy đứng trước tự thực thi xác thực. |
| `QDRANT_BIND_HOST` | `127.0.0.1` | `docker-compose.yml` | Giao diện host mà docker-compose publish Qdrant memory sidecar lên (#12578). Lý do lộ ra LAN giống như `REDIS_BIND_HOST`. |
| `BIFROST_BIND_HOST` | `127.0.0.1` | `docker-compose.yml` | Giao diện host mà docker-compose publish Bifrost router sidecar lên (#12578). Lý do lộ ra LAN giống như `REDIS_BIND_HOST`. |
| `REDIS_KEY_PREFIX` | `omniroute:` | `src/shared/utils/rateLimiter.ts` | Tiền tố namespace áp dụng cho mọi khóa Redis của OmniRoute (rate limiter, cache xác thực, kho quota, circuit breaker warmup). Ngăn xung đột khóa khi instance Redis được dùng chung với các ứng dụng khác (#11042). |
| `OMNIROUTE_INTERNAL_SERVICE_TOKEN` | _(chưa đặt — cơ chế bị vô hiệu hóa)_ | `src/lib/api/internalServiceAuth.ts` | Secret dùng chung cho các bước chuyển tiếp REST nội bộ có bảo toàn danh tính (#9260): các thành phần OmniRoute khi gọi các route OmniRoute cục bộ khác sẽ gửi nó dưới dạng `x-omniroute-internal-service-token` để danh tính của người gọi ban đầu được bảo toàn. Được so sánh bằng `timingSafeEqual`. |
| `OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE` | _(chưa thiết lập)_ | `src/lib/api/internalServiceAuth.ts` | Biến thể dạng file bí mật của token dịch vụ nội bộ: đường dẫn tới file mà nội dung đã được trim chính là token. Chỉ được tham khảo khi biến inline chưa được thiết lập. |
| `OPENROUTER_PROVIDER_STATS_ENABLED` | `true` | `src/lib/catalog/openrouterProviderStats.ts` | Bổ sung danh sách providers trên dashboard với số liệu xếp hạng hàng tuần của OpenRouter (#9324). Bật theo mặc định; đặt `false` để bỏ qua hoàn toàn việc fetch nền (không chặn, không bao giờ gây lỗi nghiêm trọng). |
| `OPENROUTER_PROVIDER_STATS_TTL_MS` | `86400000` (24h) | `src/lib/catalog/openrouterProviderStats.ts` | TTL cache cho snapshot thống kê provider của OpenRouter, tính bằng mili giây. |
| `OMNIROUTE_REDIS_IMAGE` | `redis:7-alpine` | `bin/cli/commands/redis.mjs` | Image Redis được sử dụng bởi trình khởi chạy Redis 1-cú-nhấp. Ghi đè thành `redis:8-alpine` hoặc một mirror registry riêng nếu cần. |
| `QDRANT_HOST` | `qdrant` | _(profile cluster tùy chọn)_ | Hostname của Qdrant sidecar khi `--profile memory` được kích hoạt. Mặc định trỏ tới tên dịch vụ qdrant trong mạng; ghi đè để dùng một triển khai bên ngoài. Chỉ được sử dụng khi `qdrantEnabled` là `true` trong mã (`src/lib/memory/vectorStore.ts:108`). |
| `QDRANT_PORT` | `6333` | _(profile cluster tùy chọn)_ | Cổng REST của Qdrant sidecar. |
| `QDRANT_GRPC_PORT` | `6334` | _(profile cluster tùy chọn)_ | Cổng gRPC của Qdrant sidecar. Được sử dụng bởi các thư viện client ưu tiên gRPC hơn REST cho các thao tác streaming. |
| `QDRANT_API_KEY` | _(chưa thiết lập)_ | _(profile cluster tùy chọn)_ | API key tùy chọn cho Qdrant Cloud hoặc một instance on-prem có xác thực. Để trống → không gửi header `api-key`. |
| `QDRANT_COLLECTION` | `omniroute-memory` | _(profile cluster tùy chọn)_ | Tên collection cho các embedding bộ nhớ hội thoại của OmniRoute. Được tạo ở lần chạy đầu tiên với số chiều `QDRANT_VECTOR_SIZE`. |
| `QDRANT_EMBEDDING_MODEL` | `text-embedding-3-small` | _(profile cluster tùy chọn)_ | Tên model embedding mặc định được ghi trong metadata của collection Qdrant. Embedding thực tế được tạo bởi bất kỳ provider nào mà trường `embeddingModel` trong cài đặt của OmniRoute trỏ tới. |
| `QDRANT_VECTOR_SIZE` | `1536` | _(hồ sơ cụm tùy chọn)_ | Kích thước vector embedding. Phải khớp với mô hình bạn dùng để embed (text-embedding-3-small → 1536; ada-002 → 1536; nomic-embed-text → 768). |
| `QDRANT_HNSW_EF_CONSTRUCT` | `128` | _(hồ sơ cụm tùy chọn)_ | Độ chính xác của chỉ mục HNSW tại thời điểm xây dựng. Càng cao = xây dựng chậm hơn, tìm kiếm nhanh hơn. |
| `OMNIROUTE_ROTATION_ENABLED` | `true` | `open-sse/services/rotationConfig.ts` | Công tắc tổng cho việc luân chuyển tài khoản do người vận hành cấu hình. Khi `false`, không lớp `OMNIROUTE_ROTATE_*` nào bên dưới kích hoạt chuyển đổi dự phòng tài khoản (trạng thái tắt tổng cũng chặn các lớp 429/500/502 được bật mặc định). Cho phép một front-end giám sát (ví dụ: ứng dụng desktop VibeProxy) ánh xạ các quy tắc luân chuyển của chính nó lên bộ máy chuyển đổi dự phòng tài khoản của backend. |
| `OMNIROUTE_ROTATION_RATE_LIMIT_RESET_SECONDS` | `0` | `open-sse/services/rotationConfig.ts` | Thời gian chờ (giây) áp dụng cho tài khoản bị giới hạn tốc độ khi upstream không đưa ra gợi ý reset rõ ràng. `0` = dùng thời gian chờ mặc định của bộ máy thay vì một giá trị ghi đè cố định. |
| `OMNIROUTE_ROTATION_DISABLE_TAG_WITHOUT_RESET` | `true` | `open-sse/services/rotationConfig.ts` | Phản ánh tùy chọn của front-end "không gắn thẻ là bị giới hạn tốc độ nếu không có thời điểm reset". |
| `OMNIROUTE_ROTATE_ON_429` | `true` | `open-sse/services/rotationConfig.ts` | Bật chuyển đổi dự phòng theo từng mã trạng thái cho lỗi `429`. Khi `false` (và `OMNIROUTE_ROTATION_ENABLED=true`), lỗi `429` không còn kích hoạt luân chuyển tài khoản mà sẽ được trả về cho client. |
| `OMNIROUTE_ROTATE_429_THRESHOLD` | `1` | `open-sse/services/rotationConfig.ts` | Số lỗi `429` trong khoảng `OMNIROUTE_ROTATE_429_WINDOW_SECONDS` cần đạt trước khi tài khoản được luân chuyển. `1` (mặc định) luân chuyển ngay lập tức, giữ nguyên hành vi trước đây. |
| `OMNIROUTE_ROTATE_429_WINDOW_SECONDS` | `120` | `open-sse/services/rotationConfig.ts` | Cửa sổ trượt (giây) trong đó các lỗi `429` được đếm vào `OMNIROUTE_ROTATE_429_THRESHOLD`. |
| `OMNIROUTE_ROTATE_ON_500` | `true` | `open-sse/services/rotationConfig.ts` | Bật chuyển đổi dự phòng theo từng mã trạng thái cho lỗi máy chủ `5xx` (ngoại trừ `502`, vốn có lớp riêng). Khi `false`, các lỗi này không còn kích hoạt luân chuyển tài khoản. |
| `OMNIROUTE_ROTATE_500_THRESHOLD` | `1` | `open-sse/services/rotationConfig.ts` | Số lỗi `5xx` trong khoảng `OMNIROUTE_ROTATE_500_WINDOW_SECONDS` cần đạt trước khi tài khoản được luân chuyển. `1` (mặc định) luân chuyển ngay lập tức. |
| `OMNIROUTE_ROTATE_500_WINDOW_SECONDS` | `120` | `open-sse/services/rotationConfig.ts` | Cửa sổ trượt (giây) trong đó các lỗi `5xx` được đếm vào `OMNIROUTE_ROTATE_500_THRESHOLD`. |
| `OMNIROUTE_ROTATE_ON_502` | `true` | `open-sse/services/rotationConfig.ts` | Bật fallback theo mã trạng thái cho các lỗi `502` (bad gateway). Khi là `false`, các lỗi `502` không còn kích hoạt xoay vòng tài khoản. |
| `OMNIROUTE_ROTATE_502_THRESHOLD` | `1` | `open-sse/services/rotationConfig.ts` | Số lượng lỗi `502` trong `OMNIROUTE_ROTATE_502_WINDOW_SECONDS` cần có trước khi tài khoản bị xoay vòng. `1` (mặc định) sẽ xoay vòng ngay lập tức. |
| `OMNIROUTE_ROTATE_502_WINDOW_SECONDS` | `120` | `open-sse/services/rotationConfig.ts` | Cửa sổ trượt (giây) trong đó các lỗi `502` được đếm vào `OMNIROUTE_ROTATE_502_THRESHOLD`. |
| `OMNIROUTE_ROTATE_ON_400` | `false` | `open-sse/services/rotationConfig.ts` | Tùy chọn bật (mặc định TẮT): khi là `true`, một lỗi `400` (bad request) thông thường cũng kích hoạt xoay vòng tài khoản. Điều này chỉ mang tính bổ sung — nó không bao giờ chặn hành vi hiện có của engine, trong đó một lỗi `400` mang nội dung về rate-limit/quota vẫn gây chuyển đổi bất kể cờ này. |
| `OMNIROUTE_ROTATE_400_THRESHOLD` | `1` | `open-sse/services/rotationConfig.ts` | Số lượng lỗi `400` trong `OMNIROUTE_ROTATE_400_WINDOW_SECONDS` cần có trước khi tài khoản bị xoay vòng (chỉ được xem xét khi `OMNIROUTE_ROTATE_ON_400=true`). |
| `OMNIROUTE_ROTATE_400_WINDOW_SECONDS` | `120` | `open-sse/services/rotationConfig.ts` | Cửa sổ trượt (giây) trong đó các lỗi `400` được đếm vào `OMNIROUTE_ROTATE_400_THRESHOLD`. |
### Trình lập lịch Warmup Claude
Warmup theo cron cho các kết nối Anthropic OAuth đã chọn tham gia, nhờ đó cửa sổ rate-limit 5 giờ được mở bằng một request định kỳ đơn giản thay vì bằng request thực đầu tiên (#8848). Trình lập lịch sẽ tắt trừ khi `OMNIROUTE_WARMUP_ENABLED` có giá trị truthy **và** kết nối được đánh dấu trong `settings.claudeWarmup.connections`; danh sách kết nối trống đồng nghĩa với việc không có kết nối nào được warmup ngay cả khi biến môi trường đã bật.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------ | --------------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_WARMUP_ENABLED` | _(chưa đặt → tắt)_ | `src/lib/warmupScheduler.ts` | Công tắc chính cho bộ lập lịch warmup. Chấp nhận `1`/`true`/`yes`/`on` (không phân biệt hoa thường, đã cắt khoảng trắng đầu cuối). Bất kỳ giá trị nào khác, hoặc không được đặt, sẽ giữ bộ lập lịch ở trạng thái tắt. |
| `OMNIROUTE_WARMUP_CRON` | `0 7 * * *` | `src/lib/warmupScheduler.ts` | Biểu thức cron năm trường cho lần tick warmup, được đánh giá theo múi giờ `America/Los_Angeles` (múi giờ reset của Anthropic) bất kể đồng hồ của máy chủ. |
| `OMNIROUTE_WARMUP_CONCURRENCY` | `3` | `src/lib/warmupScheduler.ts` | Số lượng kết nối được warm up song song trong mỗi lần tick. Bị giới hạn trong khoảng `1`-`10`; giá trị không phải số sẽ quay về `3`. |
| `OMNIROUTE_WARMUP_MODEL` | `claude-3-5-haiku-20241022` | `src/lib/warmupScheduler.ts` | Mô hình dùng cho yêu cầu warmup. Chỉ ghi đè nếu mô hình mặc định không khả dụng trên gói của bạn; hãy chọn mô hình rẻ nhất vẫn mở được cửa sổ. |
### Phiên VNC đăng nhập qua trình duyệt & bí danh Data-Dir
Chromium+VNC chạy trong container được dùng để thu thập thông tin xác thực đăng nhập qua trình duyệt một cách tương tác (`/api/vnc-session`), cùng với một bí danh `DATA_DIR` cũ. Tất cả đều tùy chọn — các giá trị mặc định của VNC nhắm đến image `omniroute-vnc-chromium:local` đi kèm sẵn và chỉ bị ghi đè khi dùng image container tùy chỉnh, cổng tùy chỉnh, hoặc tinh chỉnh vòng đời.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_VNC_IMAGE` | `omniroute-vnc-chromium:local` | `src/lib/vncSession/manifest.ts` | Tag image Docker cho container đăng nhập Chromium+VNC. Build `docker/vnc-browser/chromium` hoặc trỏ biến này tới một image tùy chỉnh. |
| `OMNIROUTE_DOCKER_BIN` | `docker` | `src/lib/vncSession/manifest.ts` | File nhị phân của container runtime dùng để khởi chạy container VNC (ví dụ: đặt thành `podman`). |
| `OMNIROUTE_VNC_CONTAINER_VNC_PORT` | `3000` | `src/lib/vncSession/manifest.ts` | Cổng VNC/noVNC được mở bên trong container. |
| `OMNIROUTE_VNC_CONTAINER_CDP_PORT` | `9223` | `src/lib/vncSession/manifest.ts` | Cổng Chrome DevTools Protocol bên trong container. |
| `OMNIROUTE_VNC_CONTAINER_PROFILE_DIR` | `/config` | `src/lib/vncSession/manifest.ts` | Đường dẫn thư mục profile Chromium bên trong container. |
| `OMNIROUTE_VNC_PROFILE_DIR` | `$HOME/.omniroute/browser-login-profiles` | `src/lib/vncSession/manifest.ts` | Thư mục trên máy chủ lưu các profile đăng nhập trình duyệt được duy trì. |
| `OMNIROUTE_VNC_IDLE_MS` | `600000` (10 phút) | `src/lib/vncSession/manifest.ts` | Thời gian chờ không hoạt động (ms) trước khi một phiên VNC không hoạt động bị thu hồi. |
| `OMNIROUTE_VNC_MAX_MS` | `1800000` (30 phút) | `src/lib/vncSession/manifest.ts` | Giới hạn cứng (ms) về thời gian tồn tại của một phiên VNC. |
| `OMNIROUTE_VNC_MAX_SESSIONS` | `4` | `src/lib/vncSession/manifest.ts` | Số lượng phiên VNC đồng thời tối đa. |
| `OMNIROUTE_VNC_READY_MS` | `45000` | `src/lib/vncSession/manifest.ts` | Thời gian chờ (ms) để trình duyệt trong container đạt trạng thái sẵn sàng CDP. |
| `OMNIROUTE_VNC_HARVEST_MS` | `20000` | `src/lib/vncSession/manifest.ts` | Thời gian chờ (ms) để thu thập phiên/cookie đã ghi lại sau khi đăng nhập hoàn tất. |
| `OMNIROUTE_VNC_CHROMIUM_ARGS` | `--remote-debugging-port=9222 --no-first-run --no-default-browser-check` | `src/lib/vncSession/manifest.ts` | Các cờ dòng lệnh bổ sung truyền cho Chromium trong container. |
| `OMNIROUTE_VNC_NETWORK` | `omniroute-vnc-browser-login` | `src/lib/vncSession/manifest.ts` | Mạng Docker chuyên dụng mà container đăng nhập VNC tham gia (#12571) thay vì bridge mặc định, để các container anh em không thể truy cập cổng bridge CDP của nó. |
| `VIBEPROXY_DATA_DIR` | _(chưa đặt)_ | `open-sse/services/notionThreadSessions.ts` | **Bí danh cũ** của `DATA_DIR`, chỉ được kiểm tra sau khi cả `DATA_DIR` và `OMNIROUTE_DATA_DIR` đều chưa được đặt. Xác định vị trí bộ nhớ đệm phiên web-thread của Notion (`/notion-web-thread-sessions.json`). |
---
## 26. Công cụ Test & E2E
Được sử dụng bởi `scripts/dev/run-next-playwright.mjs`, `scripts/dev/smoke-electron-packaged.mjs`,
`scripts/dev/run-ecosystem-tests.mjs`, và `scripts/build/uninstall.mjs`. Hãy để mọi
giá trị bên dưới ở trạng thái chưa đặt trong các bản triển khai production.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| -------------------------------------- | ------------------------------------ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_E2E_BOOTSTRAP_MODE` | `auth` | `scripts/dev/run-next-playwright.mjs` | Chế độ bootstrap E2E (`auth`, `fresh`, `reuse`) cho trình chạy Playwright. |
| `OMNIROUTE_E2E_PASSWORD` | dùng `INITIAL_PASSWORD` làm dự phòng | `scripts/dev/run-next-playwright.mjs` | Mật khẩu admin được chèn vào môi trường Playwright. |
| `OMNIROUTE_DISABLE_LOCAL_HEALTHCHECK` | `true` | `scripts/dev/run-next-playwright.mjs` | Tắt việc thăm dò healthcheck cục bộ trong các lần chạy Playwright. |
| `OMNIROUTE_DISABLE_TOKEN_HEALTHCHECK` | `true` | `scripts/dev/run-next-playwright.mjs` | Tắt vòng lặp healthcheck token OAuth trong quá trình kiểm thử. |
| `OMNIROUTE_HEALTHCHECK_SKIP_PROVIDERS` | _(chưa đặt)_ | `src/lib/tokenHealthCheck.ts` | Danh sách provider phân tách bằng dấu phẩy được loại trừ khỏi đợt quét làm mới token chủ động (ví dụ `codex,openai`). Giải pháp thay thế có chọn lọc thay cho việc tắt hoàn toàn healthcheck — các provider có TTL ngắn vẫn tiếp tục làm mới trong khi các provider cascade chỉ hoạt động theo kiểu phản ứng. |
| `OMNIROUTE_HIDE_HEALTHCHECK_LOGS` | `true` | `scripts/dev/run-next-playwright.mjs` | Làm im lặng các log healthcheck gây nhiễu trong stdout của Playwright. |
| `OMNIROUTE_PLAYWRIGHT_SKIP_BUILD` | `0` | `scripts/dev/run-next-playwright.mjs` | Bỏ qua bản build production Next.js trước khi Playwright khởi động (tối ưu hóa CI). |
| `OMNIROUTE_SKIP_UNINSTALL_HOOK` | `0` | `scripts/build/uninstall.mjs` | Bỏ qua hook gỡ cài đặt OmniRoute (được CI sử dụng để giữ nguyên `node_modules`). |
| `ECOSYSTEM_SERVER_WAIT_MS` | `180000` | `scripts/dev/run-ecosystem-tests.mjs` | Thời gian chờ (ms) để server đạt trạng thái healthy trước khi chạy các bài kiểm thử ecosystem/protocol. |
| `ELECTRON_SMOKE_URL` | `http://127.0.0.1:20128/login` | `scripts/dev/smoke-electron-packaged.mjs` | URL mà công cụ smoke Electron mong đợi ứng dụng đã đóng gói sẽ phục vụ. |
| `ELECTRON_SMOKE_TIMEOUT_MS` | `45000` | `scripts/dev/smoke-electron-packaged.mjs` | Tổng thời gian timeout (ms) trước khi công cụ smoke từ bỏ. |
| `ELECTRON_SMOKE_SETTLE_MS` | `2000` | `scripts/dev/smoke-electron-packaged.mjs` | Khoảng thời gian ổn định (ms) sau khi trang tải xong. |
| `ELECTRON_SMOKE_APP_EXECUTABLE` | _(tự động)_ | `scripts/dev/smoke-electron-packaged.mjs` | Đường dẫn tường minh đến tệp thực thi Electron đã đóng gói. |
| `ELECTRON_SMOKE_DATA_DIR` | _(thư mục tạm)_ | `scripts/dev/smoke-electron-packaged.mjs` | Thư mục dữ liệu cho lần chạy smoke Electron. |
| `ELECTRON_SMOKE_KEEP_DATA` | `0` | `scripts/dev/smoke-electron-packaged.mjs` | Đặt `1` để giữ lại thư mục dữ liệu smoke sau khi chạy. |
| `ELECTRON_SMOKE_STREAM_LOGS` | `0` | `scripts/dev/smoke-electron-packaged.mjs` | Đặt `1` để truyền trực tiếp log của Electron ra stdout trong quá trình chạy. |
| `ELECTRON_SMOKE_COLD_RESTART` | `0` | `scripts/dev/smoke-electron-packaged.mjs` | #7592: khởi chạy lại với cùng thư mục dữ liệu và xác nhận lần khởi chạy thứ hai chọn driver SQLite gốc. |
| `CLI_DEVIN_BIN` | _(tra cứu PATH)_ | `open-sse/executors/devin-cli.ts` | Ghi đè đường dẫn binary của Devin CLI. |
### Pipeline dịch tài liệu
Được sử dụng bởi `scripts/i18n/run-translation.mjs` (lệnh `npm run i18n:run`).
Cả sáu biến đều chưa được đặt theo mặc định — chỉ đặt chúng trong `.env` trên
những máy cần có khả năng chạy trình dịch tài liệu.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ---------------------------------------- | ------------ | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_TRANSLATION_API_URL` | _(chưa đặt)_ | `scripts/i18n/run-translation.mjs` | URL cơ sở tương thích OpenAI cho backend dịch thuật. |
| `OMNIROUTE_TRANSLATION_API_KEY` | _(chưa đặt)_ | `scripts/i18n/run-translation.mjs` | Bearer token cho backend dịch thuật (không bao giờ được ghi log). |
| `OMNIROUTE_TRANSLATION_MODEL` | _(chưa đặt)_ | `scripts/i18n/run-translation.mjs` | ID model, ví dụ `gpt-4o-mini` hoặc `cx/gpt-5.4-mini`. |
| `OMNIROUTE_TRANSLATION_FALLBACK_MODELS` | _(chưa đặt)_ | `scripts/i18n/lib/translate-backend.mjs` | Chuỗi model dự phòng tùy chọn phân tách bằng dấu phẩy, được thử theo thứ tự khi model chính thất bại (hết quota 429, 401/402, 5xx, timeout, lỗi mạng); một request không hợp lệ (400/413/422) sẽ không được thử lại ở model khác. |
| `OMNIROUTE_TRANSLATION_TIMEOUT_MS` | `60000` | `scripts/i18n/run-translation.mjs` | Thời gian chờ cho mỗi request, tính bằng mili giây. |
| `OMNIROUTE_TRANSLATION_REASONING_EFFORT` | _(chưa đặt)_ | `scripts/i18n/lib/translate-backend.mjs` | Tùy chọn điều khiển reasoning, được gửi nguyên trạng đến backend khi được đặt. |
| `OMNIROUTE_TRANSLATION_CONCURRENCY` | `4` | `scripts/i18n/run-translation.mjs` | Số request dịch song song khi chạy trên nhiều tệp / locale. |
---
## 27. Nguồn cấp dữ liệu Radar (Tự lưu trữ)
Tiện ích bổ sung tùy chọn được kiểm soát bởi cờ tính năng RADAR_ENABLED (mặc định tắt — đây là cờ tính năng được bật/tắt thông qua Settings/DB, không phải biến môi trường; xem
[docs/frameworks/RADAR.md](../frameworks/RADAR.md#flag-radar_enabled-default-off)).
Bốn biến đầu tiên bên dưới là các giá trị ghi đè tùy chọn dành cho nguồn cấp dữ liệu tự lưu trữ hoặc phân nhánh và các luồng khóa người ủng hộ. Biến thứ năm, `RADAR_ADMIN_URL`, là một liên kết riêng biệt không có giá trị mặc định đến bảng điều hành riêng tư của chủ sở hữu. Xem [docs/frameworks/RADAR.md](../frameworks/RADAR.md) để biết tài liệu đầy đủ về mô-đun và
[trình tự kích hoạt đầu cuối cùng quy trình thiết lập có hướng dẫn](../frameworks/RADAR.md#end-to-end-activation-and-guided-setup).
Trình đọc thông báo Home/Changelog chung không được cấu hình bằng biến môi trường và không phụ thuộc vào cờ tính năng RADAR_ENABLED. Trình đọc này chỉ đọc bằng GET từ URL `news.json` của kho lưu trữ công khai được khai báo trong `src/shared/utils/releaseNotes.ts`; các ID thông báo đã bỏ qua vẫn được lưu trong bộ nhớ cục bộ của trình duyệt.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ----------------------------- | -------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `RADAR_FEED_URL` | `https://radar.omniroute.online` | `src/lib/radar/{sync,referralsSync,offersSync,intelSync}.ts` | URL cơ sở dùng chung cho các nguồn cấp danh mục, giới thiệu, ưu đãi dành cho người ủng hộ và Intel được ký riêng biệt. Ghi đè để trỏ đến một dịch vụ tự lưu trữ hoặc phân nhánh. |
| `RADAR_FEED_PUBKEY` | _(khóa mặc định được ghim)_ | `src/lib/radar/pinnedKeys.ts` | Khóa công khai Ed25519 (SPKI DER mã hóa base64 hoặc PEM) dùng để xác minh chữ ký nguồn cấp từ một nguồn cấp tùy chỉnh. |
| `RADAR_CONTRIBUTOR_CLAIM_URL` | `https://radar.omniroute.online/auth/github` | `src/lib/radar/links.ts` | URL được mở bởi nút "Tôi là người đóng góp" trên bảng điều khiển (luồng nhận khóa người ủng hộ qua GitHub OAuth). |
| `RADAR_SUPPORTER_PLANS_URL` | `https://radar.omniroute.online/planos` | `src/lib/radar/links.ts` | URL được mở bởi nút "Ủng hộ dự án" trên bảng điều khiển (trang thanh toán/gói dịch vụ). |
| `RADAR_ADMIN_URL` | _(chưa đặt)_ | `src/lib/radar/links.ts` | Liên kết đến bảng điều hành riêng tư chỉ dành cho chủ sở hữu. HTTPS là bắt buộc, ngoại trừ trường hợp chuyển tiếp SSH loopback qua HTTP; giá trị chưa đặt hoặc không hợp lệ sẽ không tạo mục điều hướng. |
---
## Kiểm tra: Các biến đã bị loại bỏ / không còn sử dụng
Các biến sau từng xuất hiện trong các phiên bản trước của `.env.example` nhưng **không có tham chiếu thời gian chạy nào** trong cơ sở mã hiện tại. Chúng đã bị loại bỏ:
| Biến | Lý do |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `STORAGE_DRIVER=sqlite` | Không bao giờ được bất kỳ tệp nguồn nào đọc. SQLite là trình điều khiển duy nhất được hỗ trợ — không cần lựa chọn. |
| `INSTANCE_NAME=omniroute` | Có trong tài liệu/mẫu env cũ nhưng không được sử dụng khi chạy. Có thể quay lại trong một tính năng đa phiên bản trong tương lai. |
| `SQLITE_MAX_SIZE_MB=2048` | Không được tham chiếu trong mã nguồn. Kích thước cơ sở dữ liệu không bị giới hạn một cách nhân tạo. |
| `SQLITE_CLEAN_LEGACY_FILES=true` | Không được tham chiếu trong mã nguồn. Chức năng dọn dẹp cũ có thể đã bị loại bỏ. |
| `CLI_ROO_BIN` | Không được đăng ký trong `src/shared/services/cliRuntime.ts`. |
| `CLI_KIMI_CODING_BIN` | Không được đăng ký trong `src/shared/services/cliRuntime.ts` (Kimi Coding sử dụng OAuth, không phải tệp nhị phân CLI). |
| `IFLOW_OAUTH_CLIENT_ID` / `IFLOW_OAUTH_CLIENT_SECRET` | Không được tham chiếu ở bất kỳ đâu trong mã nguồn. |
| `CEREBRAS_API_KEY` / `COHERE_API_KEY` / `FIREWORKS_API_KEY` / `GROQ_API_KEY` / `MISTRAL_API_KEY` / `NEBIUS_API_KEY` / `PERPLEXITY_API_KEY` / `TOGETHER_API_KEY` / `XAI_API_KEY` | Đã bị loại bỏ trong v3.8.0. Runtime không còn đọc các biến env này — thông tin xác thực đến từ Dashboard / `data/provider-credentials.json` / DB được mã hóa. |
| `CURSOR_PROTOBUF_DEBUG` | Đã bị loại bỏ trong v3.8.0. Trình thực thi Cursor sử dụng `CURSOR_DEBUG` / `CURSOR_STREAM_DEBUG` (xem §22). |
| `CLI_COMPAT_KIRO` | Đã bị loại bỏ trong v3.8.0. Kiro nằm trong `CLI_COMPAT_OMITTED_PROVIDER_IDS` — tùy chọn bật/tắt của nó không có tác dụng. |
| `QIANFAN_API_KEY` | Đã bị loại bỏ cùng với các stub khóa API nhà cung cấp không được sử dụng khác trong v3.8.0. |
### Hiệu chỉnh giá trị mặc định
| Biến | Giá trị `.env.example` cũ | Giá trị mặc định thực tế trong mã | Đã sửa |
| ------------------------- | ------------------------- | --------------------------------- | ----------------------------------------------------------- |
| `APP_LOG_RETENTION_DAYS` | `90` | `7` | ✅ Đã loại bỏ giá trị gây hiểu nhầm; ghi rõ `7` là mặc định |
| `CALL_LOG_RETENTION_DAYS` | `90` | `7` | ✅ Đã loại bỏ giá trị gây hiểu nhầm; ghi rõ `7` là mặc định |
### Tạo lại cấu hình OpenCode (công cụ chuyên biệt)
Được `scripts/ad-hoc/regen-opencode-config.ts` sử dụng để tạo lại một tệp `opencode.json`
với các giá trị `limit.context` và `limit.output` chính xác được lấy từ phiên bản
OmniRoute đang chạy. Không có mục nào trong số này là bắt buộc đối với hoạt động thông thường — script
chỉ là công cụ dành cho nhà phát triển.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------ | ------------------------ | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_URL` | `http://localhost:20128` | `scripts/ad-hoc/regen-opencode-config.ts` | URL cơ sở của phiên bản OmniRoute cần truy vấn cho `/v1/models`. |
| `OMNIROUTE_KEY` | _(chưa đặt)_ | `scripts/ad-hoc/regen-opencode-config.ts` | Khóa API để xác thực với điểm cuối OmniRoute `/v1/models`. Dùng `OPENCODE_API_KEY` làm phương án dự phòng khi chưa được đặt. |
| `OPENCODE_API_KEY` | _(chưa đặt)_ | `scripts/ad-hoc/regen-opencode-config.ts` | Khóa API kiểu OpenCode (`sk-...`) được ghi vào `opencode.json` đã tạo lại. Dùng `OMNIROUTE_KEY` làm phương án dự phòng khi chưa được đặt. |
### Bộ công cụ đánh giá ngoại tuyến cho tính năng nén (công cụ đặc biệt)
Được CLI đánh giá nén ngoại tuyến `scripts/compression-eval/index.ts` sử dụng.
Không bắt buộc đối với hoạt động thông thường — chỉ dành cho công cụ phát triển.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ---------------------------- | ----------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_EVAL_CREDENTIALS` | `{}` (rỗng) | `scripts/compression-eval/index.ts` | Thông tin xác thực JSON do người vận hành cung cấp cho nhà cung cấp được CLI đánh giá nén ngoại tuyến sử dụng (được phân tích bằng `JSON.parse`). Để chưa đặt nếu muốn chạy thử. |
### Phiên trình duyệt VNC
Được `src/lib/vncSession/manifest.ts` sử dụng để cấu hình các phiên Chromium không giao diện dựa trên Docker cho những nhà cung cấp tự động hóa trình duyệt. Tất cả đều là tùy chọn — các giá trị mặc định được hiển thị bên dưới.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------- | ------------------------------ | ------------------------------------------- | ---------------------------------------------------------------------------------- |
| `OMNIROUTE_DOCKER_BIN` | `docker` | `src/lib/vncSession/manifest.ts` | Đường dẫn đến tệp nhị phân Docker dùng để khởi chạy các container VNC. |
| `OMNIROUTE_VNC_IMAGE` | `omniroute-vnc-chromium:local` | `src/lib/vncSession/manifest.ts` | Image Docker cho container VNC Chromium. |
| `OMNIROUTE_VNC_CHROMIUM_ARGS` | _(các cờ tích hợp sẵn)_ | `src/lib/vncSession/manifest.ts` | Các đối số CLI Chromium bổ sung được truyền cho trình duyệt bên trong container. |
| `OMNIROUTE_VNC_CONTAINER_VNC_PORT` | `3000` | `src/lib/vncSession/manifest.ts` | Cổng VNC bên trong container. |
| `OMNIROUTE_VNC_CONTAINER_CDP_PORT` | `9223` | `src/lib/vncSession/manifest.ts` | Cổng Chrome DevTools Protocol bên trong container. |
| `OMNIROUTE_VNC_CONTAINER_PROFILE_DIR` | `/config` | `src/lib/vncSession/manifest.ts` | Thư mục hồ sơ bên trong container. |
| `OMNIROUTE_VNC_PROFILE_DIR` | _(chưa đặt)_ | `src/lib/vncSession/manifest.ts` | Thư mục phía máy chủ cho các hồ sơ trình duyệt lâu dài. |
| `OMNIROUTE_VNC_IDLE_MS` | `600000` | `src/lib/vncSession/manifest.ts` | Thời gian chờ khi không hoạt động (ms) trước khi một phiên VNC được thu hồi. |
| `OMNIROUTE_VNC_MAX_MS` | `1800000` | `src/lib/vncSession/manifest.ts` | Thời lượng phiên tối đa (ms). |
| `OMNIROUTE_VNC_MAX_SESSIONS` | `4` | `src/lib/vncSession/manifest.ts` | Số phiên VNC đồng thời tối đa. |
| `OMNIROUTE_VNC_READY_MS` | `45000` | `src/lib/vncSession/manifest.ts` | Thời gian chờ trình duyệt sẵn sàng (ms). |
| `OMNIROUTE_VNC_HARVEST_MS` | `20000` | `src/lib/vncSession/manifest.ts` | Thời gian chờ thu hồi/dọn dẹp (ms). |
| `OMNIROUTE_VNC_NETWORK` | `omniroute-vnc-browser-login` | `src/lib/vncSession/manifest.ts` | Mạng Docker chuyên dụng mà container tham gia (#12571), tách khỏi bridge mặc định. |
| `VIBEPROXY_DATA_DIR` | _(chưa đặt)_ | `open-sse/services/notionThreadSessions.ts` | Thư mục dùng để lưu trữ lâu dài các phiên luồng Notion. |
### Xác thực dịch vụ nội bộ
| Biến | Mặc định | Mô tả |
| --------------------------------------- | -------- | -------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_INTERNAL_SERVICE_TOKEN` | – | Token nội tuyến dùng để xác thực giữa các dịch vụ thuộc tầng quản lý. |
| `OMNIROUTE_INTERNAL_SERVICE_TOKEN_FILE` | – | Đường dẫn đến tệp chứa token dịch vụ nội bộ (được ưu tiên trong container; ghi đè biến nội tuyến). |
### Thống kê nhà cung cấp OpenRouter
| Biến | Mặc định | Mô tả |
| ----------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `OPENROUTER_PROVIDER_STATS_ENABLED` | `true` | Đặt thành `false` để bỏ qua việc truy xuất số liệu thống kê theo từng nhà cung cấp OpenRouter nhằm bổ sung thông tin cho danh mục. |
| `OPENROUTER_PROVIDER_STATS_TTL_MS` | `3600000` | TTL bộ nhớ đệm (ms) cho số liệu thống kê nhà cung cấp OpenRouter đã truy xuất. |
### Liên kết Redis nhúng
| Biến | Mặc định | Mô tả |
| --------------------------- | ----------- | ------------------------------------------------------------------------ |
| `REDIS_BIND_HOST` | `127.0.0.1` | Địa chỉ liên kết cho dịch vụ Redis nhúng. |
| `REDIS_PORT` | `6379` | Cổng cho dịch vụ Redis nhúng. |
| `OMNIROUTE_REDIS_BIND_HOST` | – | Giá trị ghi đè trong phạm vi OmniRoute cho địa chỉ liên kết Redis nhúng. |
---
## 24. Các bổ sung trong bản phát hành v3.8.50
Các cài đặt này được giới thiệu sau bản snapshot hợp đồng môi trường (environment-contract) trước đó.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `OMNIROUTE_CHAT_ADMISSION_QUEUE_MS` | `2000` | `src/shared/middleware/chatBodyAdmission.ts` | Thời gian chờ tối đa để có một slot admission chat nặng trước khi trả về lỗi `503` có thể thử lại; một khoảng chờ ngắn có giới hạn sẽ tuần tự hóa các đợt burst của agent thay vì trả `503` ngay lập tức. `0` khôi phục hành vi từ chối ngay lập tức. |
| `OMNIROUTE_CHAT_ADMISSION_MAX_QUEUED_BYTES` | `4194304` (4 MB) | `src/shared/middleware/chatBodyAdmission.ts` | Ngân sách byte trong hàng đợi cho lượt chờ admission: giới hạn tổng số byte body được đệm và giữ trên toàn tiến trình để việc chờ không thể khuếch đại heap (#4380). Các lượt chờ vượt ngân sách sẽ nhận ngay lỗi `503` có thể thử lại. |
| `OMNIROUTE_CHAT_VIRTUAL_TTL_MS` | `60000` (60 s) | `src/shared/middleware/chatBodyAdmission.ts` | Đã deprecated, không còn tác dụng (no-op) kể từ #10110: các lane admission theo phiên đã bị loại bỏ, thay bằng một ngân sách chung cho toàn tiến trình. Vẫn được chấp nhận để tương thích cấu hình; bị bỏ qua. |
| `OMNIROUTE_CHAT_VIRTUAL_MAX_SESSIONS` | `64` | `src/shared/middleware/chatBodyAdmission.ts` | Đã deprecated, không còn tác dụng (no-op) kể từ #10110: các lane admission theo phiên đã bị loại bỏ, thay bằng một ngân sách chung cho toàn tiến trình. Vẫn được chấp nhận để tương thích cấu hình; bị bỏ qua. |
| `OMNIROUTE_CHAT_VIRTUAL_LANES` | `0` (tắt) | `open-sse/services/admission/runtime.ts` | Các lane admission ảo thích ứng lúc runtime (#9654): công tắc chính cho cổng thích ứng theo tenant (hệ thống 2). Khác với các biến lane theo kết nối đã deprecated ở trên (TTL_MS / MAX_SESSIONS, no-op kể từ #10110). Cờ tính năng trên Dashboard trùng tên; biến môi trường được ưu tiên hơn thiết lập ghi đè trên Dashboard; yêu cầu khởi động lại. |
| `OMNIROUTE_RUNNOW_TIMEOUT_MS` | `30000` | `src/app/api/jobs/[id]/run-now/route.ts` | Giới hạn thời gian một lời gọi run-now chờ một job đang chạy trước khi bắt đầu lượt chạy trong hàng đợi. |
| `ADOBE_FIREFLY_BROWSER_REFRESH` | bật | `open-sse/services/adobeFireflySession.ts` | Giữ trạng thái IMS và browser-risk luôn mới thông qua các phiên Chrome CDP theo phạm vi tài khoản; đặt `0` để tắt. |
| `ADOBE_FIREFLY_SESSION_DISK` | bật | `open-sse/services/adobeFireflySession.ts` | Lưu trữ các phiên Adobe đã khôi phục trong `DATA_DIR`; đặt `0` để chỉ giữ trạng thái trong bộ nhớ. |
| `ADOBE_FIREFLY_MIN_SUBMIT_GAP_MS` | `12000` | `open-sse/services/adobeFireflySession.ts` | Khoảng cách tối thiểu giữa các lần gửi yêu cầu generate của Adobe Firefly. |
| `ADOBE_FIREFLY_BATCH_EXTRA_GAP_MS` | `15000` | `open-sse/services/adobeFireflySession.ts` | Khoảng thời gian nghỉ bổ sung sau mỗi lần gửi thành công thứ ba tới Adobe. |
| `ADOBE_FIREFLY_CHROME_HEADLESS` | `0` | `open-sse/services/adobeFireflyBrowserLogin.ts` | Chế độ true-headless chỉ dành cho debug; Adobe colligo thường từ chối phiên risk được tạo ra từ chế độ này. |
| `CHROME_PATH` | tự động phát hiện | `open-sse/executors/cloudflare-playground.ts`, `open-sse/executors/chatgpt-web-codex.ts` | Đường dẫn tuyệt đối tùy chọn tới file thực thi Chrome, dùng bởi các executor điều khiển trình duyệt khi tính năng tự động phát hiện theo nền tảng không đủ. |
| `TELEGRAM_BOT_TOKEN` | _(chưa đặt)_ | `src/lib/telegram/config.ts` | Token BotFather dùng để bật webhook đầu vào và ký `initData` của Mini App. |
| `TELEGRAM_WEBHOOK_SECRET` | _(chưa đặt)_ | `src/lib/telegram/config.ts` | Secret dùng chung được đăng ký qua `setWebhook` và được xác minh với header `X-Telegram-Bot-Api-Secret-Token` trong mỗi lần gửi webhook. Bắt buộc cho đường dẫn webhook; nếu không đặt, các lần gửi webhook sẽ bị từ chối với mã 503. |
| `TELEGRAM_DEFAULT_MODEL` | `auto/chat` | `src/lib/telegram/chatProxy.ts` | Model dùng cho các phản hồi chat Telegram. |
| `TELEGRAM_BOT_API_BASE` | `https://api.telegram.org` | `src/lib/telegram/config.ts` | Ghi đè URL gốc của Bot API để dùng proxy hoặc máy chủ Bot API tự lưu trữ. |
| `TELEGRAM_WEBHOOK_TIMEOUT_MS` | `60000` | `src/lib/telegram/config.ts` | Thời gian chờ (tính bằng mili giây) cho các lời gọi Bot API đi ra. |
| `OMNIROUTE_OPTIONAL_PACK_TAR` | `1` (bật) | `scripts/build/optionalPackStaging.mjs` | Đặt `0` để bỏ qua việc tạo các tarball `.tar.gz` khi staging các gói ML/trình duyệt tùy chọn cho cây Electron standalone (thư mục gói và `optional-packs.index.json` vẫn được tạo). Được dùng bởi workflow phát hành desktop để giảm dung lượng artifact tải lên. |
| `GROK_SUBSCRIPTION_IMAGES_ENABLED` | `false` | `open-sse/config/imageRegistry.ts` | Bật đăng ký các route ảnh theo gói đăng ký xAI; tắt theo mặc định để đường dẫn ảnh qua API key không thay đổi. |
| `OMNIROUTE_API_KEY_COOLDOWN_MS` | `60000` | `open-sse/services/apiKeyRotator.ts` | Thời gian cooldown theo từng key (tính bằng mili giây) khi phản hồi `429` không có gợi ý `Retry-After` khả dụng. |
| `OMNIROUTE_ESTIMATOR_CALIBRATION` | bật | `open-sse/services/estimatorCalibration.ts` | Đặt thành `off`, `0` hoặc `false` để tắt việc ghi và áp dụng hiệu chuẩn estimator trong bộ nhớ. |
| `NEXT_MANUAL_SIG_HANDLE` | _(nội bộ)_ | `scripts/dev/standalone-server-ws.mjs` | Ghi đè trình xử lý tín hiệu nội bộ của standalone server; thường do launcher đặt và xóa thay vì do người vận hành cấu hình. |
### ChatGPT Web (Codex)
Các giá trị mặc định toàn cục cho trình duyệt headless và tunnel công cụ đi ra. Các giá trị connection được đặt trong Dashboard sẽ được ưu tiên.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| --------------------------------------- | ------------------------------ | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CHATGPT_WEB_CODEX_CHROME_PATH` | _(tự động phát hiện)_ | `open-sse/executors/chatgpt-web-codex.ts` | Đường dẫn Chrome/Chromium rõ ràng cho hoạt động npm, systemd và PM2. |
| `CHROME_PATH` | _(tự động phát hiện)_ | `open-sse/executors/chatgpt-web-codex.ts` | Fallback chung cho đường dẫn Chrome/Chromium rõ ràng. |
| `CHATGPT_WEB_CODEX_CDP_URL` | _(chưa đặt)_ | `open-sse/executors/chatgpt-web-codex.ts` | Endpoint CDP nội bộ; Docker sử dụng sidecar trên cổng `9223`. |
| `CHATGPT_WEB_CODEX_USE_CDP_PROFILE` | _(chưa đặt — tắt)_ | `open-sse/vendor/codex-chatgpt-web/persistent-cdp-context.ts` | Đặt thành `1` (với endpoint CDP đã được cấu hình) để tái sử dụng trang ChatGPT hiện có của hồ sơ trình duyệt đã đăng nhập, được quản lý bên ngoài, thay vì một ngữ cảnh biệt lập cho mỗi lượt; đồng thời giới hạn số tab ChatGPT đồng thời ở mức 1. Tắt theo mặc định. Xem [hồ sơ CDP bền vững](../guides/CHATGPT-WEB-PERSISTENT-CDP.md). |
| `CDP_PROXY_TOKEN` | _(chưa đặt)_ | `docker/chatgpt-web-codex-browser/cdp-proxy.mjs` | Nếu được đặt, mọi yêu cầu gửi đến sidecar CDP-Proxy phải kèm theo giá trị này trong header `X-Omni-Cdp-Token` (#13679). Nếu không có giá trị, proxy sẽ chuyển tiếp mà không xác thực — khi đó chỉ có sự cô lập mạng của mạng Compose `chatgpt-web-codex-net` bảo vệ. Tạo bằng `openssl rand -hex 32`. |
| `CHATGPT_WEB_CODEX_TUNNEL_ID` | _(chưa đặt)_ | `open-sse/executors/chatgpt-web-codex.ts` | ID tunnel OpenAI toàn cục cho các vòng công cụ Codex cục bộ. |
| `CHATGPT_WEB_CODEX_RUNTIME_KEY` | _(chưa đặt)_ | `open-sse/executors/chatgpt-web-codex.ts` | Runtime key của tunnel toàn cục; không bao giờ xuất ra log. |
| `CHATGPT_WEB_CODEX_CONNECTOR_NAME` | `OmniRoute Codex v2` | `open-sse/executors/chatgpt-web-codex.ts` | Tên chính xác của ChatGPT Custom Connector mới được tạo cho cầu nối MCP. |
| `CODEX_CHATGPT_WEB_HOME` | `/chatgpt-web-codex` | `open-sse/vendor/codex-chatgpt-web/config.ts` | Thư mục chuyên dụng cho trạng thái trình duyệt, broker và tunnel. |
| `CODEX_CHATGPT_WEB_BROWSER_DIAGNOSTICS` | `0` | `open-sse/vendor/codex-chatgpt-web/adapters/chatgpt-web/browser-worker.ts` | Khi đặt thành `1`, hình ảnh chẩn đoán trình duyệt sẽ được ghi lại tại mỗi checkpoint. |
| `CODEX_CHATGPT_WEB_LAUNCHER` | _(chưa đặt)_ | `open-sse/vendor/codex-chatgpt-web/config.ts` | Đường dẫn tuyệt đối tùy chọn tới binary launcher cố định. |
| `CODEX_CHATGPT_WEB_BUN` | _(tự động phát hiện)_ | `open-sse/vendor/codex-chatgpt-web/config.ts` | Đường dẫn tuyệt đối tùy chọn tới binary runtime Bun. |
| `CODEX_WEB_GPT_BUN` | _(chưa đặt)_ | `open-sse/vendor/codex-chatgpt-web/config.ts` | Fallback cũ (legacy) cho `CODEX_CHATGPT_WEB_BUN`; các thiết lập mới sử dụng tên chuẩn. |
---
## Cầu nối OmniConductor
Trình tiêu thụ SSE tồn tại lâu dài, đồng bộ (mirror) các tác vụ của hub OmniConductor vào TaskManager A2A cục bộ (`src/lib/conductor/`). Tùy chọn bật — cầu nối chỉ khởi động khi `CONDUCTOR_HUB_URL` được thiết lập. Chỉ chạy phía máy chủ: token của hub không bao giờ được lọt đến trình duyệt.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ------------------------------ | ----------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `CONDUCTOR_HUB_URL` | _(trống)_ | `src/lib/conductor/boot.ts` | URL gốc của hub OmniConductor (ví dụ `http://127.0.0.1:7910`). Không thiết lập = cầu nối bị tắt. |
| `CONDUCTOR_HUB_TOKEN` | _(trống)_ | `src/lib/conductor/boot.ts` | Thông tin xác thực của hub cho luồng SSE — tạo một peer loại `spokesperson` trên hub (`POST /v1/peers`, quyền admin). |
| `CONDUCTOR_ORCHESTRATOR_TOKEN` | _(trống)_ | `src/lib/conductor/hubProxy.ts` | Thông tin xác thực cho việc ủy quyền tác vụ A2A→hub đến (`POST /v1/tasks`); dùng `CONDUCTOR_HUB_TOKEN` làm dự phòng khi chưa thiết lập. |
| `CONDUCTOR_SPOKESPERSON_URL` | `http://127.0.0.1:7920` | `src/lib/conductor/faroProxy.ts` | URL gốc của dịch vụ spokesperson (Faro) đứng sau proxy chat của dashboard (`/api/conductor/ask`). |
### Lập lịch theo hạn ngạch (quota)
Được sử dụng bởi `open-sse/services/combo.ts` và `src/lib/quota/quotaScheduler.ts` để kiểm tra ngân sách token trước khi gửi yêu cầu. Tùy chọn bật — hành vi định tuyến mặc định không thay đổi khi chưa thiết lập.
| Biến | Mặc định | Tệp nguồn | Mô tả |
| ---------------------------------- | -------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_QUOTA_AWARE_ROUTING` | `0` | `open-sse/services/combo.ts` | Khi đặt là `1`, bỏ qua các kết nối có ngân sách token theo cửa sổ (`rateLimitOverrides.tpm`, bảng `provider_quota_state`) không đủ chi trả chi phí ước tính của yêu cầu trước khi điều phối. Fail-open khi chưa cấu hình ngân sách. |
| `OMNIROUTE_ESTIMATOR_CALIBRATION` | _(bật)_ | `open-sse/services/estimatorCalibration.ts` | Hiệu chuẩn phản hồi cho bộ ước lượng token của context-guard (#14931): EMA theo từng (provider, model, có công cụ) của `usage.prompt_tokens` / giá trị ước lượng, giới hạn trong khoảng 0.15–2.0, chỉ lưu trong bộ nhớ. `off`, `0` hoặc `false` sẽ tắt việc ghi nhận và áp dụng. |
| `GROK_SUBSCRIPTION_IMAGES_ENABLED` | `false` | `open-sse/config/imageRegistry.ts` | Đăng ký các route hình ảnh `xai-oauth` (`xao`) và `grok-cli`. Cờ tính năng trên dashboard mang cùng tên; giá trị ghi đè trong DB sẽ được ưu tiên hơn giá trị này. |