docs(i18n): translate 25 core documentation files to Indonesian (#3348)

Integrated into release/v3.8.14 — Indonesian i18n docs.
This commit is contained in:
Krisna Santosa
2026-06-07 11:56:25 +07:00
committed by GitHub
parent 1306e7b3f1
commit 559b97c0e8
25 changed files with 4109 additions and 4152 deletions

View File

@@ -1,132 +1,89 @@
# Contributor Covenant Code of Conduct (Bahasa Indonesia)
# Kode Etik Contributor Covenant (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../CODE_OF_CONDUCT.md) · 🇸🇦 [ar](../ar/CODE_OF_CONDUCT.md) · 🇧🇬 [bg](../bg/CODE_OF_CONDUCT.md) · 🇧🇩 [bn](../bn/CODE_OF_CONDUCT.md) · 🇨🇿 [cs](../cs/CODE_OF_CONDUCT.md) · 🇩🇰 [da](../da/CODE_OF_CONDUCT.md) · 🇩🇪 [de](../de/CODE_OF_CONDUCT.md) · 🇪🇸 [es](../es/CODE_OF_CONDUCT.md) · 🇮🇷 [fa](../fa/CODE_OF_CONDUCT.md) · 🇫🇮 [fi](../fi/CODE_OF_CONDUCT.md) · 🇫🇷 [fr](../fr/CODE_OF_CONDUCT.md) · 🇮🇳 [gu](../gu/CODE_OF_CONDUCT.md) · 🇮🇱 [he](../he/CODE_OF_CONDUCT.md) · 🇮🇳 [hi](../hi/CODE_OF_CONDUCT.md) · 🇭🇺 [hu](../hu/CODE_OF_CONDUCT.md) · 🇮🇩 [id](../id/CODE_OF_CONDUCT.md) · 🇮🇹 [it](../it/CODE_OF_CONDUCT.md) · 🇯🇵 [ja](../ja/CODE_OF_CONDUCT.md) · 🇰🇷 [ko](../ko/CODE_OF_CONDUCT.md) · 🇮🇳 [mr](../mr/CODE_OF_CONDUCT.md) · 🇲🇾 [ms](../ms/CODE_OF_CONDUCT.md) · 🇳🇱 [nl](../nl/CODE_OF_CONDUCT.md) · 🇳🇴 [no](../no/CODE_OF_CONDUCT.md) · 🇵🇭 [phi](../phi/CODE_OF_CONDUCT.md) · 🇵🇱 [pl](../pl/CODE_OF_CONDUCT.md) · 🇵🇹 [pt](../pt/CODE_OF_CONDUCT.md) · 🇧🇷 [pt-BR](../pt-BR/CODE_OF_CONDUCT.md) · 🇷🇴 [ro](../ro/CODE_OF_CONDUCT.md) · 🇷🇺 [ru](../ru/CODE_OF_CONDUCT.md) · 🇸🇰 [sk](../sk/CODE_OF_CONDUCT.md) · 🇸🇪 [sv](../sv/CODE_OF_CONDUCT.md) · 🇰🇪 [sw](../sw/CODE_OF_CONDUCT.md) · 🇮🇳 [ta](../ta/CODE_OF_CONDUCT.md) · 🇮🇳 [te](../te/CODE_OF_CONDUCT.md) · 🇹🇭 [th](../th/CODE_OF_CONDUCT.md) · 🇹🇷 [tr](../tr/CODE_OF_CONDUCT.md) · 🇺🇦 [uk-UA](../uk-UA/CODE_OF_CONDUCT.md) · 🇵🇰 [ur](../ur/CODE_OF_CONDUCT.md) · 🇻🇳 [vi](../vi/CODE_OF_CONDUCT.md) · 🇨🇳 [zh-CN](../zh-CN/CODE_OF_CONDUCT.md)
---
## Our Pledge
## Ikrar Kami
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
Kami sebagai anggota, kontributor, dan pemimpin berjanji untuk menjadikan partisipasi dalam komunitas kami sebagai pengalaman yang bebas dari pelecehan bagi semua orang, tanpa memandang usia, ukuran tubuh, disabilitas yang terlihat maupun tidak terlihat, etnisitas, karakteristik seks, identitas dan ekspresi gender, tingkat pengalaman, pendidikan, status sosial-ekonomi, kebangsaan, penampilan pribadi, ras, agama, atau identitas dan orientasi seksual.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
Kami berjanji untuk bertindak dan berinteraksi dengan cara yang berkontribusi pada komunitas yang terbuka, ramah, beragam, inklusif, dan sehat.
## Our Standards
## Standar Kami
Examples of behavior that contributes to a positive environment for our
community include:
Contoh perilaku yang berkontribusi pada lingkungan yang positif bagi komunitas kami meliputi:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
- Menunjukkan empati dan kebaikan terhadap orang lain
- Menghormati pendapat, sudut pandang, dan pengalaman yang berbeda
- Memberikan dan menerima umpan balik yang konstruktif dengan lapang dada
- Menerima tanggung jawab dan meminta maaf kepada mereka yang terdampak oleh kesalahan kita, serta belajar dari pengalaman tersebut
- Berfokus pada apa yang terbaik bukan hanya bagi kita sebagai individu, tetapi bagi komunitas secara keseluruhan
Examples of unacceptable behavior include:
Contoh perilaku yang tidak dapat diterima meliputi:
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
- Penggunaan bahasa atau citra yang bersifat seksual, serta perhatian atau rayuan seksual dalam bentuk apa pun
- Trolling, komentar menghina atau merendahkan, serta serangan pribadi atau politis
- Pelecehan di ranah publik maupun privat
- Mempublikasikan informasi pribadi orang lain, seperti alamat fisik atau email, tanpa izin eksplisit mereka
- Perilaku lain yang secara wajar dapat dianggap tidak pantas dalam lingkungan profesional
## Enforcement Responsibilities
## Tanggung Jawab Penegakan
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Pemimpin komunitas bertanggung jawab untuk mengklarifikasi dan menegakkan standar perilaku yang dapat diterima, serta akan mengambil tindakan korektif yang tepat dan adil sebagai respons terhadap perilaku apa pun yang mereka anggap tidak pantas, mengancam, menyinggung, atau merugikan.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
Pemimpin komunitas memiliki hak dan tanggung jawab untuk menghapus, mengedit, atau menolak komentar, commit, kode, suntingan wiki, isu, dan kontribusi lain yang tidak sesuai dengan Kode Etik ini, serta akan mengomunikasikan alasan keputusan moderasi bila diperlukan.
## Scope
## Cakupan
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
Kode Etik ini berlaku di semua ruang komunitas, dan juga berlaku ketika seseorang secara resmi mewakili komunitas di ruang publik. Contoh perwakilan komunitas kita meliputi penggunaan alamat email resmi, posting melalui akun media sosial resmi, atau bertindak sebagai perwakilan yang ditunjuk pada acara daring maupun luring.
## Enforcement
## Penegakan
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
Kasus perilaku kasar, melecehkan, atau tidak dapat diterima lainnya dapat dilaporkan kepada pemimpin komunitas yang bertanggung jawab atas penegakan di
.
All complaints will be reviewed and investigated promptly and fairly.
Semua pengaduan akan ditinjau dan diselidiki dengan segera dan adil.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
Semua pemimpin komunitas berkewajiban untuk menghormati privasi dan keamanan pelapor dari setiap insiden.
## Enforcement Guidelines
## Pedoman Penegakan
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
Pemimpin komunitas akan mengikuti Pedoman Dampak Komunitas ini dalam menentukan konsekuensi atas setiap tindakan yang mereka anggap melanggar Kode Etik ini:
### 1. Correction
### 1. Koreksi
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Dampak Komunitas**: Penggunaan bahasa yang tidak pantas atau perilaku lain yang dianggap tidak profesional atau tidak diinginkan dalam komunitas.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
**Konsekuensi**: Peringatan tertulis secara privat dari pemimpin komunitas, yang memberikan kejelasan mengenai sifat pelanggaran dan penjelasan mengapa perilaku tersebut tidak pantas. Permohonan maaf secara publik mungkin diminta.
### 2. Warning
### 2. Peringatan
**Community Impact**: A violation through a single incident or series
of actions.
**Dampak Komunitas**: Pelanggaran melalui satu insiden atau serangkaian tindakan.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
**Konsekuensi**: Peringatan dengan konsekuensi apabila perilaku tersebut berlanjut. Tidak ada interaksi dengan pihak-pihak yang terlibat, termasuk interaksi yang tidak diminta dengan mereka yang menegakkan Kode Etik, selama jangka waktu tertentu. Hal ini mencakup penghindaran interaksi di ruang komunitas maupun di saluran eksternal seperti media sosial. Melanggar ketentuan ini dapat mengakibatkan larangan sementara atau permanen.
### 3. Temporary Ban
### 3. Larangan Sementara
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Dampak Komunitas**: Pelanggaran serius terhadap standar komunitas, termasuk perilaku tidak pantas yang berkelanjutan.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
**Konsekuensi**: Larangan sementara dari segala bentuk interaksi atau komunikasi publik dengan komunitas selama jangka waktu tertentu. Tidak ada interaksi publik maupun privat dengan pihak-pihak yang terlibat, termasuk interaksi yang tidak diminta dengan mereka yang menegakkan Kode Etik, yang diizinkan selama periode ini. Melanggar ketentuan ini dapat mengakibatkan larangan permanen.
### 4. Permanent Ban
### 4. Larangan Permanen
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Dampak Komunitas**: Menunjukkan pola pelanggaran standar komunitas, termasuk perilaku tidak pantas yang berkelanjutan, pelecehan terhadap individu, atau agresi terhadap atau penghinaan kepada golongan individu tertentu.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
**Konsekuensi**: Larangan permanen dari segala bentuk interaksi publik dalam komunitas.
## Attribution
## Atribusi
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
Kode Etik ini diadaptasi dari [Contributor Covenant][homepage],
versi 2.0, tersedia di
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
Pedoman Dampak Komunitas terinspirasi dari [tangga penegakan kode etik Mozilla](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
Untuk jawaban atas pertanyaan umum tentang kode etik ini, lihat FAQ di
https://www.contributor-covenant.org/faq. Terjemahan tersedia di
https://www.contributor-covenant.org/translations.

View File

@@ -1,22 +1,22 @@
# Contributing to OmniRoute (Bahasa Indonesia)
# Berkontribusi ke OmniRoute (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇧🇩 [bn](../bn/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇮🇷 [fa](../fa/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇮🇳 [gu](../gu/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇮🇳 [hi](../hi/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇮🇳 [mr](../mr/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇰🇪 [sw](../sw/CONTRIBUTING.md) · 🇮🇳 [ta](../ta/CONTRIBUTING.md) · 🇮🇳 [te](../te/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇹🇷 [tr](../tr/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇵🇰 [ur](../ur/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md)
---
Thank you for your interest in contributing! This guide covers everything you need to get started.
Terima kasih atas minat Anda untuk berkontribusi! Panduan ini mencakup semua yang perlu Anda ketahui untuk memulai.
---
## Development Setup
## Pengaturan Pengembangan
### Prerequisites
### Persyaratan
- **Node.js** >= 18 < 24 (recommended: 22 LTS)
- **npm** 10+
- **Git**
### Clone & Install
### Kloning & Instalasi
```bash
git clone https://github.com/diegosouzapw/OmniRoute.git
@@ -24,7 +24,7 @@ cd OmniRoute
npm install
```
### Environment Variables
### Variabel Lingkungan
```bash
# Create your .env from the template
@@ -35,28 +35,28 @@ echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
```
Key variables for development:
Variabel-variabel utama untuk pengembangan:
| Variable | Development Default | Description |
| ---------------------- | ------------------------ | --------------------- |
| `PORT` | `20128` | Server port |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
| `JWT_SECRET` | (generate above) | JWT signing secret |
| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
| `APP_LOG_LEVEL` | `info` | Log verbosity level |
| Variable | Development Default | Deskripsi |
| ---------------------- | ------------------------ | --------------------------------- |
| `PORT` | `20128` | Port server |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | URL dasar untuk frontend |
| `JWT_SECRET` | (generate above) | Kunci penandatanganan JWT |
| `INITIAL_PASSWORD` | `CHANGEME` | Kata sandi login pertama |
| `APP_LOG_LEVEL` | `info` | Tingkat verbositas log |
### Dashboard Settings
### Pengaturan Dashboard
The dashboard provides UI toggles for features that can also be configured via environment variables:
Dashboard menyediakan tombol UI untuk fitur-fitur yang juga dapat dikonfigurasi melalui variabel lingkungan:
| Setting Location | Toggle | Description |
| ------------------- | ------------------ | ------------------------------ |
| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
| Lokasi Pengaturan | Tombol | Deskripsi |
| ------------------- | ------------------ | ---------------------------------------- |
| Settings → Advanced | Debug Mode | Aktifkan log permintaan debug (UI) |
| Settings → General | Sidebar Visibility | Tampilkan/sembunyikan bagian sidebar |
These settings are stored in the database and persist across restarts, overriding env var defaults when set.
Pengaturan ini disimpan di database dan tetap ada setelah restart, menggantikan nilai default variabel lingkungan jika sudah diatur.
### Running Locally
### Menjalankan Secara Lokal
```bash
# Development mode (hot reload)
@@ -70,16 +70,16 @@ npm run start
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
Default URLs:
URL default:
- **Dashboard**: `http://localhost:20128/dashboard`
- **API**: `http://localhost:20128/v1`
---
## Git Workflow
## Alur Kerja Git
> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
> ⚠️ **JANGAN PERNAH melakukan commit langsung ke `main`.** Selalu gunakan cabang fitur.
```bash
git checkout -b feat/your-feature-name
@@ -89,20 +89,20 @@ git push -u origin feat/your-feature-name
# Open a Pull Request on GitHub
```
### Branch Naming
### Penamaan Cabang
| Prefix | Purpose |
| ----------- | ------------------------- |
| `feat/` | New features |
| `fix/` | Bug fixes |
| `refactor/` | Code restructuring |
| `docs/` | Documentation changes |
| `test/` | Test additions/fixes |
| `chore/` | Tooling, CI, dependencies |
| Awalan | Tujuan |
| ----------- | ------------------------------ |
| `feat/` | Fitur baru |
| `fix/` | Perbaikan bug |
| `refactor/` | Restrukturisasi kode |
| `docs/` | Perubahan dokumentasi |
| `test/` | Penambahan/perbaikan tes |
| `chore/` | Perkakas, CI, dependensi |
### Commit Messages
### Pesan Commit
Follow [Conventional Commits](https://www.conventionalcommits.org/):
Ikuti [Conventional Commits](https://www.conventionalcommits.org/):
```
feat: add circuit breaker for provider calls
@@ -112,11 +112,11 @@ test: add observability unit tests
refactor(db): consolidate rate limit tables
```
Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
Cakupan: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
---
## Running Tests
## Menjalankan Tes
```bash
# All tests (unit + vitest + ecosystem + e2e)
@@ -146,166 +146,166 @@ npm run lint
npm run check
```
Coverage notes:
Catatan cakupan:
- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
- Pull requests must keep the overall coverage gate at **60% or higher** for statements, lines, functions, and branches
- If a PR changes production code in `src/`, `open-sse/`, `electron/`, or `bin/`, it must add or update automated tests in the same PR
- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
- `npm run test:coverage:legacy` preserves the older metric for historical comparison
- See `docs/ops/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
- `npm run test:coverage` mengukur cakupan kode sumber untuk rangkaian tes unit utama, mengecualikan `tests/**`, dan menyertakan `open-sse/**`
- Pull request harus menjaga batas cakupan keseluruhan di **60% atau lebih tinggi** untuk pernyataan, baris, fungsi, dan cabang
- Jika sebuah PR mengubah kode produksi di `src/`, `open-sse/`, `electron/`, atau `bin/`, PR tersebut harus menambahkan atau memperbarui tes otomatis dalam PR yang sama
- `npm run coverage:report` mencetak laporan terperinci per file dari hasil cakupan terbaru
- `npm run test:coverage:legacy` mempertahankan metrik lama untuk perbandingan historis
- Lihat `docs/ops/COVERAGE_PLAN.md` untuk peta jalan peningkatan cakupan bertahap
### Pull Request Requirements
### Persyaratan Pull Request
Before opening or merging a PR:
Sebelum membuka atau menggabungkan sebuah PR:
- Run `npm run test:unit`
- Run `npm run test:coverage`
- Ensure the coverage gate stays at **60%+** for all metrics
- Include the changed or added test files in the PR description when production code changed
- Check the SonarQube result on the PR when the project secrets are configured in CI
- Jalankan `npm run test:unit`
- Jalankan `npm run test:coverage`
- Pastikan batas cakupan tetap di **60%+** untuk semua metrik
- Sertakan file tes yang diubah atau ditambahkan dalam deskripsi PR ketika kode produksi berubah
- Periksa hasil SonarQube pada PR ketika rahasia proyek dikonfigurasi di CI
Current test status: **122 unit test files** covering:
Status tes saat ini: **122 file tes unit** yang mencakup:
- Provider translators and format conversion
- Rate limiting, circuit breaker, and resilience
- Semantic cache, idempotency, progress tracking
- Database operations and schema (21 DB modules)
- OAuth flows and authentication
- API endpoint validation (Zod v4)
- MCP server tools and scope enforcement
- Memory and Skills systems
- Penerjemah penyedia dan konversi format
- Pembatasan laju, pemutus sirkuit, dan ketahanan
- Cache semantik, idempoten, pelacakan progres
- Operasi database dan skema (21 modul DB)
- Alur OAuth dan autentikasi
- Validasi endpoint API (Zod v4)
- Alat server MCP dan penegakan cakupan
- Sistem Memory dan Skills
---
## Code Style
## Gaya Kode
- **ESLint** — Run `npm run lint` before committing
- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
- **Zod validation** — Use Zod v4 schemas for all API input validation
- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
- **ESLint** — Jalankan `npm run lint` sebelum melakukan commit
- **Prettier** — Diformat otomatis melalui `lint-staged` saat commit (2 spasi, titik koma, tanda kutip ganda, lebar 100 karakter, koma trailing es5)
- **TypeScript** — Semua kode `src/` menggunakan `.ts`/`.tsx`; `open-sse/` menggunakan `.ts`/`.js`; dokumentasi dengan TSDoc (`@param`, `@returns`, `@throws`)
- **Tanpa `eval()`** — ESLint menerapkan `no-eval`, `no-implied-eval`, `no-new-func`
- **Validasi Zod** — Gunakan skema Zod v4 untuk semua validasi input API
- **Penamaan**: File = camelCase/kebab-case, komponen = PascalCase, konstanta = UPPER_SNAKE
---
## Project Structure
## Struktur Proyek
```
src/ # TypeScript (.ts / .tsx)
├── app/ # Next.js 16 App Router
│ ├── (dashboard)/ # Dashboard pages (23 sections)
│ ├── api/ # API routes (51 directories)
│ └── login/ # Auth pages (.tsx)
├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
├── lib/ # Core business logic (.ts)
│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
│ ├── acp/ # Agent Communication Protocol registry
│ ├── compliance/ # Compliance policy engine
│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
│ ├── memory/ # Persistent conversational memory
│ ├── oauth/ # OAuth providers, services, and utilities
│ ├── skills/ # Extensible skill framework
│ ├── usage/ # Usage tracking and cost calculation
│ └── localDb.ts # Re-export layer only — never add logic here
├── middleware/ # Request middleware (promptInjectionGuard)
├── mitm/ # MITM proxy (cert, DNS, target routing)
│ ├── (dashboard)/ # Halaman dashboard (23 bagian)
│ ├── api/ # Rute API (51 direktori)
│ └── login/ # Halaman autentikasi (.tsx)
├── domain/ # Mesin kebijakan (policyEngine, comboResolver, costRules, dll.)
├── lib/ # Logika bisnis inti (.ts)
│ ├── a2a/ # Server protokol Agent-to-Agent v0.3
│ ├── acp/ # Registri Agent Communication Protocol
│ ├── compliance/ # Mesin kebijakan kepatuhan
│ ├── db/ # Lapisan database SQLite (21 modul + 16 migrasi)
│ ├── memory/ # Memori percakapan persisten
│ ├── oauth/ # Penyedia, layanan, dan utilitas OAuth
│ ├── skills/ # Kerangka skill yang dapat diperluas
│ ├── usage/ # Pelacakan penggunaan dan kalkulasi biaya
│ └── localDb.ts # Lapisan re-ekspor saja — jangan pernah tambahkan logika di sini
├── middleware/ # Middleware permintaan (promptInjectionGuard)
├── mitm/ # Proxy MITM (sertifikat, DNS, perutean target)
├── shared/
│ ├── components/ # React components (.tsx)
│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
│ └── validation/ # Zod v4 schemas
└── sse/ # SSE proxy pipeline
│ ├── components/ # Komponen React (.tsx)
│ ├── constants/ # Definisi penyedia (60+), cakupan MCP, strategi perutean
│ ├── utils/ # Pemutus sirkuit, sanitizer, pembantu autentikasi
│ └── validation/ # Skema Zod v4
└── sse/ # Pipeline proxy SSE
open-sse/ # @omniroute/open-sse workspace
├── executors/ # 14 provider-specific request executors
├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
├── transformer/ # Responses API transformer
└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
open-sse/ # Workspace @omniroute/open-sse
├── executors/ # 14 eksekutor permintaan khusus penyedia
├── handlers/ # 11 penangan permintaan (chat, responses, embeddings, images, dll.)
├── mcp-server/ # Server MCP (25 alat, 3 transport, 10 cakupan)
├── services/ # 36+ layanan (combo, autoCombo, rateLimitManager, dll.)
├── translator/ # Penerjemah format (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
├── transformer/ # Transformer Responses API
└── utils/ # 22 modul utilitas (stream, TLS, proxy, logging)
electron/ # Electron desktop app (cross-platform)
electron/ # Aplikasi desktop Electron (lintas platform)
tests/
├── unit/ # Node.js test runner (122 test files)
├── integration/ # Integration tests
├── e2e/ # Playwright tests
├── security/ # Security tests
├── translator/ # Translator-specific tests
└── load/ # Load tests
├── unit/ # Runner tes Node.js (122 file tes)
├── integration/ # Tes integrasi
├── e2e/ # Tes Playwright
├── security/ # Tes keamanan
├── translator/ # Tes khusus penerjemah
└── load/ # Tes beban
docs/ # Documentation
├── ARCHITECTURE.md # System architecture
├── API_REFERENCE.md # All endpoints
├── USER_GUIDE.md # Provider setup, CLI integration
├── TROUBLESHOOTING.md # Common issues
├── MCP-SERVER.md # MCP server (25 tools)
├── A2A-SERVER.md # A2A agent protocol
├── AUTO-COMBO.md # Auto-combo engine
├── CLI-TOOLS.md # CLI tools integration
├── COVERAGE_PLAN.md # Test coverage improvement plan
├── openapi.yaml # OpenAPI specification
└── adr/ # Architecture Decision Records
docs/ # Dokumentasi
├── ARCHITECTURE.md # Arsitektur sistem
├── API_REFERENCE.md # Semua endpoint
├── USER_GUIDE.md # Pengaturan penyedia, integrasi CLI
├── TROUBLESHOOTING.md # Masalah umum
├── MCP-SERVER.md # Server MCP (25 alat)
├── A2A-SERVER.md # Protokol agen A2A
├── AUTO-COMBO.md # Mesin auto-combo
├── CLI-TOOLS.md # Integrasi alat CLI
├── COVERAGE_PLAN.md # Rencana peningkatan cakupan tes
├── openapi.yaml # Spesifikasi OpenAPI
└── adr/ # Catatan Keputusan Arsitektur
```
---
## Adding a New Provider
## Menambahkan Penyedia Baru
### Step 1: Register Provider Constants
### Langkah 1: Daftarkan Konstanta Penyedia
Add to `src/shared/constants/providers.ts`Zod-validated at module load.
Tambahkan ke `src/shared/constants/providers.ts`divalidasi dengan Zod saat modul dimuat.
### Step 2: Add Executor (if custom logic needed)
### Langkah 2: Tambahkan Eksekutor (jika diperlukan logika kustom)
Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
Buat eksekutor di `open-sse/executors/your-provider.ts` dengan memperluas eksekutor dasar.
### Step 3: Add Translator (if non-OpenAI format)
### Langkah 3: Tambahkan Penerjemah (jika format bukan OpenAI)
Create request/response translators in `open-sse/translator/`.
Buat penerjemah permintaan/respons di `open-sse/translator/`.
### Step 4: Add OAuth Config (if OAuth-based)
### Langkah 4: Tambahkan Konfigurasi OAuth (jika berbasis OAuth)
Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
Tambahkan kredensial OAuth di `src/lib/oauth/constants/oauth.ts` dan layanan di `src/lib/oauth/services/`.
### Step 5: Register Models
### Langkah 5: Daftarkan Model
Add model definitions in `open-sse/config/providerRegistry.ts`.
Tambahkan definisi model di `open-sse/config/providerRegistry.ts`.
### Step 6: Add Tests
### Langkah 6: Tambahkan Tes
Write unit tests in `tests/unit/` covering at minimum:
Tulis tes unit di `tests/unit/` yang mencakup minimal:
- Provider registration
- Request/response translation
- Error handling
- Pendaftaran penyedia
- Terjemahan permintaan/respons
- Penanganan kesalahan
---
## Pull Request Checklist
## Daftar Periksa Pull Request
- [ ] Tests pass (`npm test`)
- [ ] Linting passes (`npm run lint`)
- [ ] Build succeeds (`npm run build`)
- [ ] TypeScript types added for new public functions and interfaces
- [ ] No hardcoded secrets or fallback values
- [ ] All inputs validated with Zod schemas
- [ ] CHANGELOG updated (if user-facing change)
- [ ] Documentation updated (if applicable)
- [ ] Tes lulus (`npm test`)
- [ ] Linting lulus (`npm run lint`)
- [ ] Build berhasil (`npm run build`)
- [ ] Tipe TypeScript ditambahkan untuk fungsi dan antarmuka publik baru
- [ ] Tidak ada rahasia atau nilai fallback yang dikodekan secara keras
- [ ] Semua input divalidasi dengan skema Zod
- [ ] CHANGELOG diperbarui (jika ada perubahan yang terlihat pengguna)
- [ ] Dokumentasi diperbarui (jika berlaku)
---
## Releasing
## Rilis
Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
Rilis dikelola melalui alur kerja `/generate-release`. Ketika GitHub Release baru dibuat, paket secara **otomatis diterbitkan ke npm** melalui GitHub Actions.
---
## Getting Help
## Mendapatkan Bantuan
- **Architecture**: See [`docs/architecture/ARCHITECTURE.md`](docs/architecture/ARCHITECTURE.md)
- **API Reference**: See [`docs/reference/API_REFERENCE.md`](docs/reference/API_REFERENCE.md)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **ADRs**: See `docs/adr/` for architectural decision records
- **Arsitektur**: Lihat [`docs/architecture/ARCHITECTURE.md`](docs/architecture/ARCHITECTURE.md)
- **Referensi API**: Lihat [`docs/reference/API_REFERENCE.md`](docs/reference/API_REFERENCE.md)
- **Masalah**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **ADR**: Lihat `docs/adr/` untuk catatan keputusan arsitektur

View File

@@ -1,25 +1,25 @@
# Security and Cleanliness Rules for AI Assistants (Bahasa Indonesia)
# Aturan Keamanan dan Kebersihan untuk Asisten AI (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../GEMINI.md) · 🇸🇦 [ar](../ar/GEMINI.md) · 🇧🇬 [bg](../bg/GEMINI.md) · 🇧🇩 [bn](../bn/GEMINI.md) · 🇨🇿 [cs](../cs/GEMINI.md) · 🇩🇰 [da](../da/GEMINI.md) · 🇩🇪 [de](../de/GEMINI.md) · 🇪🇸 [es](../es/GEMINI.md) · 🇮🇷 [fa](../fa/GEMINI.md) · 🇫🇮 [fi](../fi/GEMINI.md) · 🇫🇷 [fr](../fr/GEMINI.md) · 🇮🇳 [gu](../gu/GEMINI.md) · 🇮🇱 [he](../he/GEMINI.md) · 🇮🇳 [hi](../hi/GEMINI.md) · 🇭🇺 [hu](../hu/GEMINI.md) · 🇮🇩 [id](../id/GEMINI.md) · 🇮🇹 [it](../it/GEMINI.md) · 🇯🇵 [ja](../ja/GEMINI.md) · 🇰🇷 [ko](../ko/GEMINI.md) · 🇮🇳 [mr](../mr/GEMINI.md) · 🇲🇾 [ms](../ms/GEMINI.md) · 🇳🇱 [nl](../nl/GEMINI.md) · 🇳🇴 [no](../no/GEMINI.md) · 🇵🇭 [phi](../phi/GEMINI.md) · 🇵🇱 [pl](../pl/GEMINI.md) · 🇵🇹 [pt](../pt/GEMINI.md) · 🇧🇷 [pt-BR](../pt-BR/GEMINI.md) · 🇷🇴 [ro](../ro/GEMINI.md) · 🇷🇺 [ru](../ru/GEMINI.md) · 🇸🇰 [sk](../sk/GEMINI.md) · 🇸🇪 [sv](../sv/GEMINI.md) · 🇰🇪 [sw](../sw/GEMINI.md) · 🇮🇳 [ta](../ta/GEMINI.md) · 🇮🇳 [te](../te/GEMINI.md) · 🇹🇭 [th](../th/GEMINI.md) · 🇹🇷 [tr](../tr/GEMINI.md) · 🇺🇦 [uk-UA](../uk-UA/GEMINI.md) · 🇵🇰 [ur](../ur/GEMINI.md) · 🇻🇳 [vi](../vi/GEMINI.md) · 🇨🇳 [zh-CN](../zh-CN/GEMINI.md)
---
## 1. File Placement & Organization
## 1. Penempatan & Organisasi File
- **Test Files**: ALL unit tests, integration tests, ecosystem tests, or Vitest files MUST strictly be placed within the `tests/` directory (e.g., `tests/unit/`, `tests/integration/`). NEVER create test files in the project root (`/`).
- **Scripts and Utilities**: ALL maintenance, debugging, generation, or experimental scripts (`.cjs`, `.mjs`, `.js`, `.ts`) MUST be placed strictly inside the `scripts/` directory or `scripts/scratch/` for temporary one-offs. NEVER dump loose scripts in the project root (`/`).
- **File Tes**: SEMUA uji unit, uji integrasi, uji ekosistem, atau file Vitest HARUS ditempatkan secara ketat di dalam direktori `tests/` (mis., `tests/unit/`, `tests/integration/`). JANGAN PERNAH membuat file tes di root proyek (`/`).
- **Skrip dan Utilitas**: SEMUA skrip pemeliharaan, debugging, pembuatan, atau eksperimental (`.cjs`, `.mjs`, `.js`, `.ts`) HARUS ditempatkan secara ketat di dalam direktori `scripts/` atau `scripts/scratch/` untuk keperluan sementara. JANGAN PERNAH membuang skrip bebas di root proyek (`/`).
**The Project Root MUST ONLY CONTAIN:**
**Root Proyek HANYA BOLEH BERISI:**
- Configuration files (`vitest.config.ts`, `next.config.mjs`, `eslint.config.mjs`, etc.)
- Dependency files (`package.json`, `package-lock.json`)
- Documentation files (`README.md`, `CHANGELOG.md`, `AGENTS.md`)
- CI/CD files and ignore definitions (`.gitignore`, `.dockerignore`)
- File konfigurasi (`vitest.config.ts`, `next.config.mjs`, `eslint.config.mjs`, dll.)
- File dependensi (`package.json`, `package-lock.json`)
- File dokumentasi (`README.md`, `CHANGELOG.md`, `AGENTS.md`)
- File CI/CD dan definisi pengabaian (`.gitignore`, `.dockerignore`)
When creating _any_ validation tests or one-off logic scripts, default to using `scripts/scratch/` or the `tests/unit/` directories according to your goals. Do not pollute the `/` root context.
Saat membuat _tes validasi_ atau skrip logika sekali pakai, default ke penggunaan `scripts/scratch/` atau direktori `tests/unit/` sesuai tujuan Anda. Jangan mencemari konteks root `/`.
## 2. VPS Dashboard Credentials
## 2. Kredensial Dashboard VPS
| Environment | URL | Password |
| ----------- | ------------------------- | -------- |
| Local VPS | http://192.168.0.15:20128 | 123456 |
| Lingkungan | URL | Kata Sandi |
| ---------- | ------------------------- | ---------- |
| VPS Lokal | http://192.168.0.15:20128 | 123456 |

File diff suppressed because it is too large Load Diff

View File

@@ -1,138 +1,138 @@
# Security Policy (Bahasa Indonesia)
# Kebijakan Keamanan (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇧🇩 [bn](../bn/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇮🇷 [fa](../fa/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇮🇳 [gu](../gu/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇮🇳 [hi](../hi/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇮🇳 [mr](../mr/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇰🇪 [sw](../sw/SECURITY.md) · 🇮🇳 [ta](../ta/SECURITY.md) · 🇮🇳 [te](../te/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇹🇷 [tr](../tr/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇵🇰 [ur](../ur/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md)
---
## Reporting Vulnerabilities
## Melaporkan Kerentanan
If you discover a security vulnerability in OmniRoute, please report it responsibly:
Jika Anda menemukan kerentanan keamanan di OmniRoute, harap laporkan secara bertanggung jawab:
1. **DO NOT** open a public GitHub issue
2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
3. Include: description, reproduction steps, and potential impact
1. **JANGAN** membuka isu GitHub yang bersifat publik
2. Gunakan [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
3. Sertakan: deskripsi, langkah-langkah reproduksi, dan potensi dampak
## Response Timeline
## Linimasa Respons
| Stage | Target |
| ------------------- | --------------------------- |
| Acknowledgment | 48 hours |
| Triage & Assessment | 5 business days |
| Patch Release | 14 business days (critical) |
| Tahap | Target |
| ----------------------- | ------------------------------- |
| Konfirmasi Penerimaan | 48 jam |
| Triase & Penilaian | 5 hari kerja |
| Rilis Patch | 14 hari kerja (kritis) |
## Supported Versions
## Versi yang Didukung
| Version | Support Status |
| ------- | -------------- |
| 3.6.x | ✅ Active |
| 3.5.x | ✅ Security |
| < 3.5.0 | ❌ Unsupported |
| Versi | Status Dukungan |
| ------- | ------------------ |
| 3.6.x | ✅ Aktif |
| 3.5.x | ✅ Keamanan |
| < 3.5.0 | ❌ Tidak Didukung |
---
## Security Architecture
## Arsitektur Keamanan
OmniRoute implements a multi-layered security model:
OmniRoute menerapkan model keamanan berlapis:
```
Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
```
### 🔐 Authentication & Authorization
### 🔐 Autentikasi & Otorisasi
| Feature | Implementation |
| -------------------- | ---------------------------------------------------------- |
| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
| **API Key Auth** | HMAC-signed keys with CRC validation |
| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
| **Token Refresh** | Automatic OAuth token refresh before expiry |
| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
| **MCP Scopes** | 10 granular scopes for MCP tool access control |
| Fitur | Implementasi |
| -------------------- | ------------------------------------------------------------------- |
| **Login Dashboard** | Autentikasi berbasis kata sandi dengan token JWT (cookie HttpOnly) |
| **Autentikasi API Key** | Kunci bertanda tangan HMAC dengan validasi CRC |
| **OAuth 2.0 + PKCE** | Autentikasi penyedia yang aman (Claude, Codex, Gemini, Cursor, dll.) |
| **Pembaruan Token** | Pembaruan token OAuth otomatis sebelum kedaluwarsa |
| **Cookie Aman** | `AUTH_COOKIE_SECURE=true` untuk lingkungan HTTPS |
| **Ruang Lingkup MCP** | 10 ruang lingkup terperinci untuk kontrol akses alat MCP |
### 🛡️ Encryption at Rest
### 🛡️ Enkripsi Data Tersimpan
All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
Semua data sensitif yang disimpan di SQLite dienkripsi menggunakan **AES-256-GCM** dengan derivasi kunci scrypt:
- API keys, access tokens, refresh tokens, and ID tokens
- Versioned format: `enc:v1:<iv>:<ciphertext>:<authTag>`
- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
- Kunci API, token akses, token penyegaran, dan token ID
- Format berversi: `enc:v1:<iv>:<ciphertext>:<authTag>`
- Mode passthrough (teks biasa) ketika `STORAGE_ENCRYPTION_KEY` tidak disetel
```bash
# Generate encryption key:
STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
```
### 🧠 Prompt Injection Guard
### 🧠 Penjaga Injeksi Prompt
Middleware that detects and blocks prompt injection attacks in LLM requests:
Middleware yang mendeteksi dan memblokir serangan injeksi prompt dalam permintaan LLM:
| Pattern Type | Severity | Example |
| ------------------- | -------- | ---------------------------------------------- |
| System Override | High | "ignore all previous instructions" |
| Role Hijack | High | "you are now DAN, you can do anything" |
| Delimiter Injection | Medium | Encoded separators to break context boundaries |
| DAN/Jailbreak | High | Known jailbreak prompt patterns |
| Instruction Leak | Medium | "show me your system prompt" |
| Jenis Pola | Tingkat Keparahan | Contoh |
| ------------------- | ----------------- | ----------------------------------------------------------- |
| Penimpaan Sistem | Tinggi | "ignore all previous instructions" |
| Pembajakan Peran | Tinggi | "you are now DAN, you can do anything" |
| Injeksi Pembatas | Sedang | Pemisah yang dikodekan untuk merusak batas konteks |
| DAN/Jailbreak | Tinggi | Pola prompt jailbreak yang telah diketahui |
| Kebocoran Instruksi | Sedang | "show me your system prompt" |
Configure via dashboard (Settings → Security) or `.env`:
Konfigurasikan melalui dashboard (Settings → Security) atau `.env`:
```env
INPUT_SANITIZER_ENABLED=true
INPUT_SANITIZER_MODE=block # warn | block | redact
```
### 🔒 PII Redaction
### 🔒 Redaksi PII
Automatic detection and optional redaction of personally identifiable information:
Deteksi otomatis dan redaksi opsional informasi yang dapat mengidentifikasi pribadi:
| PII Type | Pattern | Replacement |
| ------------- | --------------------- | ------------------ |
| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
| Jenis PII | Pola | Pengganti |
| ---------------- | --------------------- | ------------------ |
| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
| CPF (Brasil) | `123.456.789-00` | `[CPF_REDACTED]` |
| CNPJ (Brasil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
| Kartu Kredit | `4111-1111-1111-1111` | `[CC_REDACTED]` |
| Telepon | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
| SSN (AS) | `123-45-6789` | `[SSN_REDACTED]` |
```env
PII_REDACTION_ENABLED=true
```
### 🌐 Network Security
### 🌐 Keamanan Jaringan
| Feature | Description |
| ------------------------ | ---------------------------------------------------------------- |
| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
| **Rate Limiting** | Per-provider rate limits with automatic backoff |
| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
| Fitur | Deskripsi |
| ------------------------ | ------------------------------------------------------------------------------- |
| **CORS** | Kontrol origin yang dapat dikonfigurasi (variabel env `CORS_ORIGIN`, default `*`) |
| **Pemfilteran IP** | Daftar izin/blokir rentang IP di dashboard |
| **Pembatasan Laju** | Batas laju per-penyedia dengan backoff otomatis |
| **Anti-Thundering Herd** | Mutex + penguncian per-koneksi mencegah kegagalan 502 beruntun |
| **Sidik Jari TLS** | Spoofing sidik jari TLS menyerupai browser untuk mengurangi deteksi bot |
| **Sidik Jari CLI** | Pengurutan header/body per-penyedia agar sesuai tanda tangan CLI native |
### 🔌 Resilience & Availability
### 🔌 Ketahanan & Ketersediaan
| Feature | Description |
| ----------------------- | ------------------------------------------------------------------ |
| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
| **Request Idempotency** | 5-second dedup window for duplicate requests |
| **Exponential Backoff** | Automatic retry with increasing delays |
| **Health Dashboard** | Real-time provider health monitoring |
| Fitur | Deskripsi |
| -------------------------- | ---------------------------------------------------------------------------- |
| **Pemutus Sirkuit** | 3 status (Closed → Open → Half-Open) per penyedia, dipersistenkan di SQLite |
| **Idempotansi Permintaan** | Jendela deduplikasi 5 detik untuk permintaan duplikat |
| **Backoff Eksponensial** | Percobaan ulang otomatis dengan penundaan yang semakin meningkat |
| **Dashboard Kesehatan** | Pemantauan kesehatan penyedia secara real-time |
### 📋 Compliance
### 📋 Kepatuhan
| Feature | Description |
| ------------------ | ----------------------------------------------------------- |
| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
| **Audit Log** | Administrative actions tracked in `audit_log` table |
| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
| Fitur | Deskripsi |
| ---------------------- | ---------------------------------------------------------------------- |
| **Retensi Log** | Pembersihan otomatis setelah `CALL_LOG_RETENTION_DAYS` |
| **Opt-out Tanpa Log** | Tanda `noLog` per kunci API menonaktifkan pencatatan permintaan |
| **Log Audit** | Tindakan administratif dilacak di tabel `audit_log` |
| **Audit MCP** | Pencatatan audit berbasis SQLite untuk semua pemanggilan alat MCP |
| **Validasi Zod** | Semua input API divalidasi dengan skema Zod v4 saat pemuatan modul |
---
## Required Environment Variables
## Variabel Lingkungan yang Wajib Disetel
All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
Semua rahasia harus disetel sebelum menjalankan server. Server akan **gagal cepat** jika nilainya tidak ada atau terlalu lemah.
```bash
# REQUIRED — server will not start without these:
@@ -143,17 +143,17 @@ API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
```
The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
Server secara aktif menolak nilai yang diketahui lemah seperti `changeme`, `secret`, atau `password`.
---
## Docker Security
## Keamanan Docker
- Use non-root user in production
- Mount secrets as read-only volumes
- Never copy `.env` files into Docker images
- Use `.dockerignore` to exclude sensitive files
- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
- Gunakan pengguna non-root di lingkungan produksi
- Pasang rahasia sebagai volume hanya-baca
- Jangan pernah menyalin file `.env` ke dalam image Docker
- Gunakan `.dockerignore` untuk mengecualikan file sensitif
- Setel `AUTH_COOKIE_SECURE=true` saat berada di belakang HTTPS
```bash
docker run -d \
@@ -170,10 +170,10 @@ docker run -d \
---
## Dependencies
## Dependensi
- Run `npm audit` regularly
- Keep dependencies updated
- The project uses `husky` + `lint-staged` for pre-commit checks
- CI pipeline runs ESLint security rules on every push
- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
- Jalankan `npm audit` secara berkala
- Jaga agar dependensi tetap diperbarui
- Proyek menggunakan `husky` + `lint-staged` untuk pemeriksaan pra-commit
- Pipeline CI menjalankan aturan keamanan ESLint pada setiap push
- Konstanta penyedia divalidasi saat pemuatan modul melalui Zod (`src/shared/validation/providerSchema.ts`)

File diff suppressed because it is too large Load Diff

View File

@@ -4,21 +4,21 @@
---
> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
> Panduan lengkap dan ramah-pemula untuk router proxy AI multi-penyedia **omniroute**.
---
## 1. What Is omniroute?
## 1. Apa Itu omniroute?
omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
omniroute adalah sebuah **router proxy** yang berada di antara klien AI (Claude CLI, Codex, Cursor IDE, dll.) dan penyedia AI (Anthropic, Google, OpenAI, AWS, GitHub, dll.). Ia memecahkan satu masalah besar:
> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
> **Klien AI yang berbeda berbicara "bahasa" yang berbeda (format API), dan penyedia AI yang berbeda pun mengharapkan "bahasa" yang berbeda pula.** omniroute menerjemahkan di antara mereka secara otomatis.
Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
Bayangkan seperti penerjemah universal di Perserikatan Bangsa-Bangsa — delegasi mana pun dapat berbicara dalam bahasa apa pun, dan penerjemah mengubahnya untuk delegasi lainnya.
---
## 2. Architecture Overview
## 2. Ikhtisar Arsitektur
```mermaid
graph LR
@@ -63,82 +63,82 @@ graph LR
H -.-> G
```
### Core Principle: Hub-and-Spoke Translation
### Prinsip Inti: Terjemahan Hub-and-Spoke
All format translation passes through **OpenAI format as the hub**:
Semua terjemahan format melewati **format OpenAI sebagai hub**:
```
Client Format → [OpenAI Hub] → Provider Format (request)
Provider Format → [OpenAI Hub] → Client Format (response)
```
This means you only need **N translators** (one per format) instead of **N²** (every pair).
Artinya Anda hanya membutuhkan **N penerjemah** (satu per format), bukan **N²** (setiap pasangan).
---
## 3. Project Structure
## 3. Struktur Proyek
```
omniroute/
├── open-sse/ ← Core proxy library (portable, framework-agnostic)
│ ├── index.js ← Main entry point, exports everything
│ ├── config/ ← Configuration & constants
│ ├── executors/ ← Provider-specific request execution
│ ├── handlers/ ← Request handling orchestration
│ ├── services/ ← Business logic (auth, models, fallback, usage)
│ ├── translator/ ← Format translation engine
│ │ ├── request/ ← Request translators (8 files)
│ │ ├── response/ ← Response translators (7 files)
│ │ └── helpers/ ← Shared translation utilities (6 files)
│ └── utils/ ← Utility functions
├── src/ ← Application layer (Express/Worker runtime)
│ ├── app/ ← Web UI, API routes, middleware
│ ├── lib/ ← Database, auth, and shared library code
│ ├── mitm/ ← Man-in-the-middle proxy utilities
│ ├── models/ ← Database models
│ ├── shared/ ← Shared utilities (wrappers around open-sse)
│ ├── sse/ ← SSE endpoint handlers
│ └── store/ ← State management
├── data/ ← Runtime data (credentials, logs)
│ └── provider-credentials.json (external credentials override, gitignored)
└── tester/ ← Test utilities
├── open-sse/ ← Library proxy inti (portabel, framework-agnostic)
│ ├── index.js ← Titik masuk utama, mengekspor segalanya
│ ├── config/ ← Konfigurasi & konstanta
│ ├── executors/ ← Eksekusi permintaan khusus penyedia
│ ├── handlers/ ← Orkestrasi penanganan permintaan
│ ├── services/ ← Logika bisnis (auth, model, fallback, penggunaan)
│ ├── translator/ ← Mesin terjemahan format
│ │ ├── request/ ← Penerjemah permintaan (8 file)
│ │ ├── response/ ← Penerjemah respons (7 file)
│ │ └── helpers/ ← Utilitas terjemahan bersama (6 file)
│ └── utils/ ← Fungsi utilitas
├── src/ ← Lapisan aplikasi (runtime Express/Worker)
│ ├── app/ ← Antarmuka web, rute API, middleware
│ ├── lib/ ← Database, auth, dan kode library bersama
│ ├── mitm/ ← Utilitas proxy man-in-the-middle
│ ├── models/ ← Model database
│ ├── shared/ ← Utilitas bersama (wrapper open-sse)
│ ├── sse/ ← Handler endpoint SSE
│ └── store/ ← Manajemen state
├── data/ ← Data runtime (kredensial, log)
│ └── provider-credentials.json (override kredensial eksternal, diabaikan git)
└── tester/ ← Utilitas pengujian
```
---
## 4. Module-by-Module Breakdown
## 4. Rincian Modul per Modul
### 4.1 Config (`open-sse/config/`)
The **single source of truth** for all provider configuration.
**Satu-satunya sumber kebenaran** untuk semua konfigurasi penyedia.
| File | Purpose |
| File | Tujuan |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
| `constants.ts` | Objek `PROVIDERS` dengan URL dasar, kredensial OAuth (default), header, dan system prompt default untuk setiap penyedia. Juga mendefinisikan `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, dan `SKIP_PATTERNS`. |
| `credentialLoader.ts` | Memuat kredensial eksternal dari `data/provider-credentials.json` dan menggabungkannya ke atas nilai default yang ter-hardcode di `PROVIDERS`. Menjaga rahasia di luar source control sambil mempertahankan kompatibilitas mundur. |
| `providerModels.ts` | Registry model terpusat: memetakan alias penyedia → ID model. Fungsi-fungsi seperti `getModels()`, `getProviderByAlias()`. |
| `codexInstructions.ts` | Instruksi sistem yang disuntikkan ke dalam permintaan Codex (batasan pengeditan, aturan sandbox, kebijakan persetujuan). |
| `defaultThinkingSignature.ts` | Tanda tangan "berpikir" default untuk model Claude dan Gemini. |
| `ollamaModels.ts` | Definisi skema untuk model Ollama lokal (nama, ukuran, keluarga, kuantisasi). |
#### Credential Loading Flow
#### Alur Pemuatan Kredensial
```mermaid
flowchart TD
A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
B --> C{"data/provider-credentials.json\nexists?"}
C -->|Yes| D["credentialLoader reads JSON"]
C -->|No| E["Use hardcoded defaults"]
C -->|No| E["Gunakan default hardcode"]
D --> F{"For each provider in JSON"}
F --> G{"Provider exists\nin PROVIDERS?"}
G -->|No| H["Log warning, skip"]
G -->|Yes| I{"Value is object?"}
G -->|Yes| I{"Nilai adalah objek?"}
I -->|No| J["Log warning, skip"]
I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
K --> F
H --> F
J --> F
F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
F -->|Done| L["PROVIDERS siap dengan\nkredensial yang digabungkan"]
E --> L
```
@@ -146,7 +146,7 @@ flowchart TD
### 4.2 Executors (`open-sse/executors/`)
Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
Executor merangkum **logika khusus penyedia** menggunakan **Strategy Pattern**. Setiap executor mengganti metode dasar sesuai kebutuhan.
```mermaid
classDiagram
@@ -196,32 +196,32 @@ classDiagram
BaseExecutor <|-- GithubExecutor
```
| Executor | Provider | Key Specializations |
| Executor | Penyedia | Spesialisasi Utama |
| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
| `base.ts` | — | Basis abstrak: pembangunan URL, header, logika percobaan ulang, pembaruan kredensial |
| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Pembaruan token OAuth generik untuk penyedia standar |
| `antigravity.ts` | Google Cloud Code | Pembuatan ID proyek/sesi, fallback multi-URL, parsing percobaan ulang kustom dari pesan error ("reset after 2h7m23s") |
| `cursor.ts` | Cursor IDE | **Paling kompleks**: autentikasi checksum SHA-256, encoding permintaan Protobuf, parsing binary EventStream → respons SSE |
| `codex.ts` | OpenAI Codex | Menyuntikkan instruksi sistem, mengelola tingkat berpikir, menghapus parameter yang tidak didukung |
| `gemini-cli.ts` | Google Gemini CLI | Pembangunan URL kustom (`streamGenerateContent`), pembaruan token OAuth Google |
| `github.ts` | GitHub Copilot | Sistem token ganda (GitHub OAuth + token Copilot), peniruan header VSCode |
| `kiro.ts` | AWS CodeWhisperer | Parsing binary AWS EventStream, frame event AMZN, estimasi token |
| `index.ts` | — | Factory: memetakan nama penyedia → kelas executor, dengan fallback default |
---
### 4.3 Handlers (`open-sse/handlers/`)
The **orchestration layer**coordinates translation, execution, streaming, and error handling.
**Lapisan orkestrasi**mengoordinasikan terjemahan, eksekusi, streaming, dan penanganan error.
| File | Purpose |
| File | Tujuan |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completionssends to `chatCore`converts SSE back to Responses format. |
| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
| `chatCore.ts` | **Orkestrator pusat** (~600 baris). Menangani siklus hidup permintaan secara lengkap: deteksi format → terjemahan → dispatch executor → respons streaming/non-streaming → pembaruan token → penanganan error → pencatatan penggunaan. |
| `responsesHandler.ts` | Adaptor untuk Responses API OpenAI: mengonversi format Responses → Penyelesaian Obrolanmengirim ke `chatCore`mengonversi SSE kembali ke format Responses. |
| `embeddings.ts` | Handler pembuatan embedding: me-resolve model embedding → penyedia, mengirim ke API penyedia, mengembalikan respons embedding yang kompatibel dengan OpenAI. Mendukung 6+ penyedia. |
| `imageGeneration.ts` | Handler pembuatan gambar: me-resolve model gambar → penyedia, mendukung mode kompatibel-OpenAI, Gemini-image (Antigravity), dan fallback (Nebius). Mengembalikan gambar base64 atau URL. |
#### Request Lifecycle (chatCore.ts)
#### Siklus Hidup Permintaan (chatCore.ts)
```mermaid
sequenceDiagram
@@ -262,26 +262,26 @@ sequenceDiagram
### 4.4 Services (`open-sse/services/`)
Business logic that supports the handlers and executors.
Logika bisnis yang mendukung handler dan executor.
| File | Purpose |
| File | Tujuan |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
| `model.ts` | Model string parsing (`claude/model-name``{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
| `provider.ts` | **Deteksi format** (`detectFormat`): menganalisis struktur body permintaan untuk mengidentifikasi format Claude/OpenAI/Gemini/Antigravity/Responses (mencakup heuristik `max_tokens` untuk Claude). Juga: pembangunan URL, pembangunan header, normalisasi konfigurasi berpikir. Mendukung penyedia dinamis `openai-compatible-*` dan `anthropic-compatible-*`. |
| `model.ts` | Parsing string model (`claude/model-name``{provider: "claude", model: "model-name"}`), resolusi alias dengan deteksi tabrakan, sanitasi input (menolak path traversal/karakter kontrol), dan resolusi info model dengan dukungan getter alias asinkron. |
| `accountFallback.ts` | Penanganan rate-limit: backoff eksponensial (1d → 2d → 4d → maks 2min), manajemen cooldown akun, klasifikasi error (error mana yang memicu fallback vs. tidak). |
| `tokenRefresh.ts` | Pembaruan token OAuth untuk **setiap penyedia**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + token ganda Copilot), Kiro (AWS SSO OIDC + Social Auth). Mencakup cache deduplikasi promise in-flight dan percobaan ulang dengan backoff eksponensial. |
| `combo.ts` | **Model combo**: rantai model fallback. Jika model A gagal dengan error yang memenuhi syarat fallback, coba model B, lalu C, dst. Mengembalikan kode status upstream yang sebenarnya. |
| `usage.ts` | Mengambil data kuota/penggunaan dari API penyedia (kuota GitHub Copilot, kuota model Antigravity, batas laju Codex, rincian penggunaan Kiro, pengaturan Claude). |
| `accountSelector.ts` | Pemilihan akun cerdas dengan algoritma penilaian: mempertimbangkan prioritas, status kesehatan, posisi round-robin, dan kondisi cooldown untuk memilih akun optimal setiap permintaan. |
| `contextManager.ts` | Manajemen siklus hidup konteks permintaan: membuat dan melacak objek konteks per-permintaan dengan metadata (ID permintaan, stempel waktu, info penyedia) untuk debugging dan pencatatan. |
| `ipFilter.ts` | Kontrol akses berbasis IP: mendukung mode allowlist dan blocklist. Memvalidasi IP klien terhadap aturan yang dikonfigurasi sebelum memproses permintaan API. |
| `sessionManager.ts` | Pelacakan sesi dengan fingerprinting klien: melacak sesi aktif menggunakan identifier klien yang di-hash, memantau jumlah permintaan, dan menyediakan metrik sesi. |
| `signatureCache.ts` | Cache deduplikasi berbasis tanda tangan permintaan: mencegah permintaan duplikat dengan menyimpan cache tanda tangan permintaan terbaru dan mengembalikan respons tersimpan untuk permintaan identik dalam jendela waktu tertentu. |
| `systemPrompt.ts` | Injeksi system prompt global: menambahkan di depan atau di belakang system prompt yang dapat dikonfigurasi ke semua permintaan, dengan penanganan kompatibilitas per-penyedia. |
| `thinkingBudget.ts` | Manajemen anggaran token penalaran: mendukung mode passthrough, auto (hapus konfigurasi berpikir), kustom (anggaran tetap), dan adaptif (skala kompleksitas) untuk mengendalikan token berpikir/penalaran. |
| `wildcardRouter.ts` | Routing pola model wildcard: me-resolve pola wildcard (mis., `*/claude-*`) ke pasangan penyedia/model konkret berdasarkan ketersediaan dan prioritas. |
#### Token Refresh Deduplication
#### Deduplikasi Pembaruan Token
```mermaid
sequenceDiagram
@@ -302,7 +302,7 @@ sequenceDiagram
Cache->>Cache: Delete cache entry
```
#### Account Fallback State Machine
#### Mesin Status Fallback Akun
```mermaid
stateDiagram-v2
@@ -327,7 +327,7 @@ stateDiagram-v2
}
```
#### Combo Model Chain
#### Model Rantai Kombo
```mermaid
flowchart LR
@@ -348,7 +348,7 @@ flowchart LR
### 4.5 Translator (`open-sse/translator/`)
The **format translation engine** using a self-registering plugin system.
**Mesin terjemahan format** yang menggunakan sistem plugin pendaftaran-diri.
#### Arsitektur
@@ -376,40 +376,40 @@ graph TD
end
```
| Directory | Files | Description |
| Direktori | File | Deskripsi |
| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
| `request/` | 8 penerjemah | Mengonversi body permintaan antar format. Setiap file mendaftar sendiri melalui `register(from, to, fn)` saat diimpor. |
| `response/` | 7 penerjemah | Mengonversi potongan respon streaming antar format. berpartisipasi tipe acara SSE, blok berpikir, panggilan alat. |
| `helpers/` | 6 pembantu | Utilitas bersama: `claudeHelper` (ekstraksi system prompt, konfigurasi berpikir), `geminiHelper` (pemetaan parts/contents), `openaiHelper` (pemfilteran format), `toolCallHelper` (pembuatan ID, injeksi respons yang hilang), `maxTokensHelper`, `responsesApiHelper`. |
| `index.ts` | — | Mesin terjemahan: `translateRequest()`, `translateResponse()`, manajemen state, registry. |
| `formats.ts` | — | Konstanta format: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
#### Key Design: Self-Registering Plugins
#### Desain Utama: Plugin Pendaftaran-Diri
```javascript
// Each translator file calls register() on import:
// Setiap file penerjemah memanggil register() saat diimpor:
import { register } from "../index.js";
register("claude", "openai", translateClaudeToOpenAI);
// The index.js imports all translator files, triggering registration:
import "./request/claude-to-openai.js"; // ← self-registers
// index.js mengimpor semua file penerjemah, memicu pendaftaran:
import "./request/claude-to-openai.js"; // ← mendaftar sendiri
```
---
### 4.6 Utils (`open-sse/utils/`)
| File | Purpose |
| File | Tujuan |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
| `stream.ts` | **SSE Transform Stream**the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. |
| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
| `error.ts` | Pembangunan respons error (format kompatibel-OpenAI), parsing error upstream, ekstraksi waktu percobaan ulang Antigravity dari pesan error, streaming error SSE. |
| `stream.ts` | **SSE Transform Stream**inti streaming saluran pipa. Mode dua: `TRANSLATE` (terjemahan format penuh) dan `PASSTHROUGH` (normalisasi + penggunaan ekstraksi). menyertakan buffering potongan, estimasi penggunaan, pelacakan panjang konten. Encoder/decoder instance per-stream menghindari status bersama. |
| `streamHelpers.ts` | Utilitas SSE tingkat rendah: `parseSSELine` (toleran terhadap spasi), `hasValuableContent` (menyaring potongan kosong untuk OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (serialisasi SSE yang peka format dengan pembersihan `perf_metrics`). |
| `usageTracking.ts` | Ekstraksi penggunaan token dari format apa pun (Claude/OpenAI/Gemini/Responses), estimasi dengan rasio karakter-per-token terpisah untuk tool/pesan, penambahan buffer (margin keamanan 2000 token), pemfilteran field spesifik-format, pencatatan konsol dengan warna ANSI. |
| `requestLogger.ts` | Pembantu pencatatan permintaan berbasis file lawas yang dipertahankan untuk kompatibilitas. Deployment saat ini sebaiknya menggunakan `APP_LOG_TO_FILE` untuk log aplikasi dan pipeline log panggilan untuk artefak permintaan yang dipersistensikan. |
| `bypassHandler.ts` | Mengintersep pola tertentu dari Claude CLI (ekstraksi judul, pemanasan, penghitungan) dan mengembalikan respons palsu tanpa memanggil penyedia apa pun. Mendukung streaming maupun non-streaming. Sengaja dibatasi hanya untuk cakupan Claude CLI. |
| `networkProxy.ts` | Me-resolve URL proxy keluar untuk penyedia tertentu dengan urutan prioritas: konfigurasi spesifik-penyedia → konfigurasi global → variabel lingkungan (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Mendukung pengecualian `NO_PROXY`. Menyimpan cache konfigurasi selama 30d. |
#### SSE Streaming Pipeline
#### SSE Streaming Saluran Pipa
```mermaid
flowchart TD
@@ -431,127 +431,127 @@ flowchart TD
style M fill:#9f9,stroke:#333
```
#### Request Logger Session Structure
#### Struktur Sesi Permintaan Logger
```
logs/
└── claude_gemini_claude-sonnet_20260208_143045/
├── 1_req_client.json ← Raw client request
├── 2_req_source.json ← After initial conversion
├── 3_req_openai.json ← OpenAI intermediate format
├── 4_req_target.json ← Final target format
├── 5_res_provider.txt ← Provider SSE chunks (streaming)
├── 5_res_provider.json ← Provider response (non-streaming)
├── 6_res_openai.txt ← OpenAI intermediate chunks
├── 7_res_client.txt ← Client-facing SSE chunks
└── 6_error.json ← Error details (if any)
├── 1_req_client.json ← Permintaan klien mentah
├── 2_req_source.json ← Setelah konversi awal
├── 3_req_openai.json ← Format perantara OpenAI
├── 4_req_target.json ← Format target akhir
├── 5_res_provider.txt ← Potongan SSE penyedia (streaming)
├── 5_res_provider.json ← Respons penyedia (non-streaming)
├── 6_res_openai.txt ← Potongan perantara OpenAI
├── 7_res_client.txt ← Potongan SSE yang menghadap klien
└── 6_error.json ← Detail error (jika ada)
```
---
### 4.7 Application Layer (`src/`)
### 4.7 Lapisan Aplikasi (`src/`)
| Directory | Purpose |
| ------------- | ---------------------------------------------------------------------- |
| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
| `src/models/` | Database model definitions |
| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
| `src/store/` | Application state management |
| Direktori | Tujuan |
| ------------- | ------------------------------------------------------------------------------- |
| `src/app/` | Antarmuka web, rute API, middleware Express, handler callback OAuth |
| `src/lib/` | Akses database (`localDb.ts`, `usageDb.ts`), autentikasi, kode bersama |
| `src/mitm/` | Utilitas proxy man-in-the-middle untuk mengintersep lalu lintas penyedia |
| `src/models/` | Definisi model basis data |
| `src/shared/` | Wrapper fungsi open-sse (penyedia, stream, error, dll.) |
| `src/sse/` | Handler endpoint SSE yang menghubungkan library open-sse ke rute Express |
| `src/store/` | Manajemen state aplikasi |
#### Notable API Routes
#### Rute API Penting
| Route | Methods | Purpose |
| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
| `/api/sessions` | GET | Active session tracking and metrics |
| `/api/rate-limits` | GET | Per-account rate limit status |
| Rute | Metode | Tujuan |
| --------------------------------------------- | --------------- | ---------------------------------------------------------------------------------------- |
| `/api/provider-models` | GET/POST/DELETE | CRUD untuk model kustom per penyedia |
| `/api/models/catalog` | GET | Katalog gabungan semua model (chat, embedding, gambar, kustom) yang dikelompokkan per penyedia |
| `/api/settings/proxy` | GET/PUT/DELETE | Konfigurasi proxy keluar hierarkis (`global/providers/combos/keys`) |
| `/api/settings/proxy/test` | POST | Memvalidasi konektivitas proxy dan mengembalikan IP publik/latensi |
| `/v1/providers/[provider]/chat/completions` | POST | Chat completions khusus per-penyedia dengan validasi model |
| `/v1/providers/[provider]/embeddings` | POST | Embedding khusus per-penyedia dengan validasi model |
| `/v1/providers/[provider]/images/generations` | POST | Pembuatan gambar khusus per-penyedia dengan validasi model |
| `/api/settings/ip-filter` | GET/PUT | Manajemen allowlist/blocklist IP |
| `/api/settings/thinking-budget` | GET/PUT | Konfigurasi anggaran token penalaran (passthrough/auto/custom/adaptive) |
| `/api/settings/system-prompt` | GET/PUT | Injeksi system prompt global untuk semua permintaan |
| `/api/sessions` | GET | Pelacakan sesi aktif dan metrik |
| `/api/rate-limits` | GET | Status batas laju per-akun |
---
## 5. Key Design Patterns
## 5. Pola Desain Utama
### 5.1 Hub-and-Spoke Translation
### 5.1 Terjemahan Hub-and-Spoke
All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
Semua format diterjemahkan melalui **format OpenAI sebagai hub**. Menambahkan penyedia baru hanya membutuhkan penulisan **satu pasang** penerjemah (ke/dari OpenAI), bukan N pasangan.
### 5.2 Executor Strategy Pattern
### 5.2 Strategy Pattern pada Executor
Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
Setiap penyedia memiliki kelas executor khusus yang mewarisi dari `BaseExecutor`. Factory di `executors/index.ts` memilih yang tepat saat runtime.
### 5.3 Self-Registering Plugin System
### 5.3 Sistem Plugin Pendaftaran-Diri
Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
Modul penerjemah mendaftarkan diri saat diimpor melalui `register()`. Menambahkan penerjemah baru cukup dengan membuat file dan mengimpornya.
### 5.4 Account Fallback with Exponential Backoff
### 5.4 Fallback Akun dengan Backoff Eksponensial
When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
Ketika penyedia mengembalikan 429/401/500, sistem dapat beralih ke akun berikutnya, menerapkan cooldown eksponensial (1d → 2d → 4d → maks 2min).
### 5.5 Combo Model Chains
### 5.5 Model Rantai Kombo
A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
Sebuah "combo" mengelompokkan beberapa string `provider/model`. Jika yang pertama gagal, otomatis beralih ke berikutnya.
### 5.6 Stateful Streaming Translation
### 5.6 Terjemahan Streaming dengan State
Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
Terjemahan respons mempertahankan state di seluruh potongan SSE (pelacakan blok berpikir, akumulasi tool call, pengindeksan blok konten) melalui mekanisme `initState()`.
### 5.7 Usage Safety Buffer
### 5.7 Buffer Keamanan Penggunaan
A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
Buffer 2000 token ditambahkan ke penggunaan yang dilaporkan untuk mencegah klien mencapai batas jendela konteks akibat overhead dari system prompt dan terjemahan format.
---
## 6. Supported Formats
## 6. Format yang Didukung
| Format | Direction | Identifier |
| Format | Arah | Identifier |
| ----------------------- | --------------- | ------------------ |
| OpenAI Chat Completions | source + target | `openai` |
| OpenAI Responses API | source + target | `openai-responses` |
| Anthropic Claude | source + target | `claude` |
| Google Gemini | source + target | `gemini` |
| Google Gemini CLI | target only | `gemini-cli` |
| Antigravity | source + target | `antigravity` |
| AWS Kiro | target only | `kiro` |
| Cursor | target only | `cursor` |
| OpenAI Chat Completions | sumber + target | `openai` |
| API Respons OpenAI | sumber + target | `openai-responses` |
| Anthropic Claude | sumber + target | `claude` |
| Google Gemini | sumber + target | `gemini` |
| Google Gemini CLI | target saja | `gemini-cli` |
| Antigravity | sumber + target | `antigravity` |
| AWS Kiro | target saja | `kiro` |
| Cursor | target saja | `cursor` |
---
## 7. Supported Providers
## 7. Penyedia yang Didukung
| Provider | Auth Method | Executor | Key Notes |
| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
| OpenAI | API key | Default | Standard Bearer auth |
| Codex | OAuth | Codex | Injects system instructions, manages thinking |
| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
| Qwen | OAuth | Default | Standard auth |
| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
| OpenRouter | API key | Default | Standard Bearer auth |
| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
| Penyedia | Metode Autentikasi | Executor | Catatan Utama |
| ------------------------ | ---------------------- | ----------- | ----------------------------------------------------- |
| Anthropic Claude | Kunci API atau OAuth | Default | Menggunakan header `x-api-key` |
| Google Gemini | Kunci API atau OAuth | Default | Menggunakan header `x-goog-api-key` |
| Google Gemini CLI | OAuth | GeminiCLI | Menggunakan endpoint `streamGenerateContent` |
| Antigravity | OAuth | Antigravity | Penggantian multi-URL, penguraian percobaan ulang kustom |
| OpenAI | API key | Default | Autentikasi Bearer standar |
| Codex | OAuth | Codex | Menyuntikkan instruksi sistem, mengelola berpikir |
| GitHub Copilot | OAuth + token Copilot | Github | Token ganda, peniruan header VSCode |
| Kiro (AWS) | AWS SSO OIDC atau Social | Kiro | Parsing binary EventStream |
| Cursor IDE | Autentikasi checksum | Cursor | Encoding Protobuf, checksum SHA-256 |
| Qwen | OAuth | Default | Autentikasi standar |
| Qoder | OAuth (Basic + Bearer) | Default | Autentikasi header ganda|
| OpenRouter | API key | Default | Autentikasi Bearer standar |
| GLM, Kimi, MiniMax | API key | Default | Kompatibel-Claude, menggunakan `x-api-key` |
| `openai-compatible-*` | API key | Default |Dinamis: endpoint kompatibel-OpenAI apa pun |
| `anthropic-compatible-*` | API key | Default | Dinamis: endpoint kompatibel-Claude apa pun |
---
## 8. Data Flow Summary
## 8. Ringkasan Alur Data
### Streaming Request
### Permintaan Streaming
```mermaid
flowchart LR
@@ -568,7 +568,7 @@ flowchart LR
K --> L["logUsage()\nsaveRequestUsage()"]
```
### Non-Streaming Request
### Permintaan Non-Streaming
```mermaid
flowchart LR
@@ -579,12 +579,12 @@ flowchart LR
E --> F["Return JSON\nresponse"]
```
### Bypass Flow (Claude CLI)
### Alur Bypass (Claude CLI)
```mermaid
flowchart LR
A["Claude CLI request"] --> B{"Match bypass\npattern?"}
B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
B -->|"Title/Warmup/Count"| C["Buat respons palsu\nOpenAI"]
B -->|"No match"| D["Normal flow"]
C --> E["Translate to\nsource format"]
E --> F["Return without\ncalling provider"]

View File

@@ -1,106 +1,106 @@
# Guia Completo: Cloudflare Tunnel & Zero Trust (Split-Port) (Bahasa Indonesia)
# Panduan Lengkap: Cloudflare Tunnel & Zero Trust (Split-Port) (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/cloudflare-zero-trust-guide.md) · 🇪🇸 [es](../../es/docs/cloudflare-zero-trust-guide.md) · 🇫🇷 [fr](../../fr/docs/cloudflare-zero-trust-guide.md) · 🇩🇪 [de](../../de/docs/cloudflare-zero-trust-guide.md) · 🇮🇹 [it](../../it/docs/cloudflare-zero-trust-guide.md) · 🇷🇺 [ru](../../ru/docs/cloudflare-zero-trust-guide.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/cloudflare-zero-trust-guide.md) · 🇯🇵 [ja](../../ja/docs/cloudflare-zero-trust-guide.md) · 🇰🇷 [ko](../../ko/docs/cloudflare-zero-trust-guide.md) · 🇸🇦 [ar](../../ar/docs/cloudflare-zero-trust-guide.md) · 🇮🇳 [hi](../../hi/docs/cloudflare-zero-trust-guide.md) · 🇮🇳 [in](../../in/docs/cloudflare-zero-trust-guide.md) · 🇹🇭 [th](../../th/docs/cloudflare-zero-trust-guide.md) · 🇻🇳 [vi](../../vi/docs/cloudflare-zero-trust-guide.md) · 🇮🇩 [id](../../id/docs/cloudflare-zero-trust-guide.md) · 🇲🇾 [ms](../../ms/docs/cloudflare-zero-trust-guide.md) · 🇳🇱 [nl](../../nl/docs/cloudflare-zero-trust-guide.md) · 🇵🇱 [pl](../../pl/docs/cloudflare-zero-trust-guide.md) · 🇸🇪 [sv](../../sv/docs/cloudflare-zero-trust-guide.md) · 🇳🇴 [no](../../no/docs/cloudflare-zero-trust-guide.md) · 🇩🇰 [da](../../da/docs/cloudflare-zero-trust-guide.md) · 🇫🇮 [fi](../../fi/docs/cloudflare-zero-trust-guide.md) · 🇵🇹 [pt](../../pt/docs/cloudflare-zero-trust-guide.md) · 🇷🇴 [ro](../../ro/docs/cloudflare-zero-trust-guide.md) · 🇭🇺 [hu](../../hu/docs/cloudflare-zero-trust-guide.md) · 🇧🇬 [bg](../../bg/docs/cloudflare-zero-trust-guide.md) · 🇸🇰 [sk](../../sk/docs/cloudflare-zero-trust-guide.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/cloudflare-zero-trust-guide.md) · 🇮🇱 [he](../../he/docs/cloudflare-zero-trust-guide.md) · 🇵🇭 [phi](../../phi/docs/cloudflare-zero-trust-guide.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/cloudflare-zero-trust-guide.md) · 🇨🇿 [cs](../../cs/docs/cloudflare-zero-trust-guide.md) · 🇹🇷 [tr](../../tr/docs/cloudflare-zero-trust-guide.md)
---
Este guia documenta o padrão ouro de infraestrutura de rede para proteger o **OmniRoute** e expor sua aplicação de forma segura para a internet, **sem abrir nenhuma porta (Zero Inbound)**.
Panduan ini mendokumentasikan standar infrastruktur jaringan terbaik untuk mengamankan **OmniRoute** dan mengekspos aplikasi Anda ke internet secara aman, **tanpa membuka satu pun port (Zero Inbound)**.
## O que foi feito na sua VM?
## Apa yang Telah Dilakukan pada VM Anda?
Nós ativamos o OmniRoute em modo **Split-Port** através do PM2:
Kami mengaktifkan OmniRoute dalam mode **Split-Port** melalui PM2:
- **Porta \`20128\`:** Roda **apenas a API** `/v1`.
- **Porta \`20129\`:** Roda **apenas o Dashboard** Administrativo visual.
- **Port \`20128\`:** Menjalankan **hanya API** `/v1`.
- **Port \`20129\`:** Menjalankan **hanya Dashboard** Administratif visual.
Além disso, o serviço interno exige \`REQUIRE_API_KEY=true\`, o que significa que nenhum agente pode consumir os endpoints da API sem enviar um "Bearer Token" legítimo gerado na aba API Keys do Painel.
Selain itu, layanan internal memerlukan `REQUIRE_API_KEY=true`, yang berarti tidak ada agen yang dapat menggunakan endpoint API tanpa mengirimkan "Bearer Token" yang sah yang dihasilkan dari tab API Keys di Panel.
Isso nos permite criar duas regras completamente independentes na rede. É aqui que entra o **Cloudflare Tunnel (cloudflared)**.
Hal ini memungkinkan kita membuat dua aturan yang sepenuhnya independen di jaringan. Di sinilah peran **Cloudflare Tunnel (cloudflared)**.
---
## 1. Como Criar o Túnel na Cloudflare
## 1. Cara Membuat Terowongan di Cloudflare
O utilitário \`cloudflared\` já está instalado na sua máquina. Siga os passos na nuvem:
Utilitas `cloudflared` sudah terpasang di mesin Anda. Ikuti langkah-langkah berikut di cloud:
1. Acesse seu painel **Cloudflare Zero Trust** (One.dash.cloudflare.com).
2. No menu à esquerda, vá em **Networks > Tunnels**.
3. Clique em **Add a Tunnel**, escolha **Cloudflared** e dê o nome \`OmniRoute-VM\`.
4. Ele vai gerar um comando na tela chamado "Install and run a connector". **Você só precisa copiar o Token (a string longa após `--token`)**.
5. Logue via SSH na sua máquina virtual (ou Terminal do Proxmox) e execute:
1. Akses panel **Cloudflare Zero Trust** Anda (One.dash.cloudflare.com).
2. Di menu sebelah kiri, pergi ke **Networks > Tunnels**.
3. Klik **Add a Tunnel**, pilih **Cloudflared**, dan beri nama `OmniRoute-VM`.
4. Sistem akan menghasilkan perintah di layar bernama "Install and run a connector". **Anda hanya perlu menyalin Token (string panjang setelah `--token`)**.
5. Masuk melalui SSH ke mesin virtual Anda (atau Terminal Proxmox) dan jalankan:
\`\`\`bash
# Inicia e amarra o túnel permanentemente à sua conta
cloudflared service install SEU_TOKEN_GIGANTE_AQUI
# Memulai dan mengikat terowongan secara permanen ke akun Anda
cloudflared service install TOKEN_PANJANG_ANDA_DI_SINI
\`\`\`
---
## 2. Configurando o Roteamento (Public Hostnames)
## 2. Mengonfigurasi Perutean (Public Hostnames)
Ainda na tela do Tunnel recém-criado, vá para a aba **Public Hostnames** e adicione as **duas** rotas, aproveitando a separação que fizemos:
Masih di layar Tunnel yang baru dibuat, buka tab **Public Hostnames** dan tambahkan **dua** rute, memanfaatkan pemisahan yang telah kita lakukan:
### Rota 1: API Segura (Limitada)
### Rute 1: API Aman (Terbatas)
- **Subdomain:** \`api\`
- **Domain:** \`seuglobal.com.br\` (escolha seu domínio real)
- **Service Type:** \`HTTP\`
- **URL:** \`127.0.0.1:20128\` _(Porta interna da API)_
- **Subdomain:** `api`
- **Domain:** `domainanda.com` (pilih domain nyata Anda)
- **Service Type:** `HTTP`
- **URL:** `127.0.0.1:20128` _(Port internal API)_
### Rota 2: Painel Zero Trust (Fechado)
### Rute 2: Panel Zero Trust (Tertutup)
- **Subdomain:** \`omniroute\` ou \`painel\`
- **Domain:** \`seuglobal.com.br\`
- **Service Type:** \`HTTP\`
- **URL:** \`127.0.0.1:20129\` _(Porta interna do App/Visual)_
- **Subdomain:** `omniroute` atau `panel`
- **Domain:** `domainanda.com`
- **Service Type:** `HTTP`
- **URL:** `127.0.0.1:20129` _(Port internal App/Visual)_
Neste momento, a conectividade "Física" está resolvida. Agora vamos blindar de verdade.
Pada titik ini, konektivitas "fisik" telah terselesaikan. Sekarang kita akan benar-benar mengamankannya.
---
## 3. Blindando o Painel com Zero Trust (Access)
## 3. Mengamankan Panel dengan Zero Trust (Access)
Nenhuma senha local protege melhor o seu painel do que remover totalmente o acesso a ele da internet aberta.
Tidak ada kata sandi lokal yang lebih baik dalam melindungi panel Anda selain menghapus sepenuhnya akses ke panel tersebut dari internet terbuka.
1. No painel Zero Trust, vá em **Access > Applications > Add an application**.
2. Selecione **Self-hosted**.
3. Em **Application name**, coloque \`Painel OmniRoute\`.
4. Em **Application domain**, coloque \`omniroute.seuglobal.com.br\` (O mesmo que você fez na "Rota 2").
5. Clique em **Next**.
6. Em **Rule action**, escolha \`Allow\`. Em nome da Rule coloque \`Admin Apenas\`.
7. Em **Include**, no seletor de "Selector" escolha \`Emails\` e digite o seu email, por exemplo \`admin@spgeo.com.br\`.
8. Salve (`Add application`).
1. Di panel Zero Trust, buka **Access > Applications > Add an application**.
2. Pilih **Self-hosted**.
3. Di **Application name**, masukkan `Panel OmniRoute`.
4. Di **Application domain**, masukkan `omniroute.domainanda.com` (sama dengan yang Anda buat di "Rute 2").
5. Klik **Next**.
6. Di **Rule action**, pilih `Allow`. Beri nama Rule `Admin Saja`.
7. Di **Include**, pada selektor "Selector" pilih `Emails` dan masukkan email Anda, misalnya `admin@domainanda.com`.
8. Simpan (`Add application`).
> **O que isso fez:** Se você tentar abrir \`omniroute.seuglobal.com.br\`, não cai mais na sua aplicação OmniRoute! Cai numa tela elegante da Cloudflare pedindo para digitar seu email. Somente se você (ou o email que você botou) for digitado lá, ele recebe no Outlook/Gmail um código de 6 dígitos temporário que libera o túnel até a porta \`20129\`.
> **Apa yang terjadi:** Jika Anda mencoba membuka `omniroute.domainanda.com`, Anda tidak akan langsung masuk ke aplikasi OmniRoute! Anda akan disambut halaman Cloudflare yang meminta Anda memasukkan email. Hanya jika email yang Anda masukkan cocok, Anda akan menerima kode sementara 6 digit melalui Outlook/Gmail yang membuka akses ke terowongan menuju port `20129`.
---
## 4. Limitando e Protegendo a API com Rate Limit (WAF)
## 4. Membatasi dan Melindungi API dengan Rate Limit (WAF)
O Dashboard do Zero Trust não se aplica à rota da API (\`api.seuglobal.com.br\`), porque é um acesso programático via ferramentas automatizadas (agentes) sem navegador. Para ele, usaremos o Firewall principal (WAF) da Cloudflare.
Dashboard Zero Trust tidak berlaku untuk rute API (`api.domainanda.com`), karena ini adalah akses terprogram melalui alat otomatis (agen) tanpa browser. Untuk ini, kita akan menggunakan Firewall utama (WAF) Cloudflare.
1. Acesse o **Painel Normal** da Cloudflare (dash.cloudflare.com) e entre no seu Domínio.
2. No menu esquerdo, vá em **Security > WAF > Rate limiting rules**.
3. Clique em **Create rule**.
4. **Name:** \`Anti-Abuso OmniRoute API\`
1. Akses **Panel Normal** Cloudflare (dash.cloudflare.com) dan masuk ke Domain Anda.
2. Di menu sebelah kiri, buka **Security > WAF > Rate limiting rules**.
3. Klik **Create rule**.
4. **Name:** `Anti-Penyalahgunaan OmniRoute API`
5. **If incoming requests match...**
- Escolha em Field: \`Hostname\`
- Operator: \`equals\`
- Value: \`api.seuglobal.com.br\`
6. Em **With the same characteristics:** Mantenha \`IP\`.
7. Nos limites (Limit):
- **When requests exceed:** \`50\`
- **Period:** \`1 minute\`
8. No final, em **Action**: \`Block\` (Bloquear) e decida se o bloqueio dura por 1 minuto ou 1 hora.
- Pilih di Field: `Hostname`
- Operator: `equals`
- Value: `api.domainanda.com`
6. Di **With the same characteristics:** Pertahankan `IP`.
7. Pada batas (Limit):
- **When requests exceed:** `50`
- **Period:** `1 minute`
8. Di bagian bawah, pada **Action**: `Block` (Blokir) dan tentukan apakah pemblokiran berlangsung 1 menit atau 1 jam.
9. **Deploy**.
> **O que isso fez:** Ninguém pode mandar mais de 50 requisições num período de 60 segundos na sua URL de API. Como você roda vários agentes e os consumos por trás já batem rate limit e já rastreiam tokens, isso é apenas uma medida na Borda da Internet (Edge Layer) que protege sua Instância On-Premises de cair por estresse térmico antes mesmo do tráfego descer pelo túnel.
> **Apa yang terjadi:** Tidak ada yang dapat mengirim lebih dari 50 permintaan dalam periode 60 detik ke URL API Anda. Karena Anda menjalankan beberapa agen dan konsumsi di belakangnya sudah mencapai batas laju serta melacak token, ini hanyalah langkah pengamanan di lapisan tepi internet (Edge Layer) yang melindungi instans On-Premises Anda dari kelebihan beban bahkan sebelum trafik melewati terowongan.
---
## Finalização
## Penutup
1. A sua VM **não possui nenhuma porta exposta** em `/etc/ufw`.
2. O OmniRoute só conversa HTTPS saindo (\`cloudflared\`) e não recebendo TCP direto do mundo.
3. Seus requets pro OpenAI são ofuscados porque configuramos eles globalmente pra passar em um Proxy SOCKS5 (A nuvem não liga pro SOCKS5 porque ela vem Inbound).
4. Seu painel web tem 2-Factor com Email.
5. Sua API está ratelimitada na borda pela Cloudflare e só trafega Bearer Tokens.
1. VM Anda **tidak memiliki port yang terbuka** di `/etc/ufw`.
2. OmniRoute hanya berkomunikasi melalui HTTPS keluar (`cloudflared`) dan tidak menerima koneksi TCP langsung dari internet.
3. Permintaan Anda ke OpenAI disamarkan karena dikonfigurasi secara global untuk melewati Proxy SOCKS5 (cloud tidak peduli dengan SOCKS5 karena trafik datang secara Inbound).
4. Panel web Anda memiliki autentikasi 2 faktor melalui Email.
5. API Anda dibatasi lajunya di tepi jaringan oleh Cloudflare dan hanya menerima lalu lintas Bearer Token.

View File

@@ -1,65 +1,65 @@
# Context Relay (Bahasa Indonesia)
# Context Relay
🌐 **Languages:** 🇺🇸 [English](../../../../../docs/features/context-relay.md) · 🇪🇸 [es](../../../es/docs/features/context-relay.md) · 🇫🇷 [fr](../../../fr/docs/features/context-relay.md) · 🇩🇪 [de](../../../de/docs/features/context-relay.md) · 🇮🇹 [it](../../../it/docs/features/context-relay.md) · 🇷🇺 [ru](../../../ru/docs/features/context-relay.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/features/context-relay.md) · 🇯🇵 [ja](../../../ja/docs/features/context-relay.md) · 🇰🇷 [ko](../../../ko/docs/features/context-relay.md) · 🇸🇦 [ar](../../../ar/docs/features/context-relay.md) · 🇮🇳 [hi](../../../hi/docs/features/context-relay.md) · 🇮🇳 [in](../../../in/docs/features/context-relay.md) · 🇹🇭 [th](../../../th/docs/features/context-relay.md) · 🇻🇳 [vi](../../../vi/docs/features/context-relay.md) · 🇮🇩 [id](../../../id/docs/features/context-relay.md) · 🇲🇾 [ms](../../../ms/docs/features/context-relay.md) · 🇳🇱 [nl](../../../nl/docs/features/context-relay.md) · 🇵🇱 [pl](../../../pl/docs/features/context-relay.md) · 🇸🇪 [sv](../../../sv/docs/features/context-relay.md) · 🇳🇴 [no](../../../no/docs/features/context-relay.md) · 🇩🇰 [da](../../../da/docs/features/context-relay.md) · 🇫🇮 [fi](../../../fi/docs/features/context-relay.md) · 🇵🇹 [pt](../../../pt/docs/features/context-relay.md) · 🇷🇴 [ro](../../../ro/docs/features/context-relay.md) · 🇭🇺 [hu](../../../hu/docs/features/context-relay.md) · 🇧🇬 [bg](../../../bg/docs/features/context-relay.md) · 🇸🇰 [sk](../../../sk/docs/features/context-relay.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/features/context-relay.md) · 🇮🇱 [he](../../../he/docs/features/context-relay.md) · 🇵🇭 [phi](../../../phi/docs/features/context-relay.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/features/context-relay.md) · 🇨🇿 [cs](../../../cs/docs/features/context-relay.md) · 🇹🇷 [tr](../../../tr/docs/features/context-relay.md)
---
`context-relay` is a combo strategy that keeps session continuity when the active account
rotates before the conversation is finished.
`context-relay` adalah strategi combo yang menjaga kesinambungan sesi ketika akun aktif
berputar sebelum percakapan selesai.
The current runtime behaves like priority routing for model selection, then adds a
handoff layer on top:
Runtime saat ini berperilaku seperti routing prioritas untuk pemilihan model, kemudian menambahkan
lapisan handoff di atasnya:
- before the active account is exhausted, OmniRoute generates a compact structured summary
- after authentication selects a different account for the same session, OmniRoute injects
that summary as a system message into the next request
- once the handoff is consumed successfully, it is removed from storage
- sebelum akun aktif habis, OmniRoute menghasilkan ringkasan terstruktur yang ringkas
- setelah autentikasi memilih akun berbeda untuk sesi yang sama, OmniRoute menyuntikkan
ringkasan tersebut sebagai pesan sistem ke dalam permintaan berikutnya
- setelah handoff berhasil dikonsumsi, handoff tersebut dihapus dari penyimpanan
## When To Use It
## Kapan Menggunakannya
Use `context-relay` when all of the following are true:
Gunakan `context-relay` ketika semua kondisi berikut terpenuhi:
- the combo is expected to rotate between multiple accounts of the same provider
- losing short-term conversational continuity would hurt task quality
- the provider exposes enough quota information to predict an approaching account limit
- combo diharapkan berputar di antara beberapa akun dari penyedia yang sama
- kehilangan kesinambungan percakapan jangka pendek akan mengurangi kualitas tugas
- penyedia mengekspos informasi kuota yang cukup untuk memprediksi batas akun yang akan datang
This is most useful for long-running coding or research sessions that may outlive a single
account window.
Ini paling berguna untuk sesi coding atau riset yang berjalan lama yang mungkin melampaui satu
jendela akun.
## Runtime Flow
## Alur Runtime
The current behavior is intentionally split across two runtime layers.
Perilaku saat ini secara sengaja dibagi ke dalam dua lapisan runtime.
### 0% to 84% quota used
### 0% hingga 84% kuota terpakai
No handoff is generated. Requests behave like normal priority routing.
Tidak ada handoff yang dihasilkan. Permintaan berperilaku seperti routing prioritas normal.
### 85% to 94% quota used
### 85% hingga 94% kuota terpakai
If the active provider is enabled in `handoffProviders`, OmniRoute generates a structured
handoff summary in the background before the account is fully exhausted.
Jika penyedia aktif diaktifkan di `handoffProviders`, OmniRoute menghasilkan ringkasan handoff
terstruktur di latar belakang sebelum akun habis sepenuhnya.
Important details:
Detail penting:
- the default warning threshold is `0.85`
- the hard stop for generation is `0.95`
- only one in-flight handoff generation is allowed per `sessionId + comboName`
- if an active handoff already exists for that session/combo, no duplicate summary is generated
- ambang batas peringatan default adalah `0.85`
- batas keras untuk pembuatan adalah `0.95`
- hanya satu pembuatan handoff yang sedang berjalan yang diizinkan per `sessionId + comboName`
- jika handoff aktif sudah ada untuk sesi/combo tersebut, tidak ada ringkasan duplikat yang dihasilkan
### 95% or more quota used
### 95% atau lebih kuota terpakai
No new handoff is generated. At this point the system is already in or near exhaustion and
the runtime avoids scheduling another summary request.
Tidak ada handoff baru yang dihasilkan. Pada titik ini sistem sudah berada dalam kondisi habis atau
mendekati habis dan runtime menghindari penjadwalan permintaan ringkasan lain.
### After account rotation
### Setelah rotasi akun
When the next request for the same session resolves to a different authenticated account,
OmniRoute prepends the stored handoff as a system message. Injection happens only after the
real account switch is known.
Ketika permintaan berikutnya untuk sesi yang sama menghasilkan akun terautentikasi yang berbeda,
OmniRoute menambahkan handoff yang tersimpan sebagai pesan sistem. Penyuntikan hanya terjadi setelah
pergantian akun nyata diketahui.
## Handoff Payload
## Muatan Handoff
The persisted handoff payload is stored in `context_handoffs` and includes:
Muatan handoff yang dipersistenkan disimpan di `context_handoffs` dan mencakup:
- `sessionId`
- `comboName`
@@ -74,7 +74,7 @@ The persisted handoff payload is stored in `context_handoffs` and includes:
- `generatedAt`
- `expiresAt`
The summary model is instructed to return a JSON object with this structure:
Model ringkasan diperintahkan untuk mengembalikan objek JSON dengan struktur berikut:
```json
{
@@ -85,46 +85,46 @@ The summary model is instructed to return a JSON object with this structure:
}
```
At injection time, OmniRoute converts that payload into a `<context_handoff>` system
message so the next account can continue with the correct local context.
Pada saat penyuntikan, OmniRoute mengonversi muatan tersebut menjadi pesan sistem `<context_handoff>`
agar akun berikutnya dapat melanjutkan dengan konteks lokal yang benar.
## Konfigurasi
`context-relay` supports these config fields:
`context-relay` mendukung kolom konfigurasi berikut:
- `handoffThreshold`: warning threshold for summary generation, default `0.85`
- `handoffModel`: optional model override used only for summary generation
- `handoffProviders`: allowlist of providers allowed to trigger handoff generation
- `handoffThreshold`: ambang batas peringatan untuk pembuatan ringkasan, default `0.85`
- `handoffModel`: penggantian model opsional yang hanya digunakan untuk pembuatan ringkasan
- `handoffProviders`: daftar izin penyedia yang diperbolehkan memicu pembuatan handoff
Global defaults can be configured in Settings, and combo-specific values can override them
in the Combos page.
Nilai default global dapat dikonfigurasi di Pengaturan, dan nilai spesifik combo dapat menggantikannya
di halaman Combos.
## Architectural Note
## Catatan Arsitektur
The current implementation does not use a standalone `handleContextRelayCombo` handler.
Implementasi saat ini tidak menggunakan pengendali `handleContextRelayCombo` yang berdiri sendiri.
Instead:
Sebaliknya:
- `open-sse/services/combo.ts` decides whether a successful turn should generate a handoff
- `src/sse/handlers/chat.ts` injects the handoff only after authentication resolves the
actual account used for the request
- `open-sse/services/combo.ts` memutuskan apakah giliran yang berhasil harus menghasilkan handoff
- `src/sse/handlers/chat.ts` menyuntikkan handoff hanya setelah autentikasi menyelesaikan
akun aktual yang digunakan untuk permintaan
This split is intentional in the current codebase because the combo loop alone does not know
whether the request stayed on the same account or actually switched accounts.
Pemisahan ini disengaja dalam basis kode saat ini karena loop combo saja tidak mengetahui
apakah permintaan tetap pada akun yang sama atau benar-benar berpindah akun.
## Limitations
## Keterbatasan
- Effective runtime support is currently centered on `codex` quota rotation.
- `handoffProviders` is already modeled as a config surface, but real handoff generation
still depends on provider-specific quota plumbing.
- The summary is intentionally compact and recent-history based; it is not a full transcript
replay mechanism.
- Handoffs are scoped by `sessionId + comboName` and expire automatically.
- If the session does not switch accounts, the stored handoff is not injected.
- Dukungan runtime yang efektif saat ini terpusat pada rotasi kuota `codex`.
- `handoffProviders` sudah dimodelkan sebagai permukaan konfigurasi, tetapi pembuatan handoff
nyata masih bergantung pada jalur kuota spesifik penyedia.
- Ringkasan secara sengaja dibuat ringkas dan berbasis riwayat terkini; ini bukan mekanisme
pemutaran ulang transkrip penuh.
- Handoff dicakupkan oleh `sessionId + comboName` dan kedaluwarsa secara otomatis.
- Jika sesi tidak berpindah akun, handoff yang tersimpan tidak disuntikkan.
## Recommended Usage Pattern
## Pola Penggunaan yang Disarankan
- use multiple accounts from the same provider
- keep stable `sessionId` values across the session
- set `handoffThreshold` early enough to leave room for the background summary request
- treat the feature as continuity assistance, not as a replacement for persistent memory
- gunakan beberapa akun dari penyedia yang sama
- pertahankan nilai `sessionId` yang stabil sepanjang sesi
- atur `handoffThreshold` cukup awal untuk menyisakan ruang bagi permintaan ringkasan latar belakang
- perlakukan fitur ini sebagai bantuan kesinambungan, bukan sebagai pengganti memori persisten

View File

@@ -1,38 +1,38 @@
# OmniRoute A2A Server Documentation (Bahasa Indonesia)
# Dokumentasi Server A2A OmniRoute (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇧🇩 [bn](../../bn/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇮🇷 [fa](../../fa/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇮🇳 [gu](../../gu/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇮🇳 [hi](../../hi/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇮🇳 [mr](../../mr/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇰🇪 [sw](../../sw/docs/A2A-SERVER.md) · 🇮🇳 [ta](../../ta/docs/A2A-SERVER.md) · 🇮🇳 [te](../../te/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇹🇷 [tr](../../tr/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇵🇰 [ur](../../ur/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md)
---
> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
> Protokol Agent-to-Agent v0.3 — OmniRoute sebagai agen routing cerdas
## Agent Discovery
## Penemuan Agen
```bash
curl http://localhost:20128/.well-known/agent.json
```
Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
Mengembalikan Kartu Agen yang mendeskripsikan kemampuan, keterampilan, dan persyaratan autentikasi OmniRoute.
---
## Authentication
## Autentikasi
All `/a2a` requests require an API key via the `Authorization` header:
Semua permintaan `/a2a` memerlukan kunci API melalui header `Authorization`:
```
Authorization: Bearer YOUR_OMNIROUTE_API_KEY
```
If no API key is configured on the server, authentication is bypassed.
Jika tidak ada kunci API yang dikonfigurasi di server, autentikasi akan dilewati.
---
## JSON-RPC 2.0 Methods
## Metode JSON-RPC 2.0
### `message/send` — Synchronous Execution
### `message/send` — Eksekusi Sinkron
Sends a message to a skill and waits for the complete response.
Mengirim pesan ke sebuah keterampilan dan menunggu respons lengkap.
```bash
curl -X POST http://localhost:20128/a2a \
@@ -50,7 +50,7 @@ curl -X POST http://localhost:20128/a2a \
}'
```
**Response:**
**Respons:**
```json
{
@@ -71,9 +71,9 @@ curl -X POST http://localhost:20128/a2a \
}
```
### `message/stream` — SSE Streaming
### `message/stream` — Streaming SSE
Same as `message/send` but returns Server-Sent Events for real-time streaming.
Sama seperti `message/send` tetapi mengembalikan Server-Sent Events untuk streaming secara real-time.
```bash
curl -N -X POST http://localhost:20128/a2a \
@@ -90,7 +90,7 @@ curl -N -X POST http://localhost:20128/a2a \
}'
```
**SSE Events:**
**Event SSE:**
```
data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
@@ -100,7 +100,7 @@ data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","s
data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
```
### `tasks/get` — Query Task Status
### `tasks/get` — Kueri Status Tugas
```bash
curl -X POST http://localhost:20128/a2a \
@@ -109,7 +109,7 @@ curl -X POST http://localhost:20128/a2a \
-d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
```
### `tasks/cancel` — Cancel a Task
### `tasks/cancel` — Batalkan Sebuah Tugas
```bash
curl -X POST http://localhost:20128/a2a \
@@ -120,16 +120,16 @@ curl -X POST http://localhost:20128/a2a \
---
## Available Skills
## Keterampilan yang Tersedia
| Skill | Description |
| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
| Keterampilan | Deskripsi |
| :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `smart-routing` | Merutekan prompt melalui pipeline cerdas OmniRoute. Mengembalikan respons beserta penjelasan routing, biaya, dan jejak ketahanan. |
| `quota-management` | Menjawab kueri bahasa alami tentang kuota penyedia, menyarankan combo gratis, dan memberikan peringkat kuota. |
---
## Task Lifecycle
## Siklus Hidup Tugas
```
submitted → working → completed
@@ -137,25 +137,25 @@ submitted → working → completed
→ cancelled
```
- Tasks expire after 5 minutes (configurable)
- Terminal states: `completed`, `failed`, `cancelled`
- Event log tracks every state transition
- Tugas kedaluwarsa setelah 5 menit (dapat dikonfigurasi)
- Status terminal: `completed`, `failed`, `cancelled`
- Log event melacak setiap transisi status
---
## Error Codes
## Kode Kesalahan
| Code | Meaning |
| :----- | :----------------------------- |
| -32700 | Parse error (invalid JSON) |
| -32600 | Invalid request / Unauthorized |
| -32601 | Method or skill not found |
| -32602 | Invalid params |
| -32603 | Internal error |
| Kode | Arti |
| :----- | :-------------------------------------- |
| -32700 | Kesalahan parse (JSON tidak valid) |
| -32600 | Permintaan tidak valid / Tidak diotorisasi |
| -32601 | Metode atau keterampilan tidak ditemukan |
| -32602 | Parameter tidak valid |
| -32603 | Kesalahan internal |
---
## Integration Examples
## Contoh Integrasi
### Python (requests)

View File

@@ -1,63 +1,63 @@
# OmniRoute MCP Server Documentation (Bahasa Indonesia)
# Dokumentasi Server MCP OmniRoute (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇧🇩 [bn](../../bn/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇮🇷 [fa](../../fa/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇮🇳 [gu](../../gu/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇮🇳 [hi](../../hi/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇮🇳 [mr](../../mr/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇰🇪 [sw](../../sw/docs/MCP-SERVER.md) · 🇮🇳 [ta](../../ta/docs/MCP-SERVER.md) · 🇮🇳 [te](../../te/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇹🇷 [tr](../../tr/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇵🇰 [ur](../../ur/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md)
---
> Model Context Protocol server with 16 intelligent tools
> Server Model Context Protocol dengan 16 alat cerdas
## Instal
## Instalasi
OmniRoute MCP is built-in. Start it with:
OmniRoute MCP sudah tersedia secara bawaan. Jalankan dengan:
```bash
omniroute --mcp
```
Or via the open-sse transport:
Atau melalui transport open-sse:
```bash
# HTTP streamable transport (port 20130)
omniroute --dev # MCP auto-starts on /mcp endpoint
```
## IDE Configuration
## Konfigurasi IDE
See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
Lihat [Konfigurasi IDE](integrations/ide-configs.md) untuk pengaturan Antigravity, Cursor, Copilot, dan Claude Desktop.
---
## Essential Tools (8)
## Alat Esensial (8)
| Tool | Description |
| :------------------------------ | :--------------------------------------- |
| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
| `omniroute_list_combos` | All configured combos with models |
| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
| `omniroute_switch_combo` | Switch active combo by ID/name |
| `omniroute_check_quota` | Quota status per provider or all |
| `omniroute_route_request` | Send a chat completion through OmniRoute |
| `omniroute_cost_report` | Cost analytics for a time period |
| `omniroute_list_models_catalog` | Full model catalog with capabilities |
| Alat | Deskripsi |
| :------------------------------ | :---------------------------------------------------------------- |
| `omniroute_get_health` | Kesehatan gateway, pemutus sirkuit, uptime |
| `omniroute_list_combos` | Semua combo yang dikonfigurasi beserta modelnya |
| `omniroute_get_combo_metrics` | Metrik performa untuk combo tertentu |
| `omniroute_switch_combo` | Ganti combo aktif berdasarkan ID/nama |
| `omniroute_check_quota` | Status kuota per penyedia atau semua penyedia |
| `omniroute_route_request` | Kirim penyelesaian chat melalui OmniRoute |
| `omniroute_cost_report` | Analitik biaya untuk periode waktu tertentu |
| `omniroute_list_models_catalog` | Katalog model lengkap beserta kemampuannya |
## Advanced Tools (8)
## Alat Lanjutan (8)
| Tool | Description |
| :--------------------------------- | :---------------------------------------------------------- |
| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
| `omniroute_explain_route` | Explain a past routing decision |
| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
| Alat | Deskripsi |
| :--------------------------------- | :--------------------------------------------------------------------- |
| `omniroute_simulate_route` | Simulasi routing percobaan dengan pohon fallback |
| `omniroute_set_budget_guard` | Anggaran sesi dengan tindakan degrade/block/alert |
| `omniroute_set_resilience_profile` | Terapkan preset conservative/balanced/aggressive |
| `omniroute_test_combo` | Uji langsung semua model dalam combo melalui permintaan upstream nyata |
| `omniroute_get_provider_metrics` | Metrik terperinci untuk satu penyedia |
| `omniroute_best_combo_for_task` | Rekomendasi kesesuaian tugas beserta alternatifnya |
| `omniroute_explain_route` | Jelaskan keputusan routing yang lalu |
| `omniroute_get_session_snapshot` | Status sesi lengkap: biaya, token, kesalahan |
## Authentication
## Autentikasi
MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
Alat MCP diautentikasi melalui lingkup kunci API. Setiap alat memerlukan lingkup tertentu:
| Scope | Tools |
| Lingkup | Alat |
| :------------- | :----------------------------------------------- |
| `read:health` | get_health, get_provider_metrics |
| `read:combos` | list_combos, get_combo_metrics |
@@ -68,20 +68,20 @@ MCP tools are authenticated via API key scopes. Each tool requires specific scop
| `write:config` | set_budget_guard, set_resilience_profile |
| `read:models` | list_models_catalog, best_combo_for_task |
## Audit Logging
## Pencatatan Audit
Every tool call is logged to `mcp_tool_audit` with:
Setiap pemanggilan alat dicatat ke `mcp_tool_audit` dengan:
- Tool name, arguments, result
- Duration (ms), success/failure
- API key hash, timestamp
- Nama alat, argumen, hasil
- Durasi (ms), berhasil/gagal
- Hash kunci API, cap waktu
## Files
## Berkas
| File | Purpose |
| :------------------------------------------- | :------------------------------------------ |
| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
| `open-sse/mcp-server/auth.ts` | API key + scope validation |
| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
| Berkas | Tujuan |
| :------------------------------------------- | :--------------------------------------------------- |
| `open-sse/mcp-server/server.ts` | Pembuatan server MCP + pendaftaran 16 alat |
| `open-sse/mcp-server/transport.ts` | Transportasi Stdio + HTTP |
| `open-sse/mcp-server/auth.ts` | Validasi kunci API + lingkup |
| `open-sse/mcp-server/audit.ts` | Pencatatan audit pemanggilan alat |
| `open-sse/mcp-server/tools/advancedTools.ts` | 8 pengendali alat lanjutan |

View File

@@ -1,270 +1,270 @@
# OmniRoute — Dashboard Features Gallery (Bahasa Indonesia)
# OmniRoute — Galeri Fitur Dashboard (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇧🇩 [bn](../../bn/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇮🇷 [fa](../../fa/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇮🇳 [gu](../../gu/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇮🇳 [hi](../../hi/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇮🇳 [mr](../../mr/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇰🇪 [sw](../../sw/docs/FEATURES.md) · 🇮🇳 [ta](../../ta/docs/FEATURES.md) · 🇮🇳 [te](../../te/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇹🇷 [tr](../../tr/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇵🇰 [ur](../../ur/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md)
---
Visual guide to every section of the OmniRoute dashboard.
Panduan visual untuk setiap bagian dashboard OmniRoute.
---
## 🔌 Providers
## 🔌 Penyedia
Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
Kelola koneksi penyedia AI: penyedia OAuth (Claude Code, Codex, Gemini CLI), penyedia kunci API (Groq, DeepSeek, OpenRouter), dan penyedia gratis (Qoder, Qwen, Kiro). Akun Kiro menyertakan pelacakan saldo kredit — sisa kredit, total tunjangan, dan tanggal pembaruan terlihat di Dashboard → Penggunaan.
![Providers Dashboard](screenshots/01-providers.png)
---
## 🎨 Combos
## 🎨 Combo
Create model routing combos with 13 strategies: priority, weighted, round-robin, random, least-used, cost-optimized, strict-random, auto, fill-first, p2c, lkgp, context-optimized, and **context-relay**. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
Buat combo routing model dengan 13 strategi: priority, weighted, round-robin, random, least-used, cost-optimized, strict-random, auto, fill-first, p2c, lkgp, context-optimized, dan **context-relay**. Setiap combo menghubungkan beberapa model dengan fallback otomatis dan menyertakan templat cepat serta pemeriksaan kesiapan.
Recent combo improvements:
Peningkatan combo terbaru:
- **Structured combo builder** — create each step by selecting provider, model, and exact account/connection
- **Repeated provider support** — reuse the same provider many times in one combo as long as the `(provider, model, connection)` tuple is unique
- **Combo target health** — analytics and health surfaces now distinguish individual combo targets/steps instead of collapsing everything into model strings
- **Composite tier ordering** — `defaultTier -> fallbackTier` now influences runtime execution/fallback order for top-level combo steps
- **Pembuat combo terstruktur** — buat setiap langkah dengan memilih penyedia, model, dan akun/koneksi yang tepat
- **Dukungan penyedia berulang** — gunakan kembali penyedia yang sama berkali-kali dalam satu combo selama tuple `(provider, model, connection)` bersifat unik
- **Kesehatan target combo** — analitik dan tampilan kesehatan kini membedakan target/langkah combo individual alih-alih menggabungkan semuanya ke dalam string model
- **Urutan tingkatan komposit** — `defaultTier -> fallbackTier` kini memengaruhi urutan eksekusi/fallback saat runtime untuk langkah combo tingkat atas
![Combos Dashboard](screenshots/02-combos.png)
---
## 📊 Analytics
## 📊 Analitik
Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
Analitik penggunaan komprehensif dengan konsumsi token, estimasi biaya, peta panas aktivitas, grafik distribusi mingguan, dan rincian per penyedia.
![Analytics Dashboard](screenshots/03-analytics.png)
---
## 🏥 System Health
## 🏥 Kesehatan Sistem
Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, provider circuit breaker states, active quota-monitored sessions, and combo target health.
Pemantauan real-time: uptime, memori, versi, persentil latensi (p50/p95/p99), statistik cache, status circuit breaker penyedia, sesi terpantau kuota yang aktif, dan kesehatan target combo.
![Health Dashboard](screenshots/04-health.png)
---
## 🔧 Translator Playground
## 🔧 Taman Bermain Translator
Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
Empat mode untuk men-debug terjemahan API: **Playground** (konverter format), **Chat Tester** (permintaan langsung), **Test Bench** (pengujian batch), dan **Live Monitor** (aliran real-time).
![Translator Playground](screenshots/05-translator.png)
---
## 🎮 Model Playground _(v2.0.9+)_
## 🎮 Taman Bermain Model _(v2.0.9+)_
Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
Uji model apa pun langsung dari dashboard. Pilih penyedia, model, dan endpoint, tulis prompt dengan Monaco Editor, streaming respons secara real-time, batalkan di tengah streaming, dan lihat metrik waktu.
---
## 🎨 Themes _(v2.0.5+)_
## 🎨 Tema _(v2.0.5+)_
Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
Tema warna yang dapat dikustomisasi untuk seluruh dashboard. Pilih dari 7 warna prasetel (Coral, Blue, Red, Green, Violet, Orange, Cyan) atau buat tema kustom dengan memilih warna hex apa pun. Mendukung mode terang, gelap, dan sistem.
---
## ⚙️ Settings
## ⚙️ Pengaturan
Comprehensive settings panel with tabs:
Panel pengaturan komprehensif dengan tab:
- **General** — System storage, backup management (export/import database)
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
- **Routing** — Model aliases, background task degradation
- **Resilience** — Rate limit persistence, circuit breaker tuning, auto-disable banned accounts, provider expiration monitoring, **Context Relay** handoff threshold and summary model configuration
- **Advanced** — Configuration overrides, configuration audit trail, fallback degradation mode
- **Umum** — Penyimpanan sistem, manajemen cadangan (ekspor/impor database)
- **Tampilan** — Pemilih tema (gelap/terang/sistem), prasetel tema warna dan warna kustom, visibilitas log kesehatan, kontrol visibilitas item bilah samping
- **Keamanan** — Perlindungan endpoint API, pemblokiran penyedia kustom, pemfilteran IP, info sesi
- **Routing** — Alias model, degradasi tugas latar belakang
- **Ketahanan** — Persistensi batas laju, penyetelan circuit breaker, nonaktifkan akun yang diblokir secara otomatis, pemantauan kedaluwarsa penyedia, ambang batas handoff **Context Relay** dan konfigurasi model ringkasan
- **Lanjutan** — Penimpaan konfigurasi, jejak audit konfigurasi, mode degradasi fallback
![Settings Dashboard](screenshots/06-settings.png)
---
## 🔧 CLI Tools
## 🔧 Alat CLI
One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
Konfigurasi satu klik untuk alat pengkodean AI: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, dan Factory Droid. Dilengkapi penerapan/reset konfigurasi otomatis, profil koneksi, dan pemetaan model.
![CLI Tools Dashboard](screenshots/07-cli-tools.png)
---
## 🤖 CLI Agents _(v2.0.11+)_
## 🤖 Agen CLI _(v2.0.11+)_
Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
Dashboard untuk menemukan dan mengelola agen CLI. Menampilkan kisi 14 agen bawaan (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) dengan:
- **Installation status** — Installed / Not Found with version detection
- **Protocol badges** — stdio, HTTP, etc.
- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
- **Status instalasi** — Terpasang / Tidak Ditemukan dengan deteksi versi
- **Lencana protokol** — stdio, HTTP, dll.
- **Agen kustom** — Daftarkan alat CLI apa pun melalui formulir (nama, biner, perintah versi, argumen spawn)
- **Pencocokan Sidik Jari CLI** — Sakelar per penyedia untuk mencocokkan tanda tangan permintaan CLI asli, mengurangi risiko pemblokiran sambil mempertahankan IP proxy
---
## 🔗 Context Relay _(v3.5.5+)_
A combo strategy that preserves session continuity when account rotation happens mid-conversation. Before the active account is exhausted, OmniRoute generates a structured handoff summary in the background. After the next request resolves to a different account, the summary is injected as a system message so the new account continues with full context.
Strategi combo yang mempertahankan kesinambungan sesi saat rotasi akun terjadi di tengah percakapan. Sebelum akun aktif habis, OmniRoute menghasilkan ringkasan handoff terstruktur di latar belakang. Setelah permintaan berikutnya diarahkan ke akun berbeda, ringkasan disuntikkan sebagai pesan sistem sehingga akun baru melanjutkan dengan konteks penuh.
Configurable via combo-level or global settings:
Dapat dikonfigurasi melalui pengaturan level combo atau global:
- **Handoff Threshold** — Quota usage percentage that triggers summary generation (default 85%)
- **Max Messages For Summary** — How much recent history to condense
- **Summary Model** — Optional override model for generating the handoff summary
- **Ambang Batas Handoff** — Persentase penggunaan kuota yang memicu pembuatan ringkasan (default 85%)
- **Maks Pesan untuk Ringkasan** — Seberapa banyak riwayat terkini yang dipadatkan
- **Model Ringkasan** — Model penimpaan opsional untuk menghasilkan ringkasan handoff
Currently supports Codex account rotation. See [Context Relay documentation](features/context-relay.md).
Saat ini mendukung rotasi akun Codex. Lihat [dokumentasi Context Relay](features/context-relay.md).
---
## 🛡️ Proxy Hardening _(v3.5.5+)_
## 🛡️ Penguatan Proxy _(v3.5.5+)_
Comprehensive proxy configuration enforcement across the entire request pipeline:
Penegakan konfigurasi proxy komprehensif di seluruh pipeline permintaan:
- **Token Health Check** — Background OAuth refresh now resolves proxy config per connection, preventing failures in proxy-required environments
- **API Key Validation** — Provider key validation (`POST /api/providers/validate`) routes through `runWithProxyContext`, honoring provider-level and global proxy settings
- **undici Dispatcher Fix** — Proxy dispatchers use undici's own fetch implementation instead of Node's built-in fetch, resolving `invalid onRequestStart method` errors on Node.js 22
- **Node.js Version Detection** — Login page proactively detects incompatible Node.js versions (24+) and displays a warning banner with instructions to use Node 22 LTS
- **Pemeriksaan Kesehatan Token** — Pembaruan OAuth latar belakang kini me-resolve konfigurasi proxy per koneksi, mencegah kegagalan di lingkungan yang memerlukan proxy
- **Validasi Kunci API** — Validasi kunci penyedia (`POST /api/providers/validate`) diarahkan melalui `runWithProxyContext`, menghormati pengaturan proxy level penyedia dan global
- **Perbaikan Dispatcher undici** — Dispatcher proxy menggunakan implementasi fetch milik undici sendiri alih-alih fetch bawaan Node, menyelesaikan kesalahan `invalid onRequestStart method` pada Node.js 22
- **Deteksi Versi Node.js** — Halaman login secara proaktif mendeteksi versi Node.js yang tidak kompatibel (24+) dan menampilkan spanduk peringatan dengan instruksi untuk menggunakan Node 22 LTS
---
## 📧 Email Privacy Masking _(v3.5.6+)_
## 📧 Penyamaran Privasi Email _(v3.5.6+)_
OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots or recording demos. The full email address remains accessible via hover tooltip (`title` attribute).
Email akun OAuth kini disembunyikan di dashboard penyedia (mis. `di*****@g****.com`) untuk mencegah paparan tidak sengaja saat berbagi tangkapan layar atau merekam demo. Alamat email lengkap tetap dapat diakses melalui tooltip hover (atribut `title`).
---
## 👁️ Model Visibility Toggle _(v3.5.6+)_
## 👁️ Sakelar Visibilitas Model _(v3.5.6+)_
The provider page model list now includes:
Daftar model halaman penyedia kini menyertakan:
- **Real-time search/filter bar** — Quickly find specific models
- **Per-model visibility toggle** (👁 icon) — Hidden models are grayed out and excluded from the `/v1/models` catalog
- **Active-count badge** (`N/M active`) — Shows at a glance how many models are enabled vs total
- **Bilah pencarian/filter real-time** — Temukan model tertentu dengan cepat
- **Sakelar visibilitas per model** (ikon 👁) — Model yang disembunyikan diarsir dan dikecualikan dari katalog `/v1/models`
- **Lencana jumlah aktif** (`N/M active`) — Menampilkan sekilas berapa banyak model yang diaktifkan vs total
---
## 🔧 OAuth Env Repair _(v3.6.1+)_
## 🔧 Perbaikan Env OAuth _(v3.6.1+)_
One-click "Repair env" action for OAuth providers that restores missing environment variables and fixes broken auth state. Accessible from `Dashboard → Providers → [OAuth Provider] → Repair env`. Automatically detects and repairs:
Tindakan "Repair env" satu klik untuk penyedia OAuth yang memulihkan variabel lingkungan yang hilang dan memperbaiki status autentikasi yang rusak. Dapat diakses dari `Dashboard → Providers → [OAuth Provider] → Repair env`. Secara otomatis mendeteksi dan memperbaiki:
- Missing OAuth client credentials
- Corrupted env file entries
- Backup path sanitization
- Kredensial klien OAuth yang hilang
- Entri file env yang rusak
- Sanitasi jalur cadangan
---
## 🗑️ Uninstall / Full Uninstall _(v3.6.2+)_
## 🗑️ Uninstall / Uninstall Penuh _(v3.6.2+)_
Clean removal scripts for all installation methods:
Skrip penghapusan bersih untuk semua metode instalasi:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
| Perintah | Tindakan |
| ------------------------ | --------------------------------------------------------------------------------------------- |
| `npm run uninstall` | Menghapus aplikasi sistem tetapi **mempertahankan DB dan konfigurasi Anda** di `~/.omniroute`. |
| `npm run uninstall:full` | Menghapus aplikasi DAN secara permanen **menghapus semua konfigurasi, kunci, dan database**. |
---
## 🖼️ Media _(v2.0.3+)_
Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
Hasilkan gambar, video, dan musik dari dashboard. Mendukung OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, dan MusicGen.
---
## 📝 Request Logs
## 📝 Log Permintaan
Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
Pencatatan permintaan real-time dengan pemfilteran berdasarkan penyedia, model, akun, dan kunci API. Menampilkan kode status, penggunaan token, latensi, dan detail respons.
![Usage Logs](screenshots/08-usage.png)
---
## 🌐 API Endpoint
## 🌐 Endpoint API
Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloudflare Quick Tunnel integration and cloud proxy support for remote access.
Endpoint API terpadu Anda dengan rincian kemampuan: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, dan kunci API yang terdaftar. Integrasi Cloudflare Quick Tunnel dan dukungan proxy cloud untuk akses jarak jauh.
![Endpoint Dashboard](screenshots/09-endpoint.png)
---
## 🔑 API Key Management
## 🔑 Manajemen Kunci API
Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
Buat, batasi cakupan, dan cabut kunci API. Setiap kunci dapat dibatasi ke model/penyedia tertentu dengan izin akses penuh atau hanya baca. Manajemen kunci secara visual dengan pelacakan penggunaan.
---
## 📋 Audit Log
## 📋 Log Audit
Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
Pelacakan tindakan administratif dengan pemfilteran berdasarkan jenis tindakan, pelaku, target, alamat IP, dan cap waktu. Riwayat kejadian keamanan lengkap.
---
## 🖥️ Desktop Application
## 🖥️ Aplikasi Desktop
Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
Aplikasi desktop Electron asli untuk Windows, macOS, dan Linux. Jalankan OmniRoute sebagai aplikasi mandiri dengan integrasi system tray, dukungan offline, pembaruan otomatis, dan instalasi satu klik.
Key features:
Fitur utama:
- Server readiness polling (no blank screen on cold start)
- System tray with port management
- Polling kesiapan server (tidak ada layar kosong saat cold start)
- System tray dengan manajemen port
- Content Security Policy
- Single-instance lock
- Auto-update on restart
- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
- **Graceful shutdown** — Electron `before-quit` shuts down Next.js cleanly, preventing SQLite WAL database locks (v3.6.2+)
- Kunci instans tunggal
- Pembaruan otomatis saat restart
- UI kondisional platform (lampu lalu lintas macOS, titlebar default Windows/Linux)
- Pengemasan build Electron yang diperkuat — `node_modules` yang di-symlink dalam bundel mandiri terdeteksi dan ditolak sebelum pengemasan, mencegah ketergantungan runtime pada mesin build (v2.5.5+)
- **Penutupan yang baik** — `before-quit` Electron menutup Next.js dengan bersih, mencegah kunci database SQLite WAL (v3.6.2+)
📖 See [`electron/README.md`](../electron/README.md) for full documentation.
📖 Lihat [`electron/README.md`](../electron/README.md) untuk dokumentasi lengkap.
---
## 🌐 V1 WebSocket Bridge _(v3.6.6+)_
## 🌐 Jembatan WebSocket V1 _(v3.6.6+)_
OmniRoute now supports **OpenAI-compatible WebSocket clients** via the `/v1/ws` upgrade endpoint. The custom `scripts/v1-ws-bridge.mjs` server wraps Next.js and upgrades WS connections to full bidirectional streaming sessions. Authentication uses the same API key or session cookie as HTTP requests.
OmniRoute kini mendukung **klien WebSocket yang kompatibel dengan OpenAI** melalui endpoint upgrade `/v1/ws`. Server `scripts/v1-ws-bridge.mjs` kustom membungkus Next.js dan mengupgrade koneksi WS menjadi sesi streaming dua arah penuh. Autentikasi menggunakan kunci API atau cookie sesi yang sama seperti permintaan HTTP.
Key behaviours:
Perilaku utama:
- WS upgrade validated by `src/lib/ws/handshake.ts` before the connection is established
- Streams terminated cleanly on session close or upstream error
- Works alongside the existing HTTP+SSE streaming path simultaneously
- Upgrade WS divalidasi oleh `src/lib/ws/handshake.ts` sebelum koneksi dibuat
- Aliran dihentikan dengan bersih saat sesi ditutup atau terjadi kesalahan upstream
- Berfungsi berdampingan dengan jalur streaming HTTP+SSE yang ada secara bersamaan
---
## 🔑 Sync Tokens & Config Bundle _(v3.6.6+)_
## 🔑 Token Sinkronisasi & Bundel Konfigurasi _(v3.6.6+)_
Multi-device and external operator access is now possible via **scoped sync tokens**:
Akses multi-perangkat dan operator eksternal kini dimungkinkan melalui **token sinkronisasi bercakupan**:
- **`POST /api/sync/tokens`** — Issue a new sync token (scoped, with optional expiry)
- **`DELETE /api/sync/tokens/:id`** — Revoke a token
- **`GET /api/sync/bundle`** — Download a versioned, ETag-keyed JSON snapshot of all non-sensitive settings (passwords redacted)
- **`POST /api/sync/tokens`** — Terbitkan token sinkronisasi baru (bercakupan, dengan kedaluwarsa opsional)
- **`DELETE /api/sync/tokens/:id`** — Cabut token
- **`GET /api/sync/bundle`** — Unduh snapshot JSON berversi dan berkey ETag dari semua pengaturan tidak sensitif (kata sandi disunting)
The config bundle is built by `src/lib/sync/bundle.ts`. Consumers compare the `ETag` response header to detect changes without re-downloading the full payload.
Bundel konfigurasi dibuat oleh `src/lib/sync/bundle.ts`. Konsumen membandingkan header respons `ETag` untuk mendeteksi perubahan tanpa mengunduh ulang payload penuh.
---
## 🧠 GLM Thinking Preset _(v3.6.6+)_
## 🧠 Prasetel GLM Thinking _(v3.6.6+)_
**GLM Thinking (`glmt`)** is now a registered first-class provider: 65 536 max output tokens, 24 576 thinking budget, 900 s default timeout, Claude-compatible API format, and shared usage sync with the GLM family.
**GLM Thinking (`glmt`)** kini merupakan penyedia kelas pertama yang terdaftar: 65 536 token output maksimum, anggaran thinking 24 576, timeout default 900 detik, format API yang kompatibel dengan Claude, dan sinkronisasi penggunaan bersama dengan keluarga GLM.
**Hybrid token counting** also lands in v3.6.6: when a Claude-compatible provider exposes `/messages/count_tokens`, OmniRoute calls it before large requests with graceful estimation fallback.
**Penghitungan token hibrida** juga hadir di v3.6.6: ketika penyedia yang kompatibel dengan Claude mengekspos `/messages/count_tokens`, OmniRoute memanggilnya sebelum permintaan besar dengan fallback estimasi yang baik.
---
## 🛡️ Safe Outbound Fetch & SSRF Guard _(v3.6.6+)_
## 🛡️ Fetch Keluar Aman & Penjaga SSRF _(v3.6.6+)_
All provider validation and model discovery calls now go through a two-layer outbound guard:
Semua panggilan validasi penyedia dan penemuan model kini melewati penjaga keluar dua lapis:
1. **URL guard** (`src/shared/network/outboundUrlGuard.ts`) — Blocks private/loopback/link-local IP ranges before the socket is opened.
2. **Safe fetch wrapper** (`src/shared/network/safeOutboundFetch.ts`) — Applies the URL guard, normalises timeouts, and retries transient errors with exponential backoff.
1. **Penjaga URL** (`src/shared/network/outboundUrlGuard.ts`) — Memblokir rentang IP privat/loopback/link-local sebelum soket dibuka.
2. **Pembungkus fetch aman** (`src/shared/network/safeOutboundFetch.ts`) — Menerapkan penjaga URL, menormalkan timeout, dan mencoba ulang kesalahan transien dengan backoff eksponensial.
Guard violations surface as HTTP 422 (`URL_GUARD_BLOCKED`) and are written to the compliance audit log via `providerAudit.ts`.
Pelanggaran penjaga muncul sebagai HTTP 422 (`URL_GUARD_BLOCKED`) dan ditulis ke log audit kepatuhan melalui `providerAudit.ts`.
---
## 🔄 Cooldown-Aware Retries _(v3.6.6+)_
## 🔄 Percobaan Ulang yang Mempertimbangkan Cooldown _(v3.6.6+)_
Chat requests now **automatically retry** when an upstream provider returns a model-scoped cooldown. Configurable via `REQUEST_RETRY` (default: 2) and `MAX_RETRY_INTERVAL_SEC` (default: 30 s). Rate-limit header learning improved across `x-ratelimit-reset-requests`, `x-ratelimit-reset-tokens`, and `Retry-After`per-model cooldown state is visible in the Resilience dashboard.
Permintaan chat kini **secara otomatis mencoba ulang** ketika penyedia upstream mengembalikan cooldown bercakupan model. Dapat dikonfigurasi melalui `REQUEST_RETRY` (default: 2) dan `MAX_RETRY_INTERVAL_SEC` (default: 30 detik). Pembelajaran header batas laju yang ditingkatkan di seluruh `x-ratelimit-reset-requests`, `x-ratelimit-reset-tokens`, dan `Retry-After`status cooldown per model terlihat di dashboard Ketahanan.
---
## 📋 Compliance Audit v2 _(v3.6.6+)_
## 📋 Audit Kepatuhan v2 _(v3.6.6+)_
The audit log has been expanded with cursor-based pagination, request context enrichment (request ID, user agent, IP), structured auth events, provider CRUD events with diff context, and SSRF-blocked validation logging. New events emitted by `src/lib/compliance/providerAudit.ts`.
Log audit telah diperluas dengan paginasi berbasis kursor, pengayaan konteks permintaan (ID permintaan, user agent, IP), kejadian autentikasi terstruktur, kejadian CRUD penyedia dengan konteks diff, dan pencatatan validasi yang diblokir SSRF. Kejadian baru dipancarkan oleh `src/lib/compliance/providerAudit.ts`.

View File

@@ -1,77 +1,77 @@
# i18n — Internationalization Guide (Bahasa Indonesia)
# i18n — Panduan Internasionalisasi (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/I18N.md) · 🇸🇦 [ar](../../ar/docs/I18N.md) · 🇧🇬 [bg](../../bg/docs/I18N.md) · 🇧🇩 [bn](../../bn/docs/I18N.md) · 🇨🇿 [cs](../../cs/docs/I18N.md) · 🇩🇰 [da](../../da/docs/I18N.md) · 🇩🇪 [de](../../de/docs/I18N.md) · 🇪🇸 [es](../../es/docs/I18N.md) · 🇮🇷 [fa](../../fa/docs/I18N.md) · 🇫🇮 [fi](../../fi/docs/I18N.md) · 🇫🇷 [fr](../../fr/docs/I18N.md) · 🇮🇳 [gu](../../gu/docs/I18N.md) · 🇮🇱 [he](../../he/docs/I18N.md) · 🇮🇳 [hi](../../hi/docs/I18N.md) · 🇭🇺 [hu](../../hu/docs/I18N.md) · 🇮🇩 [id](../../id/docs/I18N.md) · 🇮🇹 [it](../../it/docs/I18N.md) · 🇯🇵 [ja](../../ja/docs/I18N.md) · 🇰🇷 [ko](../../ko/docs/I18N.md) · 🇮🇳 [mr](../../mr/docs/I18N.md) · 🇲🇾 [ms](../../ms/docs/I18N.md) · 🇳🇱 [nl](../../nl/docs/I18N.md) · 🇳🇴 [no](../../no/docs/I18N.md) · 🇵🇭 [phi](../../phi/docs/I18N.md) · 🇵🇱 [pl](../../pl/docs/I18N.md) · 🇵🇹 [pt](../../pt/docs/I18N.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/I18N.md) · 🇷🇴 [ro](../../ro/docs/I18N.md) · 🇷🇺 [ru](../../ru/docs/I18N.md) · 🇸🇰 [sk](../../sk/docs/I18N.md) · 🇸🇪 [sv](../../sv/docs/I18N.md) · 🇰🇪 [sw](../../sw/docs/I18N.md) · 🇮🇳 [ta](../../ta/docs/I18N.md) · 🇮🇳 [te](../../te/docs/I18N.md) · 🇹🇭 [th](../../th/docs/I18N.md) · 🇹🇷 [tr](../../tr/docs/I18N.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/I18N.md) · 🇵🇰 [ur](../../ur/docs/I18N.md) · 🇻🇳 [vi](../../vi/docs/I18N.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/I18N.md)
---
OmniRoute supports **30 languages** with full dashboard UI translation, translated documentation, and RTL support for Arabic and Hebrew.
OmniRoute mendukung **30 bahasa** dengan terjemahan UI dashboard penuh, dokumentasi yang diterjemahkan, dan dukungan RTL untuk bahasa Arab dan Ibrani.
## Quick Reference
## Referensi Cepat
| Task | Command |
| ---------------------- | --------------------------------------------------------------------------------------- |
| Generate translations | `node scripts/i18n/generate-multilang.mjs messages` |
| Translate docs (LLM) | `python3 scripts/i18n_autotranslate.py --api-url <url> --api-key <key> --model <model>` |
| Validate a locale | `python3 scripts/validate_translation.py quick -l cs` |
| Check code keys | `python3 scripts/check_translations.py` |
| Generate QA report | `node scripts/i18n/generate-qa-checklist.mjs` |
| Visual QA (Playwright) | `node scripts/i18n/run-visual-qa.mjs` |
| Tugas | Perintah |
| ------------------------------ | --------------------------------------------------------------------------------------- |
| Hasilkan terjemahan | `node scripts/i18n/generate-multilang.mjs messages` |
| Terjemahkan dokumentasi (LLM) | `python3 scripts/i18n_autotranslate.py --api-url <url> --api-key <key> --model <model>` |
| Validasi lokal | `python3 scripts/validate_translation.py quick -l cs` |
| Periksa kunci kode | `python3 scripts/check_translations.py` |
| Hasilkan laporan QA | `node scripts/i18n/generate-qa-checklist.mjs` |
| QA Visual (Playwright) | `node scripts/i18n/run-visual-qa.mjs` |
## Arsitektur
### Source of Truth
### Sumber Kebenaran
- **UI strings**: `src/i18n/messages/en.json` (English source, ~2800 keys)
- **Locale files**: `src/i18n/messages/{locale}.json` (30 translations)
- **Framework**: `next-intl` with cookie-based locale resolution
- **Config**: `src/i18n/config.ts` — defines all 30 locales, language names, flags
- **String UI**: `src/i18n/messages/en.json` (sumber bahasa Inggris, ~2800 kunci)
- **File lokal**: `src/i18n/messages/{locale}.json` (30 terjemahan)
- **Framework**: `next-intl` dengan resolusi lokal berbasis cookie
- **Konfigurasi**: `src/i18n/config.ts`mendefinisikan semua 30 lokal, nama bahasa, bendera
### Runtime Flow
### Alur Runtime
1. User selects language → `NEXT_LOCALE` cookie set
2. `src/i18n/request.ts` resolves locale: cookie → `Accept-Language` header → fallback `en`
3. Dynamic import loads `messages/{locale}.json`
4. Components use `useTranslations("namespace")` and `t("key")`
1. Pengguna memilih bahasa → cookie `NEXT_LOCALE` disetel
2. `src/i18n/request.ts` menyelesaikan lokal: cookie → header `Accept-Language` → fallback `en`
3. Import dinamis memuat `messages/{locale}.json`
4. Komponen menggunakan `useTranslations("namespace")` dan `t("key")`
### Supported Locales
### Lokal yang Didukung
| Code | Language | RTL | Google Translate Code |
| Kode | Bahasa | RTL | Kode Google Translate |
| ------- | -------------------- | --- | --------------------- |
| `ar` | العربية | Yes | `ar` |
| `bg` | Български | No | `bg` |
| `cs` | Čeština | No | `cs` |
| `da` | Dansk | No | `da` |
| `de` | Deutsch | No | `de` |
| `es` | Español | No | `es` |
| `fi` | Suomi | No | `fi` |
| `fr` | Français | No | `fr` |
| `he` | עברית | Yes | `iw` |
| `hi` | हिन्दी | No | `hi` |
| `hu` | Magyar | No | `hu` |
| `id` | Bahasa Indonesia | No | `id` |
| `it` | Italiano | No | `it` |
| `ja` | 日本語 | No | `ja` |
| `ko` | 한국어 | No | `ko` |
| `ms` | Bahasa Melayu | No | `ms` |
| `nl` | Nederlands | No | `nl` |
| `no` | Norsk | No | `no` |
| `phi` | Filipino | No | `tl` |
| `pl` | Polski | No | `pl` |
| `pt` | Português (Portugal) | No | `pt` |
| `pt-BR` | Português (Brasil) | No | `pt` |
| `ro` | Română | No | `ro` |
| `ru` | Русский | No | `ru` |
| `sk` | Slovenčina | No | `sk` |
| `sv` | Svenska | No | `sv` |
| `th` | ไทย | No | `th` |
| `tr` | Türkçe | No | `tr` |
| `uk-UA` | Українська | No | `uk` |
| `vi` | Tiếng Việt | No | `vi` |
| `zh-CN` | 中文 (简体) | No | `zh-CN` |
| `ar` | العربية | Ya | `ar` |
| `bg` | Български | Tidak | `bg` |
| `cs` | Čeština | Tidak | `cs` |
| `da` | Dansk | Tidak | `da` |
| `de` | Deutsch | Tidak | `de` |
| `es` | Español | Tidak | `es` |
| `fi` | Suomi | Tidak | `fi` |
| `fr` | Français | Tidak | `fr` |
| `he` | עברית | Ya | `iw` |
| `hi` | हिन्दी | Tidak | `hi` |
| `hu` | Magyar | Tidak | `hu` |
| `id` | Bahasa Indonesia | Tidak | `id` |
| `it` | Italiano | Tidak | `it` |
| `ja` | 日本語 | Tidak | `ja` |
| `ko` | 한국어 | Tidak | `ko` |
| `ms` | Bahasa Melayu | Tidak | `ms` |
| `nl` | Nederlands | Tidak | `nl` |
| `no` | Norsk | Tidak | `no` |
| `phi` | Filipino | Tidak | `tl` |
| `pl` | Polski | Tidak | `pl` |
| `pt` | Português (Portugal) | Tidak | `pt` |
| `pt-BR` | Português (Brasil) | Tidak | `pt` |
| `ro` | Română | Tidak | `ro` |
| `ru` | Русский | Tidak | `ru` |
| `sk` | Slovenčina | Tidak | `sk` |
| `sv` | Svenska | Tidak | `sv` |
| `th` | ไทย | Tidak | `th` |
| `tr` | Türkçe | Tidak | `tr` |
| `uk-UA` | Українська | Tidak | `uk` |
| `vi` | Tiếng Việt | Tidak | `vi` |
| `zh-CN` | 中文 (简体) | Tidak | `zh-CN` |
## Adding a New Language
## Menambahkan Bahasa Baru
### 1. Register the Locale
### 1. Daftarkan Lokal
Edit `src/i18n/config.ts`:
@@ -82,9 +82,9 @@ Edit `src/i18n/config.ts`:
{ code: "xx", label: "XX", name: "Language Name", flag: "🏳️" },
```
### 2. Add to Generator
### 2. Tambahkan ke Generator
Edit `scripts/i18n/generate-multilang.mjs`add entry to `LOCALE_SPECS`:
Edit `scripts/i18n/generate-multilang.mjs`tambahkan entri ke `LOCALE_SPECS`:
```js
{
@@ -98,70 +98,70 @@ Edit `scripts/i18n/generate-multilang.mjs` — add entry to `LOCALE_SPECS`:
},
```
### 3. Generate Initial Translation
### 3. Hasilkan Terjemahan Awal
```bash
node scripts/i18n/generate-multilang.mjs messages
```
This creates `src/i18n/messages/xx.json` auto-translated from `en.json` via Google Translate.
Perintah ini membuat `src/i18n/messages/xx.json` yang diterjemahkan secara otomatis dari `en.json` melalui Google Translate.
### 4. Review & Fix Auto-Translations
### 4. Tinjau & Perbaiki Terjemahan Otomatis
Auto-translations are a starting point. Review manually for:
Terjemahan otomatis hanyalah titik awal. Tinjau secara manual untuk:
- Technical accuracy
- Context-appropriate terminology
- Proper handling of placeholders (`{count}`, `{value}`, etc.)
- Ketepatan teknis
- Terminologi yang sesuai konteks
- Penanganan placeholder yang benar (`{count}`, `{value}`, dll.)
### 5. Validate
### 5. Validasi
```bash
python3 scripts/validate_translation.py quick -l xx
python3 scripts/validate_translation.py diff common -l xx
```
### 6. Generate Translated Documentation
### 6. Hasilkan Dokumentasi yang Diterjemahkan
```bash
node scripts/i18n/generate-multilang.mjs docs
```
## Auto-Translation Pipeline
## Pipeline Terjemahan Otomatis
### generate-multilang.mjs (Google Translate)
**Primary auto-translation engine** — uses Google Translate free API to generate translations for UI strings, READMEs, and documentation.
**Mesin terjemahan otomatis utama** — menggunakan API gratis Google Translate untuk menghasilkan terjemahan string UI, README, dan dokumentasi.
```bash
node scripts/i18n/generate-multilang.mjs [messages|readme|docs|all]
```
| Mode | What it does |
| Mode | Yang dilakukan |
| ---------- | ----------------------------------------------------------------------------- |
| `messages` | Translates missing keys in `src/i18n/messages/{locale}.json` from `en.json` |
| `readme` | Translates `README.md` into all locales as `README.{code}.md` in project root |
| `docs` | Translates `DOC_SOURCE_FILES` into `docs/i18n/{locale}/{docName}` |
| `all` | Runs all three modes |
| `messages` | Menerjemahkan kunci yang hilang di `src/i18n/messages/{locale}.json` dari `en.json` |
| `readme` | Menerjemahkan `README.md` ke semua lokal sebagai `README.{code}.md` di root proyek |
| `docs` | Menerjemahkan `DOC_SOURCE_FILES` ke `docs/i18n/{locale}/{docName}` |
| `all` | Menjalankan ketiga mode sekaligus |
**Features:**
**Fitur:**
- **Text protection**: Masks code blocks (` ``` `), inline code (`` ` ``), markdown links/images (`[text](url)`), HTML tags, tables, and ICU placeholders (`{count}`, `{value}`, `{total}`, etc.) before translation, then restores them
- **Chunked batching**: Joins multiple strings with `__OMNIROUTE_I18N_SEPARATOR__` delimiters to minimize API calls (max 1800 chars per request)
- **In-memory cache**: Avoids redundant API calls for repeated strings within a session
- **Retry logic**: Exponential backoff (up to 5 attempts with 300ms × attempt delay) for 429/5xx errors
- **Timeout**: 20 seconds per request
- **Skip existing**: If target file already exists, it is NOT overwritten
- **Perlindungan teks**: Menyembunyikan blok kode (` ``` `), kode inline (`` ` ``), tautan/gambar markdown (`[text](url)`), tag HTML, tabel, dan placeholder ICU (`{count}`, `{value}`, `{total}`, dll.) sebelum penerjemahan, lalu memulihkannya
- **Pemrosesan bertahap**: Menggabungkan beberapa string dengan pemisah `__OMNIROUTE_I18N_SEPARATOR__` untuk meminimalkan panggilan API (maks 1800 karakter per permintaan)
- **Cache dalam memori**: Menghindari panggilan API yang redundan untuk string yang berulang dalam satu sesi
- **Logika percobaan ulang**: Backoff eksponensial (hingga 5 percobaan dengan penundaan 300ms × percobaan) untuk error 429/5xx
- **Batas waktu**: 20 detik per permintaan
- **Lewati yang sudah ada**: Jika file target sudah ada, file tersebut TIDAK akan ditimpa
**Important behaviors:**
**Perilaku penting:**
- `docs/i18n/README.md` is **regenerated** each run — it's an auto-generated index of all docs
- Root `README.{code}.md` files are only created if they don't exist (skips locales in `EXISTING_README_CODES`)
- Language bars (`🌐 **Languages:** ...`) are automatically inserted/updated in all translated docs
- `docs/i18n/README.md` **dihasilkan ulang** setiap kali dijalankan — ini adalah indeks dokumentasi yang dibuat otomatis
- File `README.{code}.md` di root hanya dibuat jika belum ada (melewati lokal yang ada di `EXISTING_README_CODES`)
- Bilah bahasa (`🌐 **Languages:** ...`) disisipkan/diperbarui secara otomatis di semua dokumen yang diterjemahkan
### i18n_autotranslate.py (LLM-based)
### i18n_autotranslate.py (berbasis LLM)
**Secondary translator** — uses any OpenAI-compatible LLM API (including OmniRoute itself) to translate existing `docs/i18n/` markdown files. Best for polishing or re-translating docs with better quality than Google Translate.
**Penerjemah sekunder** — menggunakan API LLM yang kompatibel dengan OpenAI (termasuk OmniRoute sendiri) untuk menerjemahkan file markdown `docs/i18n/` yang sudah ada. Paling baik digunakan untuk menyempurnakan atau menerjemahkan ulang dokumen dengan kualitas yang lebih baik dari Google Translate.
```bash
python3 scripts/i18n_autotranslate.py \
@@ -170,18 +170,18 @@ python3 scripts/i18n_autotranslate.py \
--model gpt-4o
```
**Features:**
**Fitur:**
- Scans `docs/i18n/` markdown files for English paragraphs
- Skips code blocks, tables, and already-translated content
- Sends paragraphs to LLM with technical translation system prompt
- Supports all 30 languages
- Memindai file markdown `docs/i18n/` untuk paragraf berbahasa Inggris
- Melewati blok kode, tabel, dan konten yang sudah diterjemahkan
- Mengirimkan paragraf ke LLM dengan prompt sistem penerjemahan teknis
- Mendukung semua 30 bahasa
## Validation & QA
## Validasi & QA
### validate_translation.py
**Translation validator** — compares any locale JSON against `en.json` and reports issues.
**Validator terjemahan** — membandingkan JSON lokal mana pun dengan `en.json` dan melaporkan masalah yang ditemukan.
```bash
# Quick check (counts only)
@@ -205,26 +205,26 @@ python3 scripts/validate_translation.py md -l cs > report.md
python3 scripts/validate_translation.py -l cs
```
**Detects:**
**Yang dideteksi:**
- **Missing keys** — keys in `en.json` but not in locale file
- **Extra keys** — keys in locale file but not in `en.json`
- **Untranslated keys** — keys where locale value equals English source (excluding allowlist)
- **Placeholder mismatches** — ICU placeholders that don't match between source and translation
- **Kunci yang hilang** — kunci yang ada di `en.json` tetapi tidak ada di file lokal
- **Kunci tambahan** — kunci yang ada di file lokal tetapi tidak ada di `en.json`
- **Kunci yang belum diterjemahkan** — kunci yang nilai lokalnya sama dengan sumber bahasa Inggris (tidak termasuk daftar yang diizinkan)
- **Ketidaksesuaian placeholder** — placeholder ICU yang tidak cocok antara sumber dan terjemahan
**Exit codes:**
| Code | Meaning |
|------|---------|
**Kode keluar:**
| Kode | Makna |
|------|-------|
| 0 | OK |
| 1 | Generic error |
| 2 | Missing strings (hard error) |
| 3 | Untranslated warning (soft) |
| 1 | Error umum |
| 2 | String yang hilang (error kritis) |
| 3 | Peringatan belum diterjemahkan (lunak) |
**Environment:** Set `TRANSLATION_LANG=cs` or use `-l cs` flag.
**Lingkungan:** Setel `TRANSLATION_LANG=cs` atau gunakan flag `-l cs`.
### check_translations.py
**Code-to-JSON key checker** — scans `src/**/*.tsx` and `src/**/*.ts` for `useTranslations()` calls and verifies all referenced keys exist in `en.json`.
**Pemeriksa kunci kode ke JSON** — memindai `src/**/*.tsx` dan `src/**/*.ts` untuk panggilan `useTranslations()` dan memverifikasi bahwa semua kunci yang direferensikan ada di `en.json`.
```bash
# Basic check
@@ -239,25 +239,25 @@ python3 scripts/check_translations.py --fix
### generate-qa-checklist.mjs
**Static analysis QA**scans Next.js page files for i18n risk metrics and generates a Markdown report.
**QA analisis statis**memindai file halaman Next.js untuk metrik risiko i18n dan menghasilkan laporan Markdown.
```bash
node scripts/i18n/generate-qa-checklist.mjs
```
**Checks:**
**Yang diperiksa:**
- Fixed-width class usage (overflow risk)
- Directional left/right classes (RTL risk)
- Clipping-prone patterns
- Locale parity (missing/extra keys vs `en.json`)
- README language selector bars in priority locales (`es`, `fr`, `de`, `ja`, `ar`)
- Penggunaan kelas lebar tetap (risiko overflow)
- Kelas arah kiri/kanan (risiko RTL)
- Pola rentan terpotong
- Paritas lokal (kunci yang hilang/tambahan vs `en.json`)
- Bilah pemilih bahasa README di lokal prioritas (`es`, `fr`, `de`, `ja`, `ar`)
**Output:** `docs/reports/i18n-qa-checklist-{date}.md`
**Keluaran:** `docs/reports/i18n-qa-checklist-{date}.md`
### run-visual-qa.mjs
**Visual QA via Playwright**takes screenshots of all dashboard routes in multiple locales and viewports, then evaluates page health.
**QA visual melalui Playwright**mengambil tangkapan layar semua rute dashboard dalam beberapa lokal dan viewport, lalu mengevaluasi kesehatan halaman.
```bash
# Default: es, fr, de, ja, ar on localhost:20128
@@ -270,21 +270,21 @@ QA_BASE_URL=http://staging.example.com QA_LOCALES=de,fr node scripts/i18n/run-vi
QA_ROUTES=/dashboard/settings,/dashboard/providers node scripts/i18n/run-visual-qa.mjs
```
**Detects:**
**Yang dideteksi:**
- Text overflow
- Element clipping
- RTL layout mismatches
- Teks yang meluap (text overflow)
- Elemen yang terpotong
- Ketidaksesuaian tata letak RTL
**Output:** `docs/reports/i18n-visual-qa-{date}.md` + JSON report
**Keluaran:** `docs/reports/i18n-visual-qa-{date}.md` + laporan JSON
## Managing Untranslatable Keys
## Mengelola Kunci yang Tidak Dapat Diterjemahkan
### untranslatable-keys.json
**File:** `scripts/i18n/untranslatable-keys.json`
Allowlist of keys that should remain identical to English source. Used by `validate_translation.py` to avoid false-positive "untranslated" warnings.
Daftar yang diizinkan berisi kunci yang harus tetap identik dengan sumber bahasa Inggris. Digunakan oleh `validate_translation.py` untuk menghindari peringatan "belum diterjemahkan" yang merupakan positif palsu.
```json
{
@@ -298,26 +298,26 @@ Allowlist of keys that should remain identical to English source. Used by `valid
}
```
**What belongs here:**
**Yang termasuk di sini:**
- Brand/product names: `landing.brandName`, `common.social-github`
- Technical terms/acronyms: `health.cpu`, `mcpDashboard.pid`, `settings.ai`
- ICU/format strings: `apiManager.modelsCount`, `health.millisecondsShort`
- Placeholder values: `providers.openaiBaseUrlPlaceholder`, `cliTools.baseUrlPlaceholder`
- Protocol names: `common.http`, `common.oauth`, `providers.oauth2Label`
- Navigation sections: `sidebar.primarySection`, `sidebar.cliSection`
- Nama merek/produk: `landing.brandName`, `common.social-github`
- Istilah teknis/akronim: `health.cpu`, `mcpDashboard.pid`, `settings.ai`
- String ICU/format: `apiManager.modelsCount`, `health.millisecondsShort`
- Nilai placeholder: `providers.openaiBaseUrlPlaceholder`, `cliTools.baseUrlPlaceholder`
- Nama protokol: `common.http`, `common.oauth`, `providers.oauth2Label`
- Bagian navigasi: `sidebar.primarySection`, `sidebar.cliSection`
**To add a key:** Edit the `keys` array in `scripts/i18n/untranslatable-keys.json` and re-run validation.
**Untuk menambahkan kunci:** Edit array `keys` di `scripts/i18n/untranslatable-keys.json` dan jalankan ulang validasi.
## CI Integration
## Integrasi CI
### GitHub Actions (`.github/workflows/ci.yml`)
The CI pipeline validates all locales on every push and PR:
Pipeline CI memvalidasi semua lokal pada setiap push dan PR:
1. **`i18n-matrix` job** — dynamically discovers all locale files (excluding `en.json`)
2. **`i18n` job** — runs `validate_translation.py quick -l '<lang>'` for each locale in parallel
3. **`ci-summary` job** — aggregates results into a dashboard summary
1. **Job `i18n-matrix`**secara dinamis menemukan semua file lokal (tidak termasuk `en.json`)
2. **Job `i18n`**menjalankan `validate_translation.py quick -l '<lang>'` untuk setiap lokal secara paralel
3. **Job `ci-summary`**mengagregasi hasil menjadi ringkasan dashboard
```yaml
# i18n-matrix: discovers languages
@@ -327,7 +327,7 @@ LANGS=$(ls src/i18n/messages/*.json | xargs -n1 basename | sed 's/.json$//' | gr
python3 scripts/validate_translation.py quick -l '${{ matrix.lang }}'
```
**Dashboard output:**
**Keluaran dashboard:**
```
## 🌍 Translations
@@ -339,63 +339,63 @@ python3 scripts/validate_translation.py quick -l '${{ matrix.lang }}'
✅ All translations complete
```
## File Structure
## Struktur File
```
src/i18n/
├── config.ts # Locale definitions (30 locales, RTL config)
├── request.ts # Runtime locale resolution
├── config.ts # Definisi lokal (30 lokal, konfigurasi RTL)
├── request.ts # Resolusi lokal saat runtime
└── messages/
├── en.json # Source of truth (~2800 keys)
├── cs.json # Czech translation
├── de.json # German translation
└── ... # 30 locale files total
├── en.json # Sumber kebenaran (~2800 kunci)
├── cs.json # Terjemahan bahasa Ceko
├── de.json # Terjemahan bahasa Jerman
└── ... # Total 30 file lokal
scripts/
├── i18n/
│ ├── generate-multilang.mjs # Auto-translation engine (Google Translate, 888 lines)
│ ├── generate-qa-checklist.mjs # Static analysis QA
│ ├── run-visual-qa.mjs # Playwright visual QA
│ └── untranslatable-keys.json # Allowlist for validation (236 keys)
├── validate_translation.py # Translation validator
├── check_translations.py # Code-to-JSON key checker
└── i18n_autotranslate.py # LLM-based doc translator
│ ├── generate-multilang.mjs # Mesin terjemahan otomatis (Google Translate, 888 baris)
│ ├── generate-qa-checklist.mjs # QA analisis statis
│ ├── run-visual-qa.mjs # QA visual Playwright
│ └── untranslatable-keys.json # Daftar yang diizinkan untuk validasi (236 kunci)
├── validate_translation.py # Validator terjemahan
├── check_translations.py # Pemeriksa kunci kode ke JSON
└── i18n_autotranslate.py # Penerjemah dokumentasi berbasis LLM
.github/workflows/
└── ci.yml # i18n validation in CI matrix
└── ci.yml # Validasi i18n dalam matriks CI
docs/
├── I18N.md # This file — i18n toolchain documentation
├── I18N.md # File ini — dokumentasi toolchain i18n
├── i18n/
│ ├── README.md # Auto-generated language index
│ ├── cs/ # Czech docs
│ ├── README.md # Indeks bahasa yang dibuat otomatis
│ ├── cs/ # Dokumentasi bahasa Ceko
│ │ └── docs/
│ │ ├── I18N.md # Czech translation of this file
│ │ ├── I18N.md # Terjemahan bahasa Ceko dari file ini
│ │ └── ...
│ ├── de/ # German docs
│ └── ... # 30 locale directories
│ ├── de/ # Dokumentasi bahasa Jerman
│ └── ... # 30 direktori lokal
└── reports/
├── i18n-qa-checklist-*.md # Static analysis reports
└── i18n-visual-qa-*.md # Visual QA reports
├── i18n-qa-checklist-*.md # Laporan analisis statis
└── i18n-visual-qa-*.md # Laporan QA visual
```
## Best Practices
## Praktik Terbaik
### When Editing Translations
### Saat Mengedit Terjemahan
1. **Always edit `en.json` first** — it's the source of truth
2. **Run `generate-multilang.mjs messages`** to propagate new keys to all locales
3. **Review auto-translations** — Google Translate is a starting point, not final
4. **Validate before committing**`python3 scripts/validate_translation.py quick -l <lang>`
5. **Update `untranslatable-keys.json`** if a key should remain in English
1. **Selalu edit `en.json` terlebih dahulu** — itulah sumber kebenaran
2. **Jalankan `generate-multilang.mjs messages`** untuk menyebarkan kunci baru ke semua lokal
3. **Tinjau terjemahan otomatis** — Google Translate hanyalah titik awal, bukan hasil akhir
4. **Validasi sebelum melakukan commit**`python3 scripts/validate_translation.py quick -l <lang>`
5. **Perbarui `untranslatable-keys.json`** jika sebuah kunci harus tetap dalam bahasa Inggris
### Placeholder Safety
### Keamanan Placeholder
- ICU placeholders (`{count}`, `{value}`, `{total}`, `{seconds}`) must be preserved exactly
- Plural formats (`{count, plural, one {# model} other {# models}}`) must maintain structure
- The validator detects placeholder mismatches automatically
- Placeholder ICU (`{count}`, `{value}`, `{total}`, `{seconds}`) harus dipertahankan persis sama
- Format jamak (`{count, plural, one {# model} other {# models}}`) harus mempertahankan strukturnya
- Validator mendeteksi ketidaksesuaian placeholder secara otomatis
### Adding New Translation Keys in Code
### Menambahkan Kunci Terjemahan Baru dalam Kode
```tsx
// Use namespaced keys
@@ -406,33 +406,33 @@ t("cacheSettings"); // maps to settings.cacheSettings in JSON
python3 scripts/check_translations.py --verbose
```
### RTL Considerations
### Pertimbangan RTL
- Arabic (`ar`) and Hebrew (`he`) are RTL locales
- Avoid hardcoded `left`/`right` CSS — use `start`/`end` logical properties
- Visual QA catches RTL layout mismatches via `run-visual-qa.mjs`
- Bahasa Arab (`ar`) dan Ibrani (`he`) adalah lokal RTL
- Hindari `left`/`right` CSS yang dikodekan keras — gunakan properti logis `start`/`end`
- QA visual menangkap ketidaksesuaian tata letak RTL melalui `run-visual-qa.mjs`
## Known Issues & History
## Masalah yang Diketahui & Riwayat
### `in.json` → `hi.json` Fix
### Perbaikan `in.json` → `hi.json`
The generator originally used `code: "in"` (deprecated Google Translate code) for Hindi instead of the correct ISO 639-1 `hi`. This created an orphaned `in.json` duplicate of `hi.json`. Fixed by changing `code: "in"` to `code: "hi"` in `generate-multilang.mjs` and removing the orphaned file.
Generator awalnya menggunakan `code: "in"` (kode Google Translate yang sudah usang) untuk bahasa Hindi, bukan ISO 639-1 yang benar yaitu `hi`. Hal ini menciptakan duplikat `in.json` yang tidak terhubung dari `hi.json`. Diperbaiki dengan mengubah `code: "in"` menjadi `code: "hi"` di `generate-multilang.mjs` dan menghapus file yang tidak terhubung tersebut.
### `docs/i18n/README.md` Is Auto-Generated
### `docs/i18n/README.md` Dibuat Secara Otomatis
The `docs/i18n/README.md` file is completely regenerated by `generate-multilang.mjs docs`. Any manual edits will be lost. Use `docs/guides/I18N.md` (this file) for hand-written documentation that should persist.
File `docs/i18n/README.md` sepenuhnya dihasilkan ulang oleh `generate-multilang.mjs docs`. Setiap pengeditan manual akan hilang. Gunakan `docs/guides/I18N.md` (file ini) untuk dokumentasi yang ditulis tangan yang harus tetap ada.
### External Untranslatable Keys List
### Daftar Kunci yang Tidak Dapat Diterjemahkan Eksternal
The `untranslatable-keys.json` allowlist was moved from an inline Python set in `validate_translation.py` to an external JSON file for easier maintenance. The validator loads it at runtime.
Daftar yang diizinkan `untranslatable-keys.json` dipindahkan dari set Python inline di `validate_translation.py` ke file JSON eksternal agar lebih mudah dipelihara. Validator memuatnya saat runtime.
### `generate-multilang.mjs` Hindi Code Fix
### Perbaikan Kode Hindi di `generate-multilang.mjs`
The generator originally used `code: "in"` (deprecated Google Translate code) for Hindi instead of the correct ISO 639-1 `hi`. This was introduced in upstream commit `952b0b22c` by `diegosouzapw`. Fixed by changing `code: "in"` to `code: "hi"` in the `LOCALE_SPECS` array and removing the orphaned `in.json` file.
Generator awalnya menggunakan `code: "in"` (kode Google Translate yang sudah usang) untuk bahasa Hindi, bukan ISO 639-1 yang benar yaitu `hi`. Ini diperkenalkan dalam commit upstream `952b0b22c` oleh `diegosouzapw`. Diperbaiki dengan mengubah `code: "in"` menjadi `code: "hi"` di array `LOCALE_SPECS` dan menghapus file `in.json` yang tidak terhubung.
### `validate_translation.py` Ignored Count Output
### Keluaran Jumlah Kunci yang Diabaikan di `validate_translation.py`
The `quick` check now displays the count of ignored keys from `untranslatable-keys.json`:
Pemeriksaan `quick` kini menampilkan jumlah kunci yang diabaikan dari `untranslatable-keys.json`:
```
Missing: 0

View File

@@ -1,72 +1,72 @@
# Troubleshooting (Bahasa Indonesia)
# Pemecahan Masalah (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇧🇩 [bn](../../bn/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇮🇷 [fa](../../fa/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇮🇳 [gu](../../gu/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇮🇳 [hi](../../hi/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇮🇳 [mr](../../mr/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇰🇪 [sw](../../sw/docs/TROUBLESHOOTING.md) · 🇮🇳 [ta](../../ta/docs/TROUBLESHOOTING.md) · 🇮🇳 [te](../../te/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇹🇷 [tr](../../tr/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇵🇰 [ur](../../ur/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md)
---
Common problems and solutions for OmniRoute.
Masalah umum dan solusinya untuk OmniRoute.
---
## Quick Fixes
## Perbaikan Cepat
| Problem | Solution |
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
| No logs written to disk | Set `APP_LOG_TO_FILE=true` and verify call log capture is enabled |
| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
| Login crash / blank page | Check Node.js version — see [Node.js Compatibility](#nodejs-compatibility) below |
| `dlopen` / `slice is not valid mach-o file` (macOS) | Run `cd $(npm root -g)/omniroute/app && npm rebuild better-sqlite3 && omniroute`see [macOS native module rebuild](#macos-native-module-rebuild) below |
| Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below |
| Masalah | Solusi |
| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Login pertama tidak berfungsi | Atur `INITIAL_PASSWORD` di `.env` (tidak ada nilai default yang dikodekan langsung) |
| Dashboard terbuka di port yang salah | Atur `PORT=20128` dan `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
| Tidak ada log yang ditulis ke disk | Atur `APP_LOG_TO_FILE=true` dan pastikan pengambilan log panggilan diaktifkan |
| EACCES: permission denied | Atur `DATA_DIR=/path/to/writable/dir` untuk mengganti `~/.omniroute` |
| Strategi routing tidak tersimpan | Perbarui ke v1.4.11+ (perbaikan skema Zod untuk persistensi pengaturan) |
| Login crash / halaman kosong | Periksa versi Node.js — lihat [Kompatibilitas Node.js](#nodejs-compatibility) di bawah |
| `dlopen` / `slice is not valid mach-o file` (macOS) | Jalankan `cd $(npm root -g)/omniroute/app && npm rebuild better-sqlite3 && omniroute`lihat [Pembangunan ulang modul native macOS](#macos-native-module-rebuild) di bawah |
| Proxy "fetch failed" | Pastikan konfigurasi proxy diatur pada tingkat yang tepat — lihat [Masalah Proxy](#proxy-issues) di bawah |
---
## Node.js Compatibility
## Kompatibilitas Node.js
<a name="nodejs-compatibility"></a>
### Login page crashes or shows "Module self-registration" error
### Halaman login crash atau menampilkan error "Module self-registration"
**Cause:** You are running a Node.js version outside OmniRoute's approved secure runtime floor. The most common case is running an older Node 20, 22, or 24 patch level that falls below the patched security floor OmniRoute requires.
**Penyebab:** Anda menjalankan versi Node.js di luar batas runtime aman yang disetujui OmniRoute. Kasus paling umum adalah menjalankan Node 20, 22, atau 24 versi patch lama yang berada di bawah batas keamanan yang diperlukan OmniRoute.
**Symptoms:**
**Gejala:**
- Login page shows a blank screen or a server error
- Console shows `Error: Module did not self-register` or similar native binding errors
- The login page shows an **orange warning banner** with your Node version if the runtime is outside the supported secure policy
- Halaman login menampilkan layar kosong atau error server
- Konsol menampilkan `Error: Module did not self-register` atau error binding native serupa
- Halaman login menampilkan **banner peringatan oranye** dengan versi Node Anda jika runtime berada di luar kebijakan keamanan yang didukung
**Fix:**
**Solusi:**
1. Install a supported Node.js LTS release (recommended: Node.js 24.x):
1. Instal rilis Node.js LTS yang didukung (disarankan: Node.js 24.x):
```bash
nvm install 24
nvm use 24
```
2. Verify your version: `node --version` should show `v24.0.0` or newer on the 24.x LTS line
3. Reinstall OmniRoute: `npm install -g omniroute`
4. Restart: `omniroute`
2. Verifikasi versi Anda: `node --version` seharusnya menampilkan `v24.0.0` atau lebih baru pada lini LTS 24.x
3. Instal ulang OmniRoute: `npm install -g omniroute`
4. Mulai ulang: `omniroute`
> **Supported secure versions:** `>=20.20.2 <21`, `>=22.22.2 <23`, or `>=24.0.0 <25`. Node.js 24.x LTS (Krypton) is fully supported.
> **Versi aman yang didukung:** `>=20.20.2 <21`, `>=22.22.2 <23`, atau `>=24.0.0 <25`. Node.js 24.x LTS (Krypton) sepenuhnya didukung.
### macOS: `dlopen` / "slice is not valid mach-o file"
<a name="macos-native-module-rebuild"></a>
**Cause:** After a global `npm install -g omniroute`, the `better-sqlite3` native binary inside the package may have been compiled for a different architecture or Node.js ABI than what is running locally. This is common on macOS (both Apple Silicon and Intel) when the pre-built binary does not match your environment.
**Penyebab:** Setelah `npm install -g omniroute` secara global, biner native `better-sqlite3` di dalam paket mungkin telah dikompilasi untuk arsitektur atau ABI Node.js yang berbeda dari yang berjalan secara lokal. Hal ini umum terjadi di macOS (baik Apple Silicon maupun Intel) ketika biner yang sudah dibangun tidak cocok dengan lingkungan Anda.
**Symptoms:**
**Gejala:**
- Server fails immediately on startup with a `dlopen` error
- Error contains `slice is not valid mach-o file`
- Full example:
- Server gagal langsung saat startup dengan error `dlopen`
- Error berisi `slice is not valid mach-o file`
- Contoh lengkap:
```
dlopen(/Users/<user>/.nvm/versions/node/v24.14.1/lib/node_modules/omniroute/app/node_modules/better-sqlite3/build/Release/better_sqlite3.node, 0x0001): tried: '...' (slice is not valid mach-o file)
```
**Fix — rebuild for your local environment (no Node.js downgrade required):**
**Solusi — bangun ulang untuk lingkungan lokal Anda (tidak perlu downgrade Node.js):**
```bash
cd $(npm root -g)/omniroute/app
@@ -74,98 +74,98 @@ npm rebuild better-sqlite3
omniroute
```
> **Note:** This recompiles the native binding against your local Node.js version and CPU architecture, resolving the binary mismatch. The officially supported range is **`>=20.20.2 <21`, `>=22.22.2 <23`, or `>=24.0.0 <25`** (`engines` field in `package.json`). Node.js 24.x LTS (Krypton) is fully supported with `better-sqlite3` v12.x.
> **Catatan:** Perintah ini mengompilasi ulang binding native terhadap versi Node.js dan arsitektur CPU lokal Anda, mengatasi ketidakcocokan biner. Rentang yang resmi didukung adalah **`>=20.20.2 <21`, `>=22.22.2 <23`, atau `>=24.0.0 <25`** (kolom `engines` di `package.json`). Node.js 24.x LTS (Krypton) sepenuhnya didukung dengan `better-sqlite3` v12.x.
---
## Proxy Issues
## Masalah Proxy
<a name="proxy-issues"></a>
### Provider validation shows "fetch failed"
### Validasi penyedia menampilkan "fetch failed"
**Cause:** The API key validation endpoint (`POST /api/providers/validate`) was previously bypassing proxy configuration, causing failures in environments that require proxy routing.
**Penyebab:** Endpoint validasi API key (`POST /api/providers/validate`) sebelumnya mengabaikan konfigurasi proxy, menyebabkan kegagalan di lingkungan yang memerlukan routing melalui proxy.
**Fix (v3.5.5+):** This is now fixed. Provider validation routes through `runWithProxyContext`, honoring provider-level and global proxy settings automatically.
**Solusi (v3.5.5+):** Masalah ini sudah diperbaiki. Validasi penyedia sekarang melewati `runWithProxyContext`, mengikuti pengaturan proxy pada tingkat penyedia dan global secara otomatis.
### Token health check fails with "fetch failed"
### Pemeriksaan kesehatan token gagal dengan "fetch failed"
**Cause:** Background OAuth token refresh was not resolving proxy configuration per connection.
**Penyebab:** Pembaruan token OAuth di latar belakang tidak menyelesaikan konfigurasi proxy per koneksi.
**Fix (v3.5.5+):** The token health check scheduler now resolves proxy config per connection before attempting refresh. Update to v3.5.5+.
**Solusi (v3.5.5+):** Penjadwal pemeriksaan kesehatan token sekarang menyelesaikan konfigurasi proxy per koneksi sebelum mencoba pembaruan. Perbarui ke v3.5.5+.
### SOCKS5 proxy returns "invalid onRequestStart method"
### Proxy SOCKS5 mengembalikan "invalid onRequestStart method"
**Cause:** On Node.js 22, the undici@8 dispatcher is incompatible with Node's built-in `fetch()` implementation.
**Penyebab:** Pada Node.js 22, dispatcher undici@8 tidak kompatibel dengan implementasi `fetch()` bawaan Node.
**Fix (v3.5.5+):** OmniRoute now uses undici's own `fetch()` function when a proxy dispatcher is active, ensuring consistent behavior. Update to v3.5.5+.
**Solusi (v3.5.5+):** OmniRoute sekarang menggunakan fungsi `fetch()` milik undici sendiri ketika dispatcher proxy aktif, memastikan perilaku yang konsisten. Perbarui ke v3.5.5+.
---
## Provider Issues
## Masalah Penyedia
### "Language model did not provide messages"
**Cause:** Provider quota exhausted.
**Penyebab:** Kuota penyedia habis.
**Fix:**
**Solusi:**
1. Check dashboard quota tracker
2. Use a combo with fallback tiers
3. Switch to cheaper/free tier
1. Periksa pelacak kuota di dashboard
2. Gunakan combo dengan tier fallback
3. Beralih ke tier yang lebih murah/gratis
### Rate Limiting
### Pembatasan Laju (Rate Limiting)
**Cause:** Subscription quota exhausted.
**Penyebab:** Kuota langganan habis.
**Fix:**
**Solusi:**
- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
- Use GLM/MiniMax as cheap backup
- Tambahkan fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
- Gunakan GLM/MiniMax sebagai cadangan murah
### OAuth Token Expired
### Token OAuth Kedaluwarsa
OmniRoute auto-refreshes tokens. If issues persist:
OmniRoute memperbarui token secara otomatis. Jika masalah berlanjut:
1. Dashboard → Provider → Reconnect
2. Delete and re-add the provider connection
1. Dashboard → Penyedia → Sambungkan Ulang
2. Hapus dan tambahkan ulang koneksi penyedia
---
## Cloud Issues
## Masalah Cloud
### Cloud Sync Errors
### Error Sinkronisasi Cloud
1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
1. Pastikan `BASE_URL` mengarah ke instans yang sedang berjalan (misalnya, `http://localhost:20128`)
2. Pastikan `CLOUD_URL` mengarah ke endpoint cloud Anda (misalnya, `https://omniroute.dev`)
3. Jaga agar nilai `NEXT_PUBLIC_*` selaras dengan nilai sisi server
### Cloud `stream=false` Returns 500
### Cloud `stream=false` Mengembalikan 500
**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
**Gejala:** `Unexpected token 'd'...` pada endpoint cloud untuk panggilan non-streaming.
**Cause:** Upstream returns SSE payload while client expects JSON.
**Penyebab:** Upstream mengembalikan payload SSE sementara klien mengharapkan JSON.
**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
**Solusi Sementara:** Gunakan `stream=true` untuk panggilan langsung ke cloud. Runtime lokal sudah menyertakan fallback SSE→JSON.
### Cloud Says Connected but "Invalid API key"
### Cloud Menunjukkan Terhubung tetapi "Invalid API key"
1. Create a fresh key from local dashboard (`/api/keys`)
2. Run cloud sync: Enable Cloud → Sync Now
3. Old/non-synced keys can still return `401` on cloud
1. Buat kunci baru dari dashboard lokal (`/api/keys`)
2. Jalankan sinkronisasi cloud: Aktifkan Cloud → Sinkronkan Sekarang
3. Kunci lama/yang tidak tersinkronisasi masih dapat mengembalikan `401` di cloud
---
## Docker Issues
## Masalah Docker
### CLI Tool Shows Not Installed
### Alat CLI Menampilkan Belum Terinstal
1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
2. For portable mode: use image target `runner-cli` (bundled CLIs)
3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
1. Periksa kolom runtime: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
2. Untuk mode portabel: gunakan target image `runner-cli` (CLI yang sudah dibundel)
3. Untuk mode mount host: atur `CLI_EXTRA_PATHS` dan mount direktori bin host sebagai read-only
4. Jika `installed=true` dan `runnable=false`: biner ditemukan tetapi gagal healthcheck
### Quick Runtime Validation
### Validasi Runtime Cepat
```bash
curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
@@ -175,26 +175,26 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,
---
## Cost Issues
## Masalah Biaya
### High Costs
### Biaya Tinggi
1. Check usage stats in Dashboard → Usage
2. Switch primary model to GLM/MiniMax
3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
4. Set cost budgets per API key: Dashboard → API Keys → Budget
1. Periksa statistik penggunaan di Dashboard → Penggunaan
2. Beralih model utama ke GLM/MiniMax
3. Gunakan tier gratis (Gemini CLI, Qoder) untuk tugas yang tidak kritis
4. Atur anggaran biaya per API key: Dashboard → API Keys → Anggaran
---
## Debugging
### Enable Log Files
### Aktifkan File Log
Set `APP_LOG_TO_FILE=true` in your `.env` file. Application logs are written under `logs/`.
Request artifacts are stored under `${DATA_DIR}/call_logs/` when the call log pipeline is
enabled in settings.
Atur `APP_LOG_TO_FILE=true` di file `.env` Anda. Log aplikasi ditulis di bawah `logs/`.
Artefak permintaan disimpan di bawah `${DATA_DIR}/call_logs/` ketika pipeline log panggilan
diaktifkan di pengaturan.
### Check Provider Health
### Periksa Kesehatan Penyedia
```bash
# Health dashboard
@@ -204,138 +204,138 @@ http://localhost:20128/dashboard/health
curl http://localhost:20128/api/monitoring/health
```
### Runtime Storage
### Penyimpanan Runtime
- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/call_logs/`
- Application logs: `<repo>/logs/...` (when `APP_LOG_TO_FILE=true`)
- Call log artifacts: `${DATA_DIR}/call_logs/YYYY-MM-DD/...` when the call log pipeline is enabled
- Status utama: `${DATA_DIR}/storage.sqlite` (penyedia, combo, alias, kunci, pengaturan)
- Penggunaan: tabel SQLite di `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + opsional `${DATA_DIR}/call_logs/`
- Log aplikasi: `<repo>/logs/...` (ketika `APP_LOG_TO_FILE=true`)
- Artefak log panggilan: `${DATA_DIR}/call_logs/YYYY-MM-DD/...` ketika pipeline log panggilan diaktifkan
---
## Circuit Breaker Issues
## Masalah Circuit Breaker
### Provider stuck in OPEN state
### Penyedia terjebak dalam status OPEN
When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
Ketika circuit breaker penyedia dalam status OPEN, permintaan diblokir hingga cooldown berakhir.
**Fix:**
**Solusi:**
1. Go to **Dashboard → Settings → Resilience**
2. Check the circuit breaker card for the affected provider
3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
4. Verify the provider is actually available before resetting
1. Buka **Dashboard → Settings → Resilience**
2. Periksa kartu circuit breaker untuk penyedia yang terdampak
3. Klik **Reset All** untuk menghapus semua breaker, atau tunggu hingga cooldown berakhir
4. Pastikan penyedia benar-benar tersedia sebelum melakukan reset
### Provider keeps tripping the circuit breaker
### Penyedia terus memicu circuit breaker
If a provider repeatedly enters OPEN state:
Jika penyedia berulang kali masuk ke status OPEN:
1. Check **Dashboard → Health → Provider Health** for the failure pattern
2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
3. Check if the provider has changed API limits or requires re-authentication
4. Review latency telemetry — high latency may cause timeout-based failures
1. Periksa **Dashboard → Health → Provider Health** untuk pola kegagalan
2. Buka **Settings → Resilience → Provider Profiles** dan tingkatkan ambang batas kegagalan
3. Periksa apakah penyedia telah mengubah batas API atau memerlukan autentikasi ulang
4. Tinjau telemetri latensi — latensi tinggi dapat menyebabkan kegagalan berbasis timeout
---
## Audio Transcription Issues
## Masalah Transkripsi Audio
### "Unsupported model" error
### Error "Unsupported model"
- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
- Verify the provider is connected in **Dashboard → Providers**
- Pastikan Anda menggunakan awalan yang tepat: `deepgram/nova-3` atau `assemblyai/best`
- Pastikan penyedia terhubung di **Dashboard → Providers**
### Transcription returns empty or fails
### Transkripsi mengembalikan hasil kosong atau gagal
- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
- Verify file size is within provider limits (typically < 25MB)
- Check provider API key validity in the provider card
- Periksa format audio yang didukung: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
- Pastikan ukuran file berada dalam batas penyedia (biasanya < 25MB)
- Periksa validitas API key penyedia di kartu penyedia
---
## Translator Debugging
## Debugging Translator
Use **Dashboard → Translator** to debug format translation issues:
Gunakan **Dashboard → Translator** untuk melakukan debug masalah terjemahan format:
| Mode | When to Use |
| ---------------- | -------------------------------------------------------------------------------------------- |
| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
| Mode | Kapan Digunakan |
| ---------------- | ------------------------------------------------------------------------------------------------------------ |
| **Playground** | Bandingkan format input/output berdampingan — tempel permintaan yang gagal untuk melihat cara terjemahannya |
| **Chat Tester** | Kirim pesan langsung dan periksa payload permintaan/respons lengkap termasuk header |
| **Test Bench** | Jalankan pengujian batch di berbagai kombinasi format untuk menemukan terjemahan mana yang rusak |
| **Live Monitor** | Pantau aliran permintaan secara real-time untuk menangkap masalah terjemahan yang intermiten |
### Common format issues
### Masalah format yang umum
- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
- **Tag thinking tidak muncul** — Periksa apakah penyedia target mendukung thinking dan pengaturan anggaran thinking
- **Tool call hilang** — Beberapa terjemahan format mungkin menghapus kolom yang tidak didukung; verifikasi di mode Playground
- **System prompt hilang** — Claude dan Gemini menangani system prompt secara berbeda; periksa output terjemahan
- **SDK mengembalikan string mentah alih-alih objek** — Diperbaiki di v1.1.0: sanitizer respons sekarang menghapus kolom non-standar (`x_groq`, `usage_breakdown`, dll.) yang menyebabkan kegagalan validasi Pydantic SDK OpenAI
- **GLM/ERNIE menolak role `system`** — Diperbaiki di v1.1.0: normalizer role secara otomatis menggabungkan pesan sistem ke dalam pesan pengguna untuk model yang tidak kompatibel
- **Role `developer` tidak dikenali** — Diperbaiki di v1.1.0: secara otomatis dikonversi ke `system` untuk penyedia non-OpenAI
- **`json_schema` tidak berfungsi dengan Gemini** — Diperbaiki di v1.1.0: `response_format` sekarang dikonversi ke `responseMimeType` + `responseSchema` milik Gemini
---
## Resilience Settings
## Pengaturan Resiliensi
### Auto rate-limit not triggering
### Auto rate-limit tidak terpicu
- Auto rate-limit only applies to API key providers (not OAuth/subscription)
- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
- Check if the provider returns `429` status codes or `Retry-After` headers
- Auto rate-limit hanya berlaku untuk penyedia dengan API key (bukan OAuth/langganan)
- Pastikan **Settings → Resilience → Provider Profiles** telah mengaktifkan auto rate-limit
- Periksa apakah penyedia mengembalikan kode status `429` atau header `Retry-After`
### Tuning exponential backoff
### Menyetel exponential backoff
Provider profiles support these settings:
Profil penyedia mendukung pengaturan berikut:
- **Base delay** — Initial wait time after first failure (default: 1s)
- **Max delay** — Maximum wait time cap (default: 30s)
- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
- **Base delay** — Waktu tunggu awal setelah kegagalan pertama (default: 1s)
- **Max delay** — Batas maksimum waktu tunggu (default: 30s)
- **Multiplier** — Seberapa banyak penundaan ditingkatkan per kegagalan berturut-turut (default: 2x)
### Anti-thundering herd
When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
Ketika banyak permintaan bersamaan mengenai penyedia yang dibatasi lajunya, OmniRoute menggunakan mutex + auto rate-limiting untuk membuat serialisasi permintaan dan mencegah kegagalan berantai. Ini berjalan otomatis untuk penyedia dengan API key.
---
## Optional RAG / LLM failure taxonomy (16 problems)
## Taksonomi Kegagalan RAG / LLM Opsional (16 masalah)
Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
Beberapa pengguna OmniRoute menempatkan gateway di depan tumpukan RAG atau agen. Dalam pengaturan tersebut, umum terjadi pola yang aneh: OmniRoute terlihat sehat (penyedia aktif, profil routing baik, tidak ada peringatan batas laju) tetapi jawaban akhir masih salah.
In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
Dalam praktiknya, insiden ini biasanya berasal dari pipeline RAG downstream, bukan dari gateway itu sendiri.
If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
Jika Anda menginginkan kosakata bersama untuk mendeskripsikan kegagalan tersebut, Anda dapat menggunakan WFGY ProblemMap, sebuah sumber daya teks berlisensi MIT eksternal yang mendefinisikan enam belas pola kegagalan RAG / LLM yang berulang. Secara garis besar, ini mencakup:
- retrieval drift and broken context boundaries
- empty or stale indexes and vector stores
- embedding versus semantic mismatch
- prompt assembly and context window issues
- logic collapse and overconfident answers
- long chain and agent coordination failures
- multi agent memory and role drift
- deployment and bootstrap ordering problems
- pergeseran retrieval dan batas konteks yang rusak
- indeks dan vector store yang kosong atau sudah usang
- ketidakcocokan embedding versus semantik
- masalah perakitan prompt dan jendela konteks
- keruntuhan logika dan jawaban yang terlalu percaya diri
- kegagalan rantai panjang dan koordinasi agen
- memori multi-agen dan pergeseran peran
- masalah urutan deployment dan bootstrap
The idea is simple:
Idenya sederhana:
1. When you investigate a bad response, capture:
- user task and request
- route or provider combo in OmniRoute
- any RAG context used downstream (retrieved documents, tool calls, etc)
2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
1. Saat Anda menyelidiki respons yang buruk, kumpulkan:
- tugas pengguna dan permintaan
- route atau combo penyedia di OmniRoute
- konteks RAG apa pun yang digunakan di downstream (dokumen yang diambil, tool call, dll.)
2. Petakan insiden ke satu atau dua nomor WFGY ProblemMap (`No.1` … `No.16`).
3. Simpan nomornya di dashboard, runbook, atau pelacak insiden Anda sendiri di samping log OmniRoute.
4. Gunakan halaman WFGY yang sesuai untuk memutuskan apakah Anda perlu mengubah tumpukan RAG, retriever, atau strategi routing Anda.
Full text and concrete recipes live here (MIT license, text only):
Teks lengkap dan resep konkret tersedia di sini (lisensi MIT, hanya teks):
[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
Anda dapat mengabaikan bagian ini jika Anda tidak menjalankan pipeline RAG atau agen di belakang OmniRoute.
---
## Still Stuck?
## Masih Terjebak?
- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **Architecture**: See [`docs/architecture/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
- **API Reference**: See [`docs/reference/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
- **Translator**: Use **Dashboard → Translator** to debug format issues
- **Arsitektur**: Lihat [`docs/architecture/ARCHITECTURE.md`](ARCHITECTURE.md) untuk detail internal
- **Referensi API**: Lihat [`docs/reference/API_REFERENCE.md`](API_REFERENCE.md) untuk semua endpoint
- **Health Dashboard**: Periksa **Dashboard → Health** untuk status sistem secara real-time
- **Translator**: Gunakan **Dashboard → Translator** untuk melakukan debug masalah format

View File

@@ -1,46 +1,46 @@
# OmniRoute — Uninstall Guide (Bahasa Indonesia)
# OmniRoute — Panduan Mencopot Pemasangan (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/UNINSTALL.md) · 🇸🇦 [ar](../../ar/docs/UNINSTALL.md) · 🇧🇬 [bg](../../bg/docs/UNINSTALL.md) · 🇧🇩 [bn](../../bn/docs/UNINSTALL.md) · 🇨🇿 [cs](../../cs/docs/UNINSTALL.md) · 🇩🇰 [da](../../da/docs/UNINSTALL.md) · 🇩🇪 [de](../../de/docs/UNINSTALL.md) · 🇪🇸 [es](../../es/docs/UNINSTALL.md) · 🇮🇷 [fa](../../fa/docs/UNINSTALL.md) · 🇫🇮 [fi](../../fi/docs/UNINSTALL.md) · 🇫🇷 [fr](../../fr/docs/UNINSTALL.md) · 🇮🇳 [gu](../../gu/docs/UNINSTALL.md) · 🇮🇱 [he](../../he/docs/UNINSTALL.md) · 🇮🇳 [hi](../../hi/docs/UNINSTALL.md) · 🇭🇺 [hu](../../hu/docs/UNINSTALL.md) · 🇮🇩 [id](../../id/docs/UNINSTALL.md) · 🇮🇹 [it](../../it/docs/UNINSTALL.md) · 🇯🇵 [ja](../../ja/docs/UNINSTALL.md) · 🇰🇷 [ko](../../ko/docs/UNINSTALL.md) · 🇮🇳 [mr](../../mr/docs/UNINSTALL.md) · 🇲🇾 [ms](../../ms/docs/UNINSTALL.md) · 🇳🇱 [nl](../../nl/docs/UNINSTALL.md) · 🇳🇴 [no](../../no/docs/UNINSTALL.md) · 🇵🇭 [phi](../../phi/docs/UNINSTALL.md) · 🇵🇱 [pl](../../pl/docs/UNINSTALL.md) · 🇵🇹 [pt](../../pt/docs/UNINSTALL.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/UNINSTALL.md) · 🇷🇴 [ro](../../ro/docs/UNINSTALL.md) · 🇷🇺 [ru](../../ru/docs/UNINSTALL.md) · 🇸🇰 [sk](../../sk/docs/UNINSTALL.md) · 🇸🇪 [sv](../../sv/docs/UNINSTALL.md) · 🇰🇪 [sw](../../sw/docs/UNINSTALL.md) · 🇮🇳 [ta](../../ta/docs/UNINSTALL.md) · 🇮🇳 [te](../../te/docs/UNINSTALL.md) · 🇹🇭 [th](../../th/docs/UNINSTALL.md) · 🇹🇷 [tr](../../tr/docs/UNINSTALL.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/UNINSTALL.md) · 🇵🇰 [ur](../../ur/docs/UNINSTALL.md) · 🇻🇳 [vi](../../vi/docs/UNINSTALL.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/UNINSTALL.md)
---
This guide covers how to cleanly remove OmniRoute from your system.
Panduan ini menjelaskan cara mencopot pemasangan OmniRoute dari sistem Anda secara bersih.
---
## Quick Uninstall (v3.6.2+)
## Mencopot Pemasangan dengan Cepat (v3.6.2+)
OmniRoute provides two built-in scripts for clean removal:
OmniRoute menyediakan dua skrip bawaan untuk penghapusan yang bersih:
### Keep Your Data
### Pertahankan Data Anda
```bash
npm run uninstall
```
This removes the OmniRoute application but **preserves** your database, configurations, API keys, and provider settings in `~/.omniroute/`. Use this if you plan to reinstall later and want to keep your setup.
Perintah ini menghapus aplikasi OmniRoute tetapi **mempertahankan** basis data, konfigurasi, kunci API, dan pengaturan penyedia Anda di `~/.omniroute/`. Gunakan ini jika Anda berencana memasang ulang nanti dan ingin menyimpan pengaturan yang ada.
### Full Removal
### Penghapusan Penuh
```bash
npm run uninstall:full
```
This removes the application **and permanently erases** all data:
Perintah ini menghapus aplikasi **dan menghapus secara permanen** semua data:
- Database (`storage.sqlite`)
- Provider configurations and API keys
- Backup files
- Log files
- All files in the `~/.omniroute/` directory
- Basis data (`storage.sqlite`)
- Konfigurasi penyedia dan kunci API
- Berkas cadangan
- Berkas log
- Semua berkas di direktori `~/.omniroute/`
> ⚠️ **Warning:** `npm run uninstall:full` is irreversible. All your provider connections, combos, API keys, and usage history will be permanently deleted.
> ⚠️ **Peringatan:** `npm run uninstall:full` tidak dapat dibatalkan. Semua koneksi penyedia, combo, kunci API, dan riwayat penggunaan Anda akan dihapus secara permanen.
---
## Manual Uninstall
## Mencopot Pemasangan Secara Manual
### NPM Global Install
### Instalasi Global NPM
```bash
# Remove the global package
@@ -50,7 +50,7 @@ npm uninstall -g omniroute
rm -rf ~/.omniroute
```
### pnpm Global Install
### Instalasi Global pnpm
```bash
pnpm uninstall -g omniroute
@@ -81,24 +81,24 @@ docker compose down
docker compose down -v
```
### Electron Desktop App
### Aplikasi Desktop Electron
**Windows:**
- Open `Settings → Apps → OmniRoute → Uninstall`
- Or run the NSIS uninstaller from the install directory
- Buka `Settings → Apps → OmniRoute → Uninstall`
- Atau jalankan uninstaller NSIS dari direktori instalasi
**macOS:**
- Drag `OmniRoute.app` from `/Applications` to Trash
- Remove data: `rm -rf ~/Library/Application Support/omniroute`
- Seret `OmniRoute.app` dari `/Applications` ke Trash
- Hapus data: `rm -rf ~/Library/Application Support/omniroute`
**Linux:**
- Remove the AppImage file
- Remove data: `rm -rf ~/.omniroute`
- Hapus berkas AppImage
- Hapus data: `rm -rf ~/.omniroute`
### Source Install (git clone)
### Instalasi dari Sumber (git clone)
```bash
# Remove the cloned directory
@@ -110,11 +110,11 @@ rm -rf ~/.omniroute
---
## Data Directories
## Direktori Data
OmniRoute stores data in the following locations by default:
OmniRoute menyimpan data di lokasi-lokasi berikut secara default:
| Platform | Default Path | Override |
| Platform | Jalur Default | Pengganti |
| ------------- | ----------------------------- | ------------------------- |
| Linux | `~/.omniroute/` | `DATA_DIR` env var |
| macOS | `~/.omniroute/` | `DATA_DIR` env var |
@@ -122,22 +122,22 @@ OmniRoute stores data in the following locations by default:
| Docker | `/app/data/` (mounted volume) | `DATA_DIR` env var |
| XDG-compliant | `$XDG_CONFIG_HOME/omniroute/` | `XDG_CONFIG_HOME` env var |
### Files in the data directory
### Berkas di dalam direktori data
| File/Directory | Description |
| -------------------- | ------------------------------------------------- |
| `storage.sqlite` | Main database (providers, combos, settings, keys) |
| `storage.sqlite-wal` | SQLite write-ahead log (temporary) |
| `storage.sqlite-shm` | SQLite shared memory (temporary) |
| `call_logs/` | Request payload archives |
| `backups/` | Automatic database backups |
| `log.txt` | Legacy request log (optional) |
| Berkas/Direktori | Deskripsi |
| -------------------- | ------------------------------------------------------------ |
| `storage.sqlite` | Basis data utama (penyedia, combo, pengaturan, kunci) |
| `storage.sqlite-wal` | Write-ahead log SQLite (sementara) |
| `storage.sqlite-shm` | Shared memory SQLite (sementara) |
| `call_logs/` | Arsip payload permintaan |
| `backups/` | Cadangan basis data otomatis |
| `log.txt` | Log permintaan lama (opsional) |
---
## Verify Complete Removal
## Verifikasi Penghapusan Lengkap
After uninstalling, verify there are no remaining files:
Setelah mencopot pemasangan, verifikasi bahwa tidak ada berkas yang tersisa:
```bash
# Check for global npm package
@@ -150,7 +150,7 @@ ls -la ~/.omniroute/ 2>/dev/null
pgrep -f omniroute
```
If any process is still running, stop it:
Jika ada proses yang masih berjalan, hentikan dengan perintah berikut:
```bash
pkill -f omniroute

View File

@@ -1,119 +1,119 @@
# User Guide (Bahasa Indonesia)
# Panduan Pengguna (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇧🇩 [bn](../../bn/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇮🇷 [fa](../../fa/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇮🇳 [gu](../../gu/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇮🇳 [hi](../../hi/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇮🇳 [mr](../../mr/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇰🇪 [sw](../../sw/docs/USER_GUIDE.md) · 🇮🇳 [ta](../../ta/docs/USER_GUIDE.md) · 🇮🇳 [te](../../te/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇹🇷 [tr](../../tr/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇵🇰 [ur](../../ur/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md)
---
Complete guide for configuring providers, creating combos, integrating CLI tools, and deploying OmniRoute.
Panduan lengkap untuk mengonfigurasi penyedia, membuat combo, mengintegrasikan alat CLI, dan menerapkan OmniRoute.
---
## Table of Contents
## Daftar Isi
- [Pricing at a Glance](#-pricing-at-a-glance)
- [Use Cases](#-use-cases)
- [Provider Setup](#-provider-setup)
- [CLI Integration](#-cli-integration)
- [Deployment](#-deployment)
- [Available Models](#-available-models)
- [Advanced Features](#-advanced-features)
- [Harga Sekilas](#-harga-sekilas)
- [Kasus Penggunaan](#-kasus-penggunaan)
- [Pengaturan Penyedia](#-pengaturan-penyedia)
- [Integrasi CLI](#-integrasi-cli)
- [Penerapan](#penerapan)
- [Model yang Tersedia](#-model-yang-tersedia)
- [Fitur Lanjutan](#-fitur-lanjutan)
---
## 💰 Pricing at a Glance
## 💰 Harga Sekilas
| Tier | Provider | Cost | Quota Reset | Best For |
| ------------------- | ----------------- | ----------- | ---------------- | -------------------- |
| **💳 SUBSCRIPTION** | Claude Code (Pro) | $20/mo | 5h + weekly | Already subscribed |
| | Codex (Plus/Pro) | $20-200/mo | 5h + weekly | OpenAI users |
| | Gemini CLI | **FREE** | 180K/mo + 1K/day | Everyone! |
| | GitHub Copilot | $10-19/mo | Monthly | GitHub users |
| **🔑 API KEY** | DeepSeek | Pay per use | None | Cheap reasoning |
| | Groq | Pay per use | None | Ultra-fast inference |
| | xAI (Grok) | Pay per use | None | Grok 4 reasoning |
| | Mistral | Pay per use | None | EU-hosted models |
| | Perplexity | Pay per use | None | Search-augmented |
| | Together AI | Pay per use | None | Open-source models |
| | Fireworks AI | Pay per use | None | Fast FLUX images |
| | Cerebras | Pay per use | None | Wafer-scale speed |
| | Cohere | Pay per use | None | Command R+ RAG |
| | NVIDIA NIM | Pay per use | None | Enterprise models |
| **💰 CHEAP** | GLM-4.7 | $0.6/1M | Daily 10AM | Budget backup |
| | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option |
| | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost |
| **🆓 FREE** | Qoder | $0 | Unlimited | 8 models free |
| | Qwen | $0 | Unlimited | 3 models free |
| | Kiro | $0 | Unlimited | Claude free |
| Tingkatan | Penyedia | Biaya | Reset Kuota | Terbaik Untuk |
| ------------------- | ----------------- | ----------- | ---------------- | -------------------------- |
| **💳 LANGGANAN** | Claude Code (Pro) | $20/bln | 5j + mingguan | Sudah berlangganan |
| | Codex (Plus/Pro) | $20-200/bln | 5j + mingguan | Pengguna OpenAI |
| | Gemini CLI | **GRATIS** | 180K/bln + 1K/hr | Semua orang! |
| | GitHub Copilot | $10-19/bln | Bulanan | Pengguna GitHub |
| **🔑 KUNCI API** | DeepSeek | Bayar pakai | Tidak ada | Penalaran murah |
| | Groq | Bayar pakai | Tidak ada | Inferensi sangat cepat |
| | xAI (Grok) | Bayar pakai | Tidak ada | Penalaran Grok 4 |
| | Mistral | Bayar pakai | Tidak ada |Model berbasis EU |
| | Perplexity | Bayar pakai | Tidak ada | Dilengkapi pencarian |
| | Together AI | Bayar pakai | Tidak ada | Model sumber terbuka |
| | Fireworks AI | Bayar pakai | Tidak ada | Gambar FLUX cepat |
| | Cerebras | Bayar pakai | Tidak ada | Kecepatan skala wafer |
| | Cohere | Bayar pakai | Tidak ada | RAG Command R+ |
| | NVIDIA NIM | Bayar pakai | Tidak ada | Model enterprise |
| **💰 MURAH** | GLM-4.7 | $0.6/1M | Harian pukul 10 | Cadangan hemat |
| | MiniMax M2.1 | $0.2/1M | Bergulir 5 jam | Pilihan termurah |
| | Kimi K2 | $9/bln flat | 10M token/bln | Biaya yang dapat diprediksi|
| **🆓 GRATIS** | Qoder | $0 | Tidak terbatas | 8 model gratis |
| | Qwen | $0 | Tidak terbatas | 3 model gratis |
| | Kiro | $0 | Tidak terbatas | Claude gratis |
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + Qoder (unlimited free) combo = $0 cost!
**💡 Tips Pro:** Mulai dengan combo Gemini CLI (180K gratis/bulan) + Qoder (gratis tanpa batas) = biaya $0!
---
## 🎯 Use Cases
## 🎯 Kasus Penggunaan
### Case 1: "I have Claude Pro subscription"
### Kasus 1: "Saya punya langganan Claude Pro"
**Problem:** Quota expires unused, rate limits during heavy coding
**Masalah:** Kuota habis tidak terpakai, batas kecepatan saat coding intensif
```
Combo: "maximize-claude"
1. cc/claude-opus-4-7 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
1. cc/claude-opus-4-7 (gunakan langganan sepenuhnya)
2. glm/glm-4.7 (cadangan murah saat kuota habis)
3. if/kimi-k2-thinking (fallback darurat gratis)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
Biaya bulanan: $20 (langganan) + ~$5 (cadangan) = total $25
vs. $20 + terkena batas = frustrasi
```
### Case 2: "I want zero cost"
### Kasus 2: "Saya ingin biaya nol"
**Problem:** Can't afford subscriptions, need reliable AI coding
**Masalah:** Tidak mampu berlangganan, butuh AI coding yang andal
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
1. gc/gemini-3-flash (180K gratis/bulan)
2. if/kimi-k2-thinking (gratis tanpa batas)
3. qw/qwen3-coder-plus (gratis tanpa batas)
Monthly cost: $0
Quality: Production-ready models
Biaya bulanan: $0
Kualitas: Model siap produksi
```
### Case 3: "I need 24/7 coding, no interruptions"
### Kasus 3: "Saya butuh coding 24/7, tanpa gangguan"
**Problem:** Deadlines, can't afford downtime
**Masalah:** Tenggat waktu, tidak boleh ada downtime
```
Combo: "always-on"
1. cc/claude-opus-4-7 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
1. cc/claude-opus-4-7 (kualitas terbaik)
2. cx/gpt-5.2-codex (langganan kedua)
3. glm/glm-4.7 (murah, reset harian)
4. minimax/MiniMax-M2.1 (termurah, reset 5 jam)
5. if/kimi-k2-thinking (gratis tanpa batas)
Result: 5 layers of fallback = zero downtime
Monthly cost: $20-200 (subscriptions) + $10-20 (backup)
Hasil: 5 lapis fallback = nol downtime
Biaya bulanan: $20-200 (langganan) + $10-20 (cadangan)
```
### Case 4: "I want FREE AI in OpenClaw"
### Kasus 4: "Saya ingin AI GRATIS di OpenClaw"
**Problem:** Need AI assistant in messaging apps, completely free
**Masalah:** Perlu asisten AI di aplikasi pesan, sepenuhnya gratis
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
1. if/glm-4.7 (gratis tanpa batas)
2. if/minimax-m2.1 (gratis tanpa batas)
3. if/kimi-k2-thinking (gratis tanpa batas)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
Biaya bulanan: $0
Akses melalui: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 📖 Provider Setup
## 📖 Pengaturan Penyedia
### 🔐 Subscription Providers
### 🔐 Penyedia Berlangganan
#### Claude Code (Pro/Max)
@@ -128,7 +128,7 @@ Models:
cc/claude-haiku-4-5-20251001
```
**Pro Tip:** Use Opus for complex tasks, Sonnet for speed. OmniRoute tracks quota per model!
**Tips Pro:** Gunakan Opus untuk tugas kompleks, Sonnet untuk kecepatan. OmniRoute melacak kuota per model!
#### OpenAI Codex (Plus/Pro)
@@ -142,7 +142,7 @@ Models:
cx/gpt-5.1-codex-max
```
#### Gemini CLI (FREE 180K/month!)
#### Gemini CLI (GRATIS 180K/bulan!)
```bash
Dashboard → Providers → Connect Gemini CLI
@@ -154,7 +154,7 @@ Models:
gc/gemini-2.5-pro
```
**Best Value:** Huge free tier! Use this before paid tiers.
**Nilai Terbaik:** Tingkat gratis yang sangat besar! Gunakan ini sebelum tingkatan berbayar.
#### GitHub Copilot
@@ -169,33 +169,33 @@ Models:
gh/gemini-3.1-pro-preview
```
### 💰 Cheap Providers
### 💰 Penyedia Murah
#### GLM-4.7 (Daily reset, $0.6/1M)
#### GLM-4.7 (Reset harian, $0.6/1M)
1. Sign up: [Zhipu AI](https://open.bigmodel.cn/)
2. Get API key from Coding Plan
3. Dashboard → Add API Key: Provider: `glm`, API Key: `your-key`
1. Daftar: [Zhipu AI](https://open.bigmodel.cn/)
2. Dapatkan kunci API dari Coding Plan
3. Dasbor → Tambahkan Kunci API: Penyedia: `glm`, Kunci API: `your-key`
**Use:** `glm/glm-4.7`**Pro Tip:** Coding Plan offers 3× quota at 1/7 cost! Reset daily 10:00 AM.
**Gunakan:** `glm/glm-4.7`**Tips Pro:** Coding Plan menawarkan kuota 3× dengan biaya 1/7! Reset setiap hari pukul 10:00.
#### MiniMax M2.1 (5h reset, $0.20/1M)
#### MiniMax M2.1 (Reset 5 jam, $0.20/1M)
1. Sign up: [MiniMax](https://www.minimax.io/)
2. Get API key → Dashboard → Add API Key
1. Daftar: [MiniMax](https://www.minimax.io/)
2. Dapatkan kunci API → Dasbor → Tambahkan Kunci API
**Use:** `minimax/MiniMax-M2.1`**Pro Tip:** Cheapest option for long context (1M tokens)!
**Gunakan:** `minimax/MiniMax-M2.1`**Tips Pro:** Pilihan termurah untuk konteks panjang (1M token)!
#### Kimi K2 ($9/month flat)
#### Kimi K2 ($9/bulan flat)
1. Subscribe: [Moonshot AI](https://platform.moonshot.ai/)
2. Get API key → Dashboard → Add API Key
1. Berlangganan: [Moonshot AI](https://platform.moonshot.ai/)
2. Dapatkan kunci API → Dasbor → Tambahkan Kunci API
**Use:** `kimi/kimi-latest`**Pro Tip:** Fixed $9/month for 10M tokens = $0.90/1M effective cost!
**Gunakan:** `kimi/kimi-latest`**Tips Pro:** Tetap $9/bulan untuk 10M token = biaya efektif $0.90/1M!
### 🆓 FREE Providers
### 🆓 Penyedia GRATIS
#### Qoder (8 FREE models)
#### Qoder (8 model GRATIS)
```bash
Dashboard → Connect Qoder → OAuth login → Unlimited usage
@@ -203,7 +203,7 @@ Dashboard → Connect Qoder → OAuth login → Unlimited usage
Models: if/kimi-k2-thinking, if/qwen3-coder-plus, if/glm-4.7, if/minimax-m2, if/deepseek-r1
```
#### Qwen (3 FREE models)
#### Qwen (3 model GRATIS)
```bash
Dashboard → Connect Qwen → Device code auth → Unlimited usage
@@ -211,7 +211,7 @@ Dashboard → Connect Qwen → Device code auth → Unlimited usage
Models: qw/qwen3-coder-plus, qw/qwen3-coder-flash
```
#### Kiro (Claude FREE)
#### Kiro (Claude GRATIS)
```bash
Dashboard → Connect Kiro → AWS Builder ID or Google/GitHub → Unlimited
@@ -221,46 +221,46 @@ Models: kr/claude-sonnet-4.5, kr/claude-haiku-4.5
---
## 🎨 Combos
## 🎨 Combo
You can reorder combo cards directly in **Dashboard → Combos** by dragging the handle on each card. The order is stored in SQLite and restored on reload.
Anda dapat mengurutkan ulang kartu combo langsung di **Dashboard → Combos** dengan menyeret gagang pada setiap kartu. Urutan disimpan di SQLite dan dipulihkan saat dimuat ulang.
### Example 1: Maximize Subscription → Cheap Backup
### Contoh 1: Maksimalkan Langganan → Cadangan Murah
```
Dashboard → Combos → Create New
Name: premium-coding
Models:
1. cc/claude-opus-4-7 (Subscription primary)
2. glm/glm-4.7 (Cheap backup, $0.6/1M)
3. minimax/MiniMax-M2.1 (Cheapest fallback, $0.20/1M)
1. cc/claude-opus-4-7 (Langganan utama)
2. glm/glm-4.7 (Cadangan murah, $0.6/1M)
3. minimax/MiniMax-M2.1 (Fallback termurah, $0.20/1M)
Use in CLI: premium-coding
```
### Example 2: Free-Only (Zero Cost)
### Contoh 2: Hanya Gratis (Biaya Nol)
```
Name: free-combo
Models:
1. gc/gemini-3-flash-preview (180K free/month)
2. if/kimi-k2-thinking (unlimited)
3. qw/qwen3-coder-plus (unlimited)
1. gc/gemini-3-flash-preview (180K gratis/bulan)
2. if/kimi-k2-thinking (tanpa batas)
3. qw/qwen3-coder-plus (tanpa batas)
Cost: $0 forever!
Cost: $0 selamanya!
```
---
## 🔧 CLI Integration
## 🔧 Integrasi CLI
### Cursor IDE
```
Settings → Models → Advanced:
OpenAI API Base URL: http://localhost:20128/v1
OpenAI API Key: [from omniroute dashboard]
OpenAI API Key: [dari dasbor omniroute]
Model: cc/claude-opus-4-7
```
@@ -307,14 +307,14 @@ Edit `~/.openclaw/openclaw.json`:
}
```
**Or use Dashboard:** CLI Tools → OpenClaw → Auto-config
**Atau gunakan Dasbor:** CLI Tools → OpenClaw → Auto-config
### Cline / Continue / RooCode
```
Provider: OpenAI Compatible
Base URL: http://localhost:20128/v1
API Key: [from dashboard]
API Key: [dari dasbor]
Model: cc/claude-opus-4-7
```
@@ -322,7 +322,7 @@ Model: cc/claude-opus-4-7
## Penerapan
### Global npm install (Recommended)
### Instalasi npm Global (Direkomendasikan)
```bash
npm install -g omniroute
@@ -339,20 +339,20 @@ omniroute
omniroute --port 3000
```
The CLI automatically loads `.env` from `~/.omniroute/.env` or `./.env`.
CLI secara otomatis memuat `.env` dari `~/.omniroute/.env` atau `./.env`.
### Uninstalling
### Menghapus Instalasi
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:
Saat Anda tidak lagi memerlukan OmniRoute, kami menyediakan dua skrip cepat untuk penghapusan bersih:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
| Perintah | Tindakan |
| ------------------------ | -------------------------------------------------------------------------------------------------- |
| `npm run uninstall` | Menghapus aplikasi dari sistem tetapi **menyimpan DB dan konfigurasi** di `~/.omniroute`. |
| `npm run uninstall:full` | Menghapus aplikasi DAN secara permanen **menghapus semua konfigurasi, kunci, dan basis data**. |
> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.
> Catatan: Untuk menjalankan perintah ini, navigasikan ke folder proyek OmniRoute (jika Anda telah meng-clone-nya) dan jalankan. Atau, jika diinstal secara global, Anda cukup menjalankan `npm uninstall -g omniroute`.
### VPS Deployment
### Penerapan VPS
```bash
git clone https://github.com/diegosouzapw/OmniRoute.git
@@ -371,9 +371,9 @@ npm run start
# Or: pm2 start npm --name omniroute -- start
```
### PM2 Deployment (Low Memory)
### Penerapan PM2 (Memori Rendah)
For servers with limited RAM, use the memory limit option:
Untuk server dengan RAM terbatas, gunakan opsi batas memori:
```bash
# With 512MB limit (default)
@@ -386,7 +386,7 @@ OMNIROUTE_MEMORY_MB=512 pm2 start npm --name omniroute -- start
pm2 start ecosystem.config.js
```
Create `ecosystem.config.js`:
Buat `ecosystem.config.js`:
```javascript
module.exports = {
@@ -418,14 +418,14 @@ docker build -t omniroute:cli .
docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-data:/app/data omniroute:cli
```
For host-integrated mode with CLI binaries, see the Docker section in the main docs.
Untuk mode integrasi host dengan binari CLI, lihat bagian Docker di dokumentasi utama.
### Void Linux (xbps-src)
Void Linux users can package and install OmniRoute natively using the `xbps-src` cross-compilation framework. This automates the Node.js standalone build along with the required `better-sqlite3` native bindings.
Pengguna Void Linux dapat mengemas dan menginstal OmniRoute secara native menggunakan framework kompilasi silang `xbps-src`. Ini mengotomasi build standalone Node.js beserta binding native `better-sqlite3` yang diperlukan.
<details>
<summary><b>View xbps-src template</b></summary>
<summary><b>Lihat template xbps-src</b></summary>
```bash
# Template file for 'omniroute'
@@ -520,45 +520,45 @@ post_install() {
</details>
### Environment Variables
### Variabel Lingkungan
| Variable | Default | Description |
| --------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------- |
| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
| `INITIAL_PASSWORD` | `123456` | First login password |
| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
| `PORT` | framework default | Service port (`20128` in examples) |
| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
| `NODE_ENV` | runtime default | Set `production` for deploy |
| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Server-side refresh cadence for cached Provider Limits data; UI refresh buttons still trigger manual sync |
| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk |
| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
| `CLOUDFLARED_PROTOCOL` | `http2` | Transport for managed Quick Tunnels (`http2`, `quic`, or `auto`) |
| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
| Variabel | Default | Deskripsi |
| --------------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `JWT_SECRET` | `omniroute-default-secret-change-me` | Rahasia penandatanganan JWT (**ubah di produksi**) |
| `INITIAL_PASSWORD` | `123456` | Kata sandi login pertama |
| `DATA_DIR` | `~/.omniroute` | Direktori data (db, penggunaan, log) |
| `PORT` | default framework | Port layanan (`20128` dalam contoh) |
| `HOSTNAME` | default framework | Host bind (Docker default ke `0.0.0.0`) |
| `NODE_ENV` | default runtime | Atur `production` untuk penerapan |
| `BASE_URL` | `http://localhost:20128` | URL berbasis sisi server internal |
| `CLOUD_URL` | `https://omniroute.dev` | Cloud sinkronisasi titik akhir berbasis URL |
| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | Rahasia HMAC untuk kunci API yang dihasilkan |
| `REQUIRE_API_KEY` | `false` | Wajibkan kunci API Bearer di `/v1/*` |
| `ALLOW_API_KEY_REVEAL` | `false` | Izinkan Api Manager menyalin kunci API lengkap sesuai permintaan |
| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Frekuensi refresh sisi server untuk data Provider Limits yang di-cache; tombol refresh UI tetap memicu sinkronisasi manual |
| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Nonaktifkan snapshot SQLite otomatis sebelum tulis/impor/pemulihan; backup manual tetap berfungsi |
| `APP_LOG_TO_FILE` | `true` | Mengaktifkan output log aplikasi dan audit ke disk |
| `AUTH_COOKIE_SECURE` | `false` | Paksa cookie auth `Secure` (di belakang reverse proxy HTTPS) |
| `CLOUDFLARED_BIN` | tidak diatur | Gunakan binari `cloudflared` yang sudah ada alih-alih unduhan terkelola |
| `CLOUDFLARED_PROTOCOL` | `http2` | Transport untuk Quick Tunnel terkelola (`http2`, `quic`, atau `auto`) |
| `OMNIROUTE_MEMORY_MB` | `512` | Batas heap Node.js dalam MB |
| `PROMPT_CACHE_MAX_SIZE` | `50` | Entri cache prompt maksimum |
| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Entri cache semantik maksimum |
For the full environment variable reference, see the [README](../README.md).
Untuk referensi variabel lingkungan lengkap, lihat [README](../README.md).
---
## 📊 Available Models
## 📊 Model yang Tersedia
<details>
<summary><b>View all available models</b></summary>
<summary><b>Lihat semua model yang tersedia</b></summary>
**Claude Code (`cc/`)** — Pro/Max: `cc/claude-opus-4-7`, `cc/claude-sonnet-4-5-20250929`, `cc/claude-haiku-4-5-20251001`
**Codex (`cx/`)** — Plus/Pro: `cx/gpt-5.2-codex`, `cx/gpt-5.1-codex-max`
**Gemini CLI (`gc/`)**FREE: `gc/gemini-3-flash-preview`, `gc/gemini-2.5-pro`
**Gemini CLI (`gc/`)**GRATIS: `gc/gemini-3-flash-preview`, `gc/gemini-2.5-pro`
**GitHub Copilot (`gh/`)**: `gh/gpt-5`, `gh/claude-4.5-sonnet`
@@ -566,11 +566,11 @@ For the full environment variable reference, see the [README](../README.md).
**MiniMax (`minimax/`)** — $0.2/1M: `minimax/MiniMax-M2.1`
**Qoder (`if/`)**FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
**Qoder (`if/`)**GRATIS: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
**Qwen (`qw/`)**FREE: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`
**Qwen (`qw/`)**GRATIS: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`
**Kiro (`kr/`)**FREE: `kr/claude-sonnet-4.5`, `kr/claude-haiku-4.5`
**Kiro (`kr/`)**GRATIS: `kr/claude-sonnet-4.5`, `kr/claude-haiku-4.5`
**DeepSeek (`ds/`)**: `ds/deepseek-chat`, `ds/deepseek-reasoner`
@@ -596,11 +596,11 @@ For the full environment variable reference, see the [README](../README.md).
---
## 🧩 Advanced Features
## 🧩 Fitur Lanjutan
### Custom Models
### Model Kustom
Add any model ID to any provider without waiting for an app update:
Tambahkan ID model apa pun ke penyedia mana pun tanpa menunggu pembaruan aplikasi:
```bash
# Via API
@@ -612,16 +612,16 @@ curl -X POST http://localhost:20128/api/provider-models \
# Remove: curl -X DELETE "http://localhost:20128/api/provider-models?provider=openai&model=gpt-4.5-preview"
```
Or use Dashboard: **Providers → [Provider] → Custom Models**.
Atau gunakan Dasbor: **Penyedia → [Penyedia] → Model Khusus**.
Notes:
Catatan:
- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
- Penyedia yang kompatibel dengan OpenRouter dan OpenAI/Anthropic dikelola hanya melalui **Available Models**. Penambahan manual, impor, dan auto-sync semuanya masuk ke daftar model yang sama, sehingga tidak ada bagian Custom Models terpisah untuk penyedia tersebut.
- Bagian **Custom Models** ditujukan untuk penyedia yang tidak mengekspos impor model yang terkelola.
### Dedicated Provider Routes
### Rute Penyedia Khusus
Route requests directly to a specific provider with model validation:
Arahkan permintaan langsung ke penyedia tertentu dengan validasi model:
```bash
POST http://localhost:20128/v1/providers/openai/chat/completions
@@ -629,9 +629,9 @@ POST http://localhost:20128/v1/providers/openai/embeddings
POST http://localhost:20128/v1/providers/fireworks/images/generations
```
The provider prefix is auto-added if missing. Mismatched models return `400`.
Awalan penyedia ditambahkan otomatis jika tidak ada. Model yang tidak cocok mengembalikan `400`.
### Network Proxy Configuration
### Konfigurasi Proxy Jaringan
```bash
# Set global proxy
@@ -647,103 +647,103 @@ curl -X POST http://localhost:20128/api/settings/proxy/test \
-d '{"proxy":{"type":"socks5","host":"proxy.example.com","port":"1080"}}'
```
**Precedence:** Key-specific → Combo-specific → Provider-specific → Global → Environment.
**Urutan Prioritas:** Spesifik-kunci → Spesifik-combo → Spesifik-penyedia → Global → Lingkungan.
### Model Catalog API
### API Katalog Model
```bash
curl http://localhost:20128/api/models/catalog
```
Returns models grouped by provider with types (`chat`, `embedding`, `image`).
Mengembalikan model yang dikelompokkan berdasarkan penyedia dengan tipe (`chat`, `embedding`, `image`).
### Cloud Sync
### Sinkronisasi Cloud
- Sync providers, combos, and settings across devices
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
- Sinkronkan penyedia, combo, dan pengaturan di semua perangkat
- Sinkronisasi latar belakang otomatis dengan timeout + gagal cepat
- Gunakan `BASE_URL`/`CLOUD_URL` sisi server di produksi
### Cloudflare Quick Tunnel
- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
- Quick Tunnels are not auto-restored after an OmniRoute or container restart; re-enable them from the dashboard when needed
- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
- Managed Quick Tunnels default to HTTP/2 transport to avoid noisy QUIC UDP buffer warnings in constrained containers
- Set `CLOUDFLARED_PROTOCOL=quic` or `auto` if you want to override the managed transport choice
- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
- Tersedia di **Dashboard → Endpoints** untuk penerapan Docker dan self-hosted lainnya
- Membuat URL `https://*.trycloudflare.com` sementara yang diteruskan ke endpoint `/v1` Anda yang kompatibel dengan OpenAI
- Aktifkan pertama kali untuk menginstal `cloudflared` hanya saat diperlukan; restart berikutnya menggunakan kembali binari terkelola yang sama
- Quick Tunnel tidak dipulihkan otomatis setelah OmniRoute atau container di-restart; aktifkan kembali dari dasbor bila diperlukan
- URL tunnel bersifat sementara dan berubah setiap kali Anda menghentikan/memulai tunnel
- Managed Quick Tunnel secara default menggunakan transport HTTP/2 untuk menghindari peringatan buffer UDP QUIC yang mengganggu di container terbatas
- Atur `CLOUDFLARED_PROTOCOL=quic` atau `auto` jika ingin mengubah pilihan transport terkelola
- Atur `CLOUDFLARED_BIN` jika ingin menggunakan binari `cloudflared` yang sudah terinstal alih-alih unduhan terkelola
### LLM Gateway Intelligence (Phase 9)
### Kecerdasan LLM Gateway (Fase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
- **Request Idempotency** — Deduplicates requests within 5s via `Idempotency-Key` or `X-Request-Id` header
- **Progress Tracking** — Opt-in SSE `event: progress` events via `X-OmniRoute-Progress: true` header
- **Cache Semantik** — Otomatis menyimpan respons non-streaming, temperature=0 (lewati dengan `X-OmniRoute-No-Cache: true`)
- **Idempotensitas Permintaan** — Mendeduplikasi permintaan dalam 5 detik melalui header `Idempotency-Key` atau `X-Request-Id`
- **Pelacakan Progres** — Event SSE `event: progress` yang bisa diaktifkan melalui header `X-OmniRoute-Progress: true`
---
### Translator Playground
Access via **Dashboard → Translator**. Debug and visualize how OmniRoute translates API requests between providers.
Akses melalui **Dashboard → Translator**. Debug dan visualisasikan bagaimana OmniRoute menerjemahkan permintaan API antar penyedia.
| Mode | Purpose |
| ---------------- | -------------------------------------------------------------------------------------- |
| **Playground** | Select source/target formats, paste a request, and see the translated output instantly |
| **Chat Tester** | Send live chat messages through the proxy and inspect the full request/response cycle |
| **Test Bench** | Run batch tests across multiple format combinations to verify translation correctness |
| **Live Monitor** | Watch real-time translations as requests flow through the proxy |
| Mode | Tujuan |
| ---------------- | ------------------------------------------------------------------------------------------------ |
| **Playground** | Pilih format sumber/target, tempel permintaan, dan lihat hasil terjemahan secara instan |
| **Chat Tester** | Kirim pesan chat langsung melalui proxy dan periksa siklus permintaan/respons lengkap |
| **Test Bench** | Jalankan pengujian batch di berbagai kombinasi format untuk memverifikasi kebenaran terjemahan |
| **Live Monitor** | Amati terjemahan real-time saat permintaan mengalir melalui proxy |
**Use cases:**
**Kasus penggunaan:**
- Debug why a specific client/provider combination fails
- Verify that thinking tags, tool calls, and system prompts translate correctly
- Compare format differences between OpenAI, Claude, Gemini, and Responses API formats
- Debug mengapa kombinasi klien/penyedia tertentu gagal
- Verifikasi bahwa tag thinking, pemanggilan tool, dan system prompt diterjemahkan dengan benar
- Bandingkan perbedaan format antara OpenAI, Claude, Gemini, dan format Responses API
---
### Routing Strategies
### Strategi Routing
Configure via **Dashboard → Settings → Routing**.
Konfigurasikan melalui **Dasbor → Pengaturan → Perutean**.
| Strategy | Description |
| ------------------------------ | ------------------------------------------------------------------------------------------------ |
| **Fill First** | Uses accounts in priority order — primary account handles all requests until unavailable |
| **Round Robin** | Cycles through all accounts with a configurable sticky limit (default: 3 calls per account) |
| **P2C (Power of Two Choices)** | Picks 2 random accounts and routes to the healthier one — balances load with awareness of health |
| **Random** | Randomly selects an account for each request using Fisher-Yates shuffle |
| **Least Used** | Routes to the account with the oldest `lastUsedAt` timestamp, distributing traffic evenly |
| **Cost Optimized** | Routes to the account with the lowest priority value, optimizing for lowest-cost providers |
| **Fill First** | Menggunakan akun dalam urutan prioritas — akun utama menangani semua permintaan hingga tidak tersedia |
| **Round Robin** | Menggilir semua akun dengan batas melekat yang dapat dikonfigurasi (default: 3 panggilan per akun) |
| **P2C (Power of Two Choices)** | Pilih 2 akun acak dan rute ke akun yang lebih sehat — menyeimbangkan beban dengan kesadaran akan kesehatan |
| **Random** | Memilih akun secara acak untuk setiap permintaan menggunakan pengacakan Fisher-Yates |
| **Least Used** | Merutekan ke akun dengan stempel waktu `lastUsedAt` terlama, mendistribusikan lalu lintas secara merata |
| **Cost Optimized** | Merutekan ke akun dengan nilai prioritas terendah, mengoptimalkan penyedia berbiaya terendah |
#### External Sticky Session Header
#### Header Sesi Lengket Eksternal
For external session affinity (for example, Claude Code/Codex agents behind reverse proxies), send:
Untuk afinitas sesi eksternal (misalnya, agen Claude Code/Codex di belakang proxy terbalik), kirim:
```http
X-Session-Id: your-session-key
```
OmniRoute also accepts `x_session_id` and returns the effective session key in `X-OmniRoute-Session-Id`.
OmniRoute juga menerima `x_session_id` dan mengembalikan kunci sesi efektif di `X-OmniRoute-Session-Id`.
If you use Nginx and send underscore-form headers, enable:
Jika Anda menggunakan Nginx dan mengirim header berbentuk garis bawah, aktifkan:
```nginx
underscores_in_headers on;
```
#### Wildcard Model Aliases
#### Model Alias Wildcard
Create wildcard patterns to remap model names:
Buat pola wildcard untuk memetakan ulang nama model:
```
Pattern: claude-sonnet-* → Target: cc/claude-sonnet-4-5-20250929
Pattern: gpt-* → Target: gh/gpt-5.1-codex
```
Wildcards support `*` (any characters) and `?` (single character).
Wildcard mendukung `*` (karakter apa saja) dan `?` (karakter tunggal).
#### Fallback Chains
Define global fallback chains that apply across all requests:
Tentukan rantai fallback global yang berlaku di semua permintaan:
```
Chain: production-fallback
@@ -754,50 +754,50 @@ Chain: production-fallback
---
### Resilience & Circuit Breakers
### Ketahanan & Pemutus Sirkuit
Configure via **Dashboard → Settings → Resilience**.
Konfigurasikan melalui **Dasbor → Pengaturan → Ketahanan**.
OmniRoute implements provider-level resilience with five components:
OmniRoute mengimplementasikan ketahanan tingkat penyedia dengan lima komponen:
1. **Request Queue & Pacing** — System-level request shaping:
- **Requests Per Minute (RPM)** — Maximum requests per minute per account
- **Min Time Between Requests** — Minimum gap in milliseconds between requests
- **Max Concurrent Requests** — Maximum simultaneous requests per account
1. **Antrian & Kecepatan Permintaan** — Pembentukan permintaan tingkat sistem:
- **Permintaan Per Menit (RPM)** — Permintaan maksimum per menit per akun
- **Waktu Minimum Antar Permintaan** — Kesenjangan minimum dalam milidetik antar permintaan
- **Permintaan Bersamaan Maksimum** — Permintaan simultan maksimum per akun
2. **Connection Cooldown** — Per-auth-type configuration for a single connection after retryable failures:
- **Base Cooldown** — Default cooldown window for retryable upstream failures
- **Use Upstream Retry Hints** — Honors authoritative `Retry-After` or reset hints when provided
- **Max Backoff Steps** — Maximum exponential backoff level for repeated failures
2. **Cooldown Koneksi** — Konfigurasi tipe per autentikasi untuk satu koneksi setelah kegagalan yang dapat dicoba lagi:
- **Cooldown Dasar** — Jendela cooldown default untuk kegagalan upstream yang dapat dicoba ulang
- **Gunakan Petunjuk Coba Ulang Hulu** — Ikuti `Retry-After` resmi atau petunjuk setel ulang bila diberikan
- **Langkah Backoff Maks** — Tingkat backoff eksponensial maksimum untuk kegagalan berulang
3. **Provider Circuit Breaker** — Tracks end-to-end provider failures and automatically opens the breaker when the configured threshold is reached:
- **Failure Threshold** — Consecutive provider failures before opening the breaker
- **Reset Timeout** — Time window before the provider is tested again
- **CLOSED** (Healthy) — Requests flow normally
- **OPEN** — Provider is temporarily blocked after repeated failures
- **HALF_OPEN** — Testing if provider has recovered
3. **Pemutus Sirkuit Penyedia** — Melacak kegagalan penyedia ujung ke ujung dan secara otomatis membuka pemutus ketika ambang batas yang dikonfigurasi tercapai:
- **Ambang Kegagalan** — Kegagalan penyedia berturut-turut sebelum membuka pemutus
- **Reset Timeout** — Jangka waktu sebelum penyedia diuji lagi
- **TUTUP** (Sehat) — Permintaan mengalir normal
- **BUKA** — Penyedia diblokir sementara setelah kegagalan berulang kali
- **HALF_OPEN** — Menguji apakah penyedia telah pulih
Connection-scoped `429` rate limits stay in **Connection Cooldown** and do not count toward the provider breaker.
Batas kecepatan `429` cakupan koneksi tetap dalam **Cooldown Koneksi** dan tidak diperhitungkan dalam pemutus penyedia.
The provider breaker runtime state is shown on **Dashboard → Health** only.
Status waktu proses pemutus penyedia hanya ditampilkan di **Dasbor → Kesehatan**.
4. **Wait For Cooldown**If every candidate connection is already cooling down, OmniRoute can wait for the earliest cooldown and retry the same client request automatically.
4. **Tunggu Cooldown**Jika setiap kandidat koneksi sudah cooldown, OmniRoute dapat menunggu cooldown paling awal dan mencoba kembali permintaan klien yang sama secara otomatis.
5. **Rate Limit Auto-Detection** — When upstream providers return explicit wait windows, those hints override the local connection cooldown when the setting is enabled.
5. **Deteksi Otomatis Batas Kecepatan** — Saat penyedia upstream mengembalikan jendela tunggu eksplisit, petunjuk tersebut akan menggantikan jeda pakai koneksi lokal saat pengaturan diaktifkan.
**Pro Tip:** Use the **Health** page to inspect and reset live provider breakers after an outage. The Resilience page only changes configuration.
**Kiat Pro:** Gunakan laman **Kesehatan** untuk memeriksa dan menyetel ulang pemutus penyedia langsung setelah pemadaman. Halaman Ketahanan hanya mengubah konfigurasi.
---
### Database Export / Import
### Ekspor/Impor Basis Data
Manage database backups in **Dashboard → Settings → System & Storage**.
Kelola cadangan basis data di **Dasbor → Pengaturan → Sistem & Penyimpanan**.
| Action | Description |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
| **Export Database** | Mengunduh database SQLite saat ini sebagai file `.sqlite` |
| **Ekspor Semua (.tar.gz)** | Mengunduh arsip cadangan lengkap termasuk: basis data, pengaturan, kombo, koneksi penyedia (tanpa kredensial), metadata kunci API |
| **Import Database** | Unggah file `.sqlite` untuk menggantikan database saat ini. Cadangan pra-impor dibuat secara otomatis kecuali `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -811,39 +811,39 @@ curl -X POST http://localhost:20128/api/db-backups/import \
-F "file=@backup.sqlite"
```
**Import Validation:** The imported file is validated for integrity (SQLite pragma check), required tables (`provider_connections`, `provider_nodes`, `combos`, `api_keys`), and size (max 100MB).
**Validasi Impor:** File yang diimpor divalidasi integritasnya (pemeriksaan pragma SQLite), tabel yang diperlukan (`provider_connections`, `provider_nodes`, `combos`, `api_keys`), dan ukuran (maks 100MB).
**Use Cases:**
- Migrate OmniRoute between machines
- Create external backups for disaster recovery
- Share configurations between team members (export all → share archive)
- Migrasi OmniRoute antar mesin
- Buat cadangan eksternal untuk pemulihan bencana
- Bagikan konfigurasi antar anggota tim (ekspor semua → bagikan arsip)
---
### Settings Dashboard
### Dashboard Pengaturan
The settings page is organized into 6 tabs for easy navigation:
Halaman pengaturan disusun menjadi 6 tab untuk memudahkan navigasi:
| Tab | Contents |
| -------------- | -------------------------------------------------------------------------------------------- |
| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Security** |Pengaturan Login/Kata Sandi, Kontrol Akses IP, autentikasi API untuk `/models`, dan Pemblokiran Penyedia |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Request queue, connection cooldown, provider breaker config, and wait-for-cooldown behavior |
| **Resilience** | Antrean permintaan, waktu tunggu koneksi, konfigurasi pemutus penyedia, dan perilaku menunggu waktu tunggu |
| **AI** | Thinking budget configuration, global system prompt injection, prompt cache stats |
| **Advanced** | Global proxy configuration (HTTP/SOCKS5) |
| **Advanced** | Konfigurasi proksi global (HTTP/SOCKS5) |
---
### Costs & Budget Management
### Biaya & Manajemen Anggaran
Access via **Dashboard → Costs**.
Akses melalui **Dasbor → Biaya**.
| Tab | Purpose |
| ----------- | ---------------------------------------------------------------------------------------- |
| **Budget** | Set spending limits per API key with daily/weekly/monthly budgets and real-time tracking |
| **Pricing** | View and edit model pricing entries — cost per 1K input/output tokens per provider |
| **Budget** | Tetapkan batas pengeluaran per kunci API dengan anggaran harian/mingguan/bulanan dan pelacakan waktu nyata |
| **Pricing** | Lihat dan edit entri harga model — biaya per 1K token input/output per penyedia |
```bash
# API: Set a budget
@@ -855,13 +855,13 @@ curl -X POST http://localhost:20128/api/usage/budget \
curl http://localhost:20128/api/usage/budget
```
**Cost Tracking:** Every request logs token usage and calculates cost using the pricing table. View breakdowns in **Dashboard → Usage** by provider, model, and API key.
**Pelacakan Biaya:** Setiap permintaan mencatat penggunaan token dan menghitung biaya menggunakan tabel harga. Lihat pengelompokan di **Dasbor → Penggunaan** menurut penyedia, model, dan kunci API.
---
### Audio Transcription
### Transkripsi Audio
OmniRoute supports audio transcription via the OpenAI-compatible endpoint:
OmniRoute mendukung transkripsi audio melalui titik akhir yang kompatibel dengan OpenAI:
```bash
POST /v1/audio/transcriptions
@@ -875,49 +875,49 @@ curl -X POST http://localhost:20128/v1/audio/transcriptions \
-F "model=deepgram/nova-3"
```
Available providers: **Deepgram** (`deepgram/`), **AssemblyAI** (`assemblyai/`).
Penyedia yang tersedia: **Deepgram** (`deepgram/`), **AssemblyAI** (`assemblyai/`).
Supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
Format audio yang didukung: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
---
### Combo Balancing Strategies
### Strategi Penyeimbangan Kombo
Configure per-combo balancing in **DashboardCombosCreate/Edit → Strategy**.
Konfigurasikan penyeimbangan per kombo di **DasborKombo → Buat/Edit → Strategi**.
| Strategy | Description |
| ------------------ | ------------------------------------------------------------------------ |
| **Round-Robin** | Rotates through models sequentially |
| **Priority** | Always tries the first model; falls back only on error |
| **Random** | Picks a random model from the combo for each request |
| **Weighted** | Routes proportionally based on assigned weights per model |
| **Least-Used** | Routes to the model with the fewest recent requests (uses combo metrics) |
| **Cost-Optimized** | Routes to the cheapest available model (uses pricing table) |
| **Round-Robin** | Berputar melalui model secara berurutan |
| **Priority** | Selalu mencoba model pertama; jatuh kembali hanya karena kesalahan |
| **Random** | Memilih model acak dari kombo untuk setiap permintaan |
| **Weighted** | Rute secara proporsional berdasarkan bobot yang ditetapkan per model |
| **Least-Used** | Merutekan ke model dengan permintaan terkini paling sedikit (menggunakan metrik kombo) |
| **Cost-Optimized** | Rute ke model termurah yang tersedia (menggunakan tabel harga) |
Global combo defaults can be set in **Dashboard → Settings → Routing → Combo Defaults**.
Default kombo global dapat diatur di **Dasbor → Pengaturan → Perutean → Default Kombo**.
---
### Health Dashboard
### Dashboard Kesehatan
Access via **Dashboard → Health**. Real-time system health overview with 6 cards:
Akses melalui **Dasbor → Kesehatan**. Ikhtisar kesehatan sistem real-time dengan 6 kartu:
| Card | What It Shows |
| Card | Apa yang Ditunjukkannya |
| --------------------- | ----------------------------------------------------------- |
| **System Status** | Uptime, version, memory usage, data directory |
| **Provider Health** | Global provider circuit breaker runtime state |
| **Rate Limits** | Active connection cooldowns per account with remaining time |
| **Active Lockouts** | Active model-scoped lockouts and temporary exclusions |
| **Signature Cache** | Deduplication cache stats (active keys, hit rate) |
| **Latency Telemetry** | p50/p95/p99 latency aggregation per provider |
| **Provider Health** | Status runtime pemutus sirkuit penyedia global |
| **Rate Limits** | Cooldown koneksi aktif per akun dengan sisa waktu |
| **Active Lockouts** | Penguncian cakupan model aktif dan pengecualian sementara |
| **Signature Cache** | Statistik cache deduplikasi (kunci aktif, tingkat hit) |
| **Latency Telemetry** | agregasi latensi p50/p95/p99 per penyedia |
**Pro Tip:** The Health page auto-refreshes every 10 seconds. Use the circuit breaker card to identify which providers are experiencing issues.
**Tips Pro:** Halaman Kesehatan disegarkan secara otomatis setiap 10 detik. Gunakan kartu pemutus sirkuit untuk mengidentifikasi penyedia mana yang mengalami masalah.
---
## 🖥️ Desktop Application (Electron)
## 🖥️ Aplikasi Desktop (Elektron)
OmniRoute is available as a native desktop application for Windows, macOS, and Linux.
OmniRoute tersedia sebagai aplikasi desktop asli untuk Windows, macOS, dan Linux.
### Instal
@@ -933,7 +933,7 @@ npm run dev
npm start
```
### Building Installers
### Membuat Installer
```bash
cd electron
@@ -945,18 +945,18 @@ npm run build:linux # Linux (.AppImage)
Output → `electron/dist-electron/`
### Key Features
### Fitur Utama
| Feature | Description |
| --------------------------- | ---------------------------------------------------- |
| **Server Readiness** | Polls server before showing window (no blank screen) |
| **Server Readiness** |Server jajak pendapat sebelum menampilkan jendela (tidak ada layar kosong) |
| **System Tray** | Minimize to tray, change port, quit from tray menu |
| **Port Management** | Change server port from tray (auto-restarts server) |
| **Content Security Policy** | Restrictive CSP via session headers |
| **Single Instance** | Only one app instance can run at a time |
| **Offline Mode** | Bundled Next.js server works without internet |
| **Port Management** | Ubah port server dari baki (server restart otomatis) |
| **Kebijakan Keamanan Konten** | CSP terbatas melalui header sesi |
| **Single Instance** | Hanya satu instance aplikasi yang dapat berjalan dalam satu waktu |
| **Offline Mode** | Server Next.js yang dibundel berfungsi tanpa internet|
### Environment Variables
### Variabel Lingkungan
| Variable | Default | Description |
| --------------------- | ------- | -------------------------------- |

View File

@@ -1,158 +1,158 @@
# Test Coverage Plan (Bahasa Indonesia)
# Rencana Cakupan Pengujian (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇧🇩 [bn](../../bn/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇮🇷 [fa](../../fa/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇮🇳 [gu](../../gu/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇮🇳 [hi](../../hi/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇮🇳 [mr](../../mr/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇰🇪 [sw](../../sw/docs/COVERAGE_PLAN.md) · 🇮🇳 [ta](../../ta/docs/COVERAGE_PLAN.md) · 🇮🇳 [te](../../te/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇹🇷 [tr](../../tr/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇵🇰 [ur](../../ur/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md)
---
Last updated: 2026-03-28
Terakhir diperbarui: 2026-03-28
## Baseline
There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
Ada beberapa angka cakupan tergantung pada cara laporan dihitung. Untuk keperluan perencanaan, hanya satu yang berguna.
| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
| Metrik | Ruang Lingkup | Pernyataan / Garis | Cabang | Fungsi | Catatan |
| -------------------- | -------------------------------------------------------------------- | -----------------: | -------: | --------: | ------------------------------------------------------------------------ |
| Lama | `npm run test:coverage` lama | 79.42% | 75.15% | 67.94% | Diperbesar: menghitung file pengujian dan mengecualikan `open-sse` |
| Diagnostik | Hanya sumber, mengecualikan pengujian dan mengecualikan `open-sse` | 68.16% | 63.55% | 64.06% | Berguna hanya untuk mengisolasi `src/**` |
| Baseline yang disarankan | Hanya sumber, mengecualikan pengujian dan menyertakan `open-sse` | 56.95% | 66.05% | 57.80% | Ini adalah baseline seluruh proyek yang perlu ditingkatkan |
The recommended baseline is the number to optimize against.
Baseline yang disarankan adalah angka yang perlu dioptimalkan.
## Rules
## Aturan
- Coverage targets apply to source files, not to `tests/**`.
- `open-sse/**` is part of the product and must remain in scope.
- New code should not reduce coverage in touched areas.
- Prefer testing behavior and branch outcomes over implementation details.
- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
- Target cakupan berlaku untuk file sumber, bukan untuk `tests/**`.
- `open-sse/**` adalah bagian dari produk dan harus tetap dalam cakupan.
- Kode baru tidak boleh mengurangi cakupan di area yang disentuh.
- Utamakan pengujian perilaku dan hasil cabang dibandingkan detail implementasi.
- Utamakan database SQLite sementara dan fixture kecil dibandingkan mock yang luas untuk `src/lib/db/**`.
## Current command set
## Kumpulan perintah saat ini
- `npm run test:coverage`
- Main source coverage gate for the unit test suite
- Generates `text-summary`, `html`, `json-summary`, and `lcov`
- Gerbang cakupan sumber utama untuk suite pengujian unit
- Menghasilkan `text-summary`, `html`, `json-summary`, dan `lcov`
- `npm run coverage:report`
- Detailed file-by-file report from the latest run
- Laporan per-file terperinci dari jalankan terakhir
- `npm run test:coverage:legacy`
- Historical comparison only
- Hanya untuk perbandingan historis
## Milestones
## Tonggak Pencapaian
| Phase | Target | Focus |
| ------- | ---------------------: | ------------------------------------------------- |
| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
| Phase 2 | 65% statements / lines | DB and route foundations |
| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
| Fase | Target | Fokus |
| ------- | ----------------------: | ------------------------------------------------------------------ |
| Fase 1 | 60% pernyataan / garis | Kemenangan cepat dan cakupan utilitas berisiko rendah |
| Fase 2 | 65% pernyataan / garis | Fondasi DB dan rute |
| Fase 3 | 70% pernyataan / garis | Validasi penyedia dan analitik penggunaan |
| Fase 4 | 75% pernyataan / garis | Penerjemah dan pembantu `open-sse` |
| Fase 5 | 80% pernyataan / garis | Handler dan cabang eksekutor `open-sse` |
| Fase 6 | 85% pernyataan / garis | Kasus tepi yang lebih sulit, utang cabang, suite regresi |
| Fase 7 | 90% pernyataan / garis | Pemeriksaan akhir, penutupan celah, ratchet ketat |
Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
Cabang dan fungsi harus meningkat secara bertahap di setiap fase, tetapi target keras utama adalah pernyataan / garis.
## Priority hotspots
## Titik panas prioritas
These files or areas offer the best return for the next phases:
File atau area berikut menawarkan keuntungan terbaik untuk fase selanjutnya:
1. `open-sse/handlers`
- `chatCore.ts` at 7.57%
- Overall directory at 29.07%
- `chatCore.ts` pada 7.57%
- Direktori keseluruhan pada 29.07%
2. `open-sse/translator/request`
- Overall directory at 36.39%
- Many translators are still near single-digit coverage
- Direktori keseluruhan pada 36.39%
- Banyak penerjemah masih mendekati cakupan satu digit
3. `open-sse/translator/response`
- Overall directory at 8.07%
- Direktori keseluruhan pada 8.07%
4. `open-sse/executors`
- Overall directory at 36.62%
- Direktori keseluruhan pada 36.62%
5. `src/lib/db`
- `models.ts` at 20.66%
- `registeredKeys.ts` at 34.46%
- `modelComboMappings.ts` at 36.25%
- `settings.ts` at 46.40%
- `webhooks.ts` at 33.33%
- `models.ts` pada 20.66%
- `registeredKeys.ts` pada 34.46%
- `modelComboMappings.ts` pada 36.25%
- `settings.ts` pada 46.40%
- `webhooks.ts` pada 33.33%
6. `src/lib/usage`
- `usageHistory.ts` at 21.12%
- `usageStats.ts` at 9.56%
- `costCalculator.ts` at 30.00%
- `usageHistory.ts` pada 21.12%
- `usageStats.ts` pada 9.56%
- `costCalculator.ts` pada 30.00%
7. `src/lib/providers`
- `validation.ts` at 41.16%
8. Low-risk utility and API files for early gains
- `validation.ts` pada 41.16%
8. File utilitas dan API berisiko rendah untuk keuntungan awal
- `src/shared/utils/upstreamError.ts`
- `src/shared/utils/apiAuth.ts`
- `src/lib/api/errorResponse.ts`
- `src/app/api/settings/require-login/route.ts`
- `src/app/api/providers/[id]/models/route.ts`
## Execution checklist
## Daftar periksa eksekusi
### Phase 1: 56.95% -> 60%
### Fase 1: 56.95% -> 60%
- [x] Fix coverage metric so it reflects source code instead of test files
- [x] Keep a legacy coverage script for comparison
- [x] Record the baseline and hotspots in-repo
- [ ] Add focused tests for low-risk utilities:
- [x] Perbaiki metrik cakupan agar mencerminkan kode sumber, bukan file pengujian
- [x] Simpan skrip cakupan lama untuk perbandingan
- [x] Catat baseline dan titik panas di dalam repo
- [ ] Tambahkan pengujian terfokus untuk utilitas berisiko rendah:
- `src/shared/utils/upstreamError.ts`
- `src/shared/utils/fetchTimeout.ts`
- `src/lib/api/errorResponse.ts`
- `src/shared/utils/apiAuth.ts`
- `src/lib/display/names.ts`
- [ ] Add route tests for:
- [ ] Tambahkan pengujian rute untuk:
- `src/app/api/settings/require-login/route.ts`
- `src/app/api/providers/[id]/models/route.ts`
### Phase 2: 60% -> 65%
### Fase 2: 60% -> 65%
- [ ] Add DB-backed tests for:
- [ ] Tambahkan pengujian berbasis DB untuk:
- `src/lib/db/modelComboMappings.ts`
- `src/lib/db/settings.ts`
- `src/lib/db/registeredKeys.ts`
- [ ] Cover branch behavior in:
- [ ] Cakup perilaku cabang dalam:
- `src/lib/providers/validation.ts`
- `src/app/api/v1/embeddings/route.ts`
- `src/app/api/v1/moderations/route.ts`
### Phase 3: 65% -> 70%
### Fase 3: 65% -> 70%
- [ ] Add usage analytics tests for:
- [ ] Tambahkan pengujian analitik penggunaan untuk:
- `src/lib/usage/usageHistory.ts`
- `src/lib/usage/usageStats.ts`
- `src/lib/usage/costCalculator.ts`
- [ ] Expand route coverage for proxy management and settings branches
- [ ] Perluas cakupan rute untuk manajemen proxy dan cabang pengaturan
### Phase 4: 70% -> 75%
### Fase 4: 70% -> 75%
- [ ] Cover translator helpers and central translation paths:
- [ ] Cakup pembantu penerjemah dan jalur penerjemahan sentral:
- `open-sse/translator/index.ts`
- `open-sse/translator/helpers/*`
- `open-sse/translator/request/*`
- `open-sse/translator/response/*`
### Phase 5: 75% -> 80%
### Fase 5: 75% -> 80%
- [ ] Add handler-level tests for:
- [ ] Tambahkan pengujian tingkat handler untuk:
- `open-sse/handlers/chatCore.ts`
- `open-sse/handlers/responsesHandler.js`
- `open-sse/handlers/imageGeneration.js`
- `open-sse/handlers/embeddings.js`
- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
- [ ] Tambahkan cakupan cabang eksekutor untuk autentikasi spesifik penyedia, percobaan ulang, dan penggantian endpoint
### Phase 6: 80% -> 85%
### Fase 6: 80% -> 85%
- [ ] Merge more edge-case suites into the main coverage path
- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
- [ ] Gabungkan lebih banyak suite kasus tepi ke dalam jalur cakupan utama
- [ ] Tingkatkan cakupan fungsi untuk modul DB dengan cakupan konstruktor/pembantu yang lemah
- [ ] Tutup celah cabang dalam `settings.ts`, `registeredKeys.ts`, `validation.ts`, dan pembantu penerjemah
### Phase 7: 85% -> 90%
### Fase 7: 85% -> 90%
- [ ] Treat the remaining low-coverage files as blockers
- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
- [ ] Perlakukan file dengan cakupan rendah yang tersisa sebagai pemblokir
- [ ] Tambahkan pengujian regresi untuk setiap bug produksi yang belum tercakup yang diperbaiki selama pendakian ke 90%
- [ ] Naikkan gerbang cakupan di CI hanya setelah baseline lokal stabil selama setidaknya dua jalankan berurutan
## Ratchet policy
## Kebijakan ratchet
Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
Perbarui ambang batas `npm run test:coverage` hanya setelah proyek benar-benar melampaui tonggak berikutnya dengan buffer yang nyaman.
Recommended ratchet sequence:
Urutan ratchet yang disarankan:
1. 55/60/55
2. 60/62/58
@@ -163,8 +163,8 @@ Recommended ratchet sequence:
7. 85/80/84
8. 90/85/88
Order is `statements-lines / branches / functions`.
Urutan adalah `pernyataan-garis / cabang / fungsi`.
## Known gap
## Celah yang diketahui
The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
Perintah cakupan saat ini mengukur suite unit Node utama dan menyertakan sumber yang dapat dijangkau darinya, termasuk `open-sse`. Perintah ini belum menggabungkan cakupan Vitest ke dalam satu laporan terpadu. Penggabungan tersebut layak dilakukan nanti, tetapi bukan pemblokir untuk memulai pendakian 60% -> 80%.

View File

@@ -1,32 +1,32 @@
# OmniRoute Fly.io 部署指南 (Bahasa Indonesia)
# Panduan Deployment OmniRoute di Fly.io
🌐 **Languages:** 🇺🇸 [English](../../../../docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇧🇩 [bn](../../bn/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇷 [fa](../../fa/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [gu](../../gu/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [hi](../../hi/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [mr](../../mr/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇰🇪 [sw](../../sw/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [ta](../../ta/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [te](../../te/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇹🇷 [tr](../../tr/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇰 [ur](../../ur/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FLY_IO_DEPLOYMENT_GUIDE.md)
---
本文档记录 OmniRoute Fly.io 上的实际部署方法,适用于两类场景:
Dokumen ini menjelaskan metode deployment OmniRoute di Fly.io yang telah terbukti berhasil, mencakup dua skenario utama:
- 首次把当前项目部署到 Fly.io
- 后续代码更新后继续发布
- 新项目参考同样流程部署
- Deployment pertama kali proyek saat ini ke Fly.io
- Publikasi setelah pembaruan kode berikutnya
- Referensi alur deployment yang sama untuk proyek baru
本文基于当前项目已经验证通过的配置整理,应用名为 `omniroute`
Dokumen ini disusun berdasarkan konfigurasi yang telah diverifikasi pada proyek saat ini, dengan nama aplikasi `omniroute`.
---
## 1. 部署目标
## 1. Target Deployment
- 平台:Fly.io
- 部署方式:本地 `flyctl` 直接发布
- 运行方式:使用仓库内现有 `Dockerfile` `fly.toml`
- 数据持久化Fly Volume 挂载到 `/data`
- 访问地址:`https://omniroute.fly.dev/`
- Platform: Fly.io
- Metode deployment: Publikasi langsung dari lokal menggunakan `flyctl`
- Cara menjalankan: Menggunakan `Dockerfile` dan `fly.toml` yang sudah ada di repositori
- Persistensi data: Fly Volume yang dipasang ke `/data`
- Alamat akses: `https://omniroute.fly.dev/`
---
## 2. 当前项目关键配置
## 2. Konfigurasi Kunci Proyek Saat Ini
当前仓库中的 `fly.toml` 已确认包含以下关键项:
`fly.toml` di repositori saat ini telah dikonfirmasi mengandung item-item kunci berikut:
```toml
app = 'omniroute'
@@ -49,33 +49,33 @@ primary_region = 'sin'
BIND = "0.0.0.0"
```
说明:
Keterangan:
- `app = 'omniroute'` 决定实际部署到哪个 Fly 应用
- `destination = '/data'` 决定持久卷挂载目录
- 本项目必须让 `DATA_DIR=/data`,否则数据库和密钥会写到容器临时目录
- `app = 'omniroute'` menentukan aplikasi Fly mana yang menjadi target deployment
- `destination = '/data'` menentukan direktori pemasangan volume persisten
- Proyek ini mengharuskan `DATA_DIR=/data` disetel; jika tidak, database dan kunci rahasia akan ditulis ke direktori sementara kontainer
---
## 3. 必备工具
## 3. Alat yang Diperlukan
### 3.1 安装 Fly CLI
### 3.1 Instalasi Fly CLI
Windows PowerShell
Windows PowerShell:
```powershell
pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex"
```
如果安装脚本在当前环境失败,也可以手动下载 `flyctl` 二进制并放到 `PATH` 中。
Jika skrip instalasi gagal di lingkungan saat ini, Anda juga dapat mengunduh biner `flyctl` secara manual dan menempatkannya di `PATH`.
### 3.2 登录 Fly 账号
### 3.2 Login ke Akun Fly
```powershell
flyctl auth login
```
### 3.3 检查登录状态
### 3.3 Periksa Status Login
```powershell
flyctl auth whoami
@@ -84,45 +84,45 @@ flyctl version
---
## 4. 首次部署当前项目
## 4. Deployment Pertama Kali untuk Proyek Saat Ini
### 4.1 获取代码并进入目录
### 4.1 Ambil Kode dan Masuk ke Direktori
```powershell
git clone https://github.com/diegosouzapw/OmniRoute.git
cd OmniRoute
```
### 4.2 确认应用名
### 4.2 Konfirmasi Nama Aplikasi
打开 `fly.toml`,重点看这一行:
Buka `fly.toml` dan perhatikan baris berikut:
```toml
app = 'omniroute'
```
如果你准备部署到自己的新应用,可改成全局唯一名称,例如:
Jika Anda berencana melakukan deployment ke aplikasi baru milik sendiri, ubah menjadi nama yang unik secara global, misalnya:
```toml
app = 'omniroute-yourname'
```
注意:
Catatan:
- 控制台里要看的是与 `fly.toml``app` 一致的应用
- 以前如果用过别的名字,例如 `oroute`,不要和 `omniroute` 混淆
- Di konsol, pastikan Anda melihat aplikasi yang sesuai dengan nilai `app` di `fly.toml`
- Jika sebelumnya Anda menggunakan nama lain seperti `oroute`, jangan sampai tertukar dengan `omniroute`
### 4.3 创建应用
### 4.3 Buat Aplikasi
如果该应用尚不存在:
Jika aplikasi belum ada:
```powershell
flyctl apps create omniroute
```
如果你已经改成别的应用名,把 `omniroute` 替换成你的名字。
Jika Anda sudah mengganti nama aplikasi, ganti `omniroute` dengan nama Anda.
### 4.4 首次部署
### 4.4 Deployment Pertama
```powershell
flyctl deploy
@@ -130,13 +130,13 @@ flyctl deploy
---
## 5. 必配参数
## 5. Parameter yang Wajib Dikonfigurasi
本项目在 Fly.io 上建议至少配置以下参数。
Berikut adalah parameter minimum yang direkomendasikan untuk proyek ini di Fly.io.
### 5.1 已验证使用的参数
### 5.1 Parameter yang Telah Diverifikasi
这些参数已经在当前 `omniroute` 应用上实际部署:
Parameter-parameter berikut telah digunakan secara nyata pada aplikasi `omniroute` saat ini:
- `API_KEY_SECRET`
- `DATA_DIR`
@@ -145,58 +145,58 @@ flyctl deploy
- `NEXT_PUBLIC_BASE_URL`
- `STORAGE_ENCRYPTION_KEY`
### 5.2 关于 `INITIAL_PASSWORD`
### 5.2 Tentang `INITIAL_PASSWORD`
当前项目没有设置 `INITIAL_PASSWORD`,因为本次部署按需求不使用它。
Proyek saat ini tidak menyetel `INITIAL_PASSWORD` karena deployment ini tidak memerlukannya.
如果不设置:
Jika tidak disetel:
- 启动日志会提示默认密码是 `CHANGEME`
- 部署后应尽快在系统设置中修改登录密码
- Log startup akan menampilkan bahwa kata sandi default adalah `CHANGEME`
- Setelah deployment, segera ubah kata sandi login di pengaturan sistem
如果你希望无人值守初始化后台密码,也可以后续补:
Jika Anda ingin menginisialisasi kata sandi panel admin secara otomatis, Anda dapat menambahkannya nanti:
- `INITIAL_PASSWORD`
---
## 6. 推荐参数说明
## 6. Penjelasan Parameter yang Direkomendasikan
### 6.1 Secrets 中设置
### 6.1 Konfigurasi di Secrets
建议放入 Fly Secrets
Parameter yang disarankan untuk disimpan sebagai Fly Secrets:
| 变量名 | 是否推荐 | 说明 |
| ------------------------ | -------- | ------------------------------ |
| `API_KEY_SECRET` | 必需 | API Key 生成与校验使用 |
| `JWT_SECRET` | 必需 | 登录态和 JWT 签名使用 |
| `STORAGE_ENCRYPTION_KEY` | 强烈推荐 | 加密存储敏感连接信息 |
| `MACHINE_ID_SALT` | 推荐 | 生成稳定机器标识 |
| `INITIAL_PASSWORD` | 可选 | 首次部署时直接指定后台初始密码 |
| OAuth/API 私密凭证 | 按需 | 各类外部平台鉴权配置 |
| Nama Variabel | Direkomendasikan | Keterangan |
| ------------------------ | ---------------- | ----------------------------------------------- |
| `API_KEY_SECRET` | Wajib | Digunakan untuk pembuatan dan validasi API Key |
| `JWT_SECRET` | Wajib | Digunakan untuk sesi login dan tanda tangan JWT |
| `STORAGE_ENCRYPTION_KEY` | Sangat Direkomendasikan | Mengenkripsi informasi koneksi sensitif |
| `MACHINE_ID_SALT` | Direkomendasikan | Menghasilkan identifikasi mesin yang stabil |
| `INITIAL_PASSWORD` | Opsional | Menentukan kata sandi awal panel admin saat deployment pertama |
| Kredensial OAuth/API | Sesuai kebutuhan | Konfigurasi autentikasi untuk berbagai platform eksternal |
### 6.2 当前项目推荐值
### 6.2 Nilai yang Direkomendasikan untuk Proyek Saat Ini
| 变量名 | 推荐值 |
| ---------------------- | --------------------------- |
| `DATA_DIR` | `/data` |
| `NEXT_PUBLIC_BASE_URL` | `https://omniroute.fly.dev` |
| Nama Variabel | Nilai yang Direkomendasikan |
| ---------------------- | ------------------------------ |
| `DATA_DIR` | `/data` |
| `NEXT_PUBLIC_BASE_URL` | `https://omniroute.fly.dev` |
说明:
Keterangan:
- `DATA_DIR=/data` 非常关键,必须与 Fly Volume 挂载点一致
- `NEXT_PUBLIC_BASE_URL` 用于调度器和前端回调等场景
- `DATA_DIR=/data` sangat krusial dan harus sesuai dengan titik pemasangan Fly Volume
- `NEXT_PUBLIC_BASE_URL` digunakan dalam skenario seperti penjadwal dan callback frontend
---
## 7. 一键设置参数
## 7. Penyetelan Parameter Sekaligus
下面命令会生成安全随机值,并把当前项目需要的参数一次性写入 Fly Secrets。
Perintah berikut akan menghasilkan nilai acak yang aman dan menulis semua parameter yang dibutuhkan proyek saat ini ke Fly Secrets dalam satu langkah.
说明:
Keterangan:
- 不包含 `INITIAL_PASSWORD`
- 适用于当前项目 `omniroute`
- Tidak menyertakan `INITIAL_PASSWORD`
- Berlaku untuk proyek saat ini yaitu `omniroute`
```powershell
$apiKeySecret = [Convert]::ToHexString((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 })).ToLower()
@@ -214,79 +214,79 @@ flyctl secrets set `
-a omniroute
```
如果你还要加初始密码:
Jika Anda juga ingin menambahkan kata sandi awal:
```powershell
flyctl secrets set INITIAL_PASSWORD=你的强密码 -a omniroute
flyctl secrets set INITIAL_PASSWORD=kata-sandi-kuat-anda -a omniroute
```
---
## 8. 查看当前参数
## 8. Melihat Parameter Saat Ini
```powershell
flyctl secrets list -a omniroute
```
如果控制台 `Secrets` 页面没有显示你期待的变量,先检查:
Jika halaman `Secrets` di konsol tidak menampilkan variabel yang Anda harapkan, periksa terlebih dahulu:
- 看的应用是不是 `omniroute`
- `fly.toml``app` 是否和控制台应用一致
- Apakah aplikasi yang sedang dilihat adalah `omniroute`
- Apakah nilai `app` di `fly.toml` sudah sesuai dengan aplikasi di konsol
---
## 9. 后续更新发布
## 9. Pembaruan dan Publikasi Selanjutnya
代码有更新后,发布步骤很简单:
Setelah ada pembaruan kode, langkah publikasinya sangat sederhana:
```powershell
git pull
flyctl deploy
```
如果只更新参数,不改代码:
Jika hanya memperbarui parameter tanpa mengubah kode:
```powershell
flyctl secrets set KEY=value -a omniroute
```
Fly 会自动滚动更新机器。
Fly akan melakukan pembaruan mesin secara otomatis dengan rolling update.
### 9.1 跟踪原仓库更新并保留 fork 的 `fly.toml`
### 9.1 Melacak Pembaruan Repositori Asal dan Mempertahankan `fly.toml` dari Fork
如果当前仓库是 fork并且你要同步上游 `https://github.com/diegosouzapw/OmniRoute` 的更新,推荐按下面流程执行。
Jika repositori saat ini adalah fork dan Anda ingin menyinkronkan pembaruan dari upstream `https://github.com/diegosouzapw/OmniRoute`, ikuti alur berikut.
先确认远程:
Pertama, konfirmasi remote yang ada:
```powershell
git remote -v
```
应至少包含:
Harus mengandung setidaknya:
- `origin` 指向你自己的 fork
- `upstream` 指向原仓库
- `origin` yang mengarah ke fork milik Anda
- `upstream` yang mengarah ke repositori asal
如果没有 `upstream`,先添加:
Jika belum ada `upstream`, tambahkan terlebih dahulu:
```powershell
git remote add upstream https://github.com/diegosouzapw/OmniRoute.git
```
同步上游前,先抓取最新提交和标签:
Sebelum menyinkronkan upstream, ambil commit dan tag terbaru:
```powershell
git fetch upstream --tags
```
查看当前版本和上游标签:
Lihat versi saat ini dan tag upstream:
```powershell
git describe --tags --always
git show --no-patch --oneline v3.4.7
```
如果你想合并上游最新 `main`,并强制保留 fork 当前的 `fly.toml`,可按下面流程执行:
Jika Anda ingin menggabungkan `main` upstream terbaru sambil mempertahankan `fly.toml` fork saat ini secara paksa, ikuti alur berikut:
```powershell
git merge upstream/main
@@ -296,52 +296,52 @@ git commit -m "chore(deploy): keep fork fly.toml"
git push origin main
```
说明:
Keterangan:
- `git merge upstream/main` 用于同步原仓库最新代码
- `git checkout HEAD~1 -- fly.toml` 用于恢复合并前你 fork 自己的 `fly.toml`
- 如果上游没有改 `fly.toml`,这一步不会带来额外差异
- 如果上游改了 `fly.toml`,这一步能确保 Fly 应用名、挂载卷、区域等 fork 自定义部署配置不被覆盖
- `git merge upstream/main` digunakan untuk menyinkronkan kode terbaru dari repositori asal
- `git checkout HEAD~1 -- fly.toml` digunakan untuk memulihkan `fly.toml` fork Anda sebelum penggabungan
- Jika upstream tidak mengubah `fly.toml`, langkah ini tidak akan menimbulkan perbedaan tambahan
- Jika upstream mengubah `fly.toml`, langkah ini memastikan konfigurasi deployment kustom fork Anda seperti nama aplikasi Fly, volume pemasangan, dan region tidak tertimpa
如果你明确只想对齐某个发布标签,例如 `v3.4.7`,也可以先确认标签是否已经包含在 `upstream/main`
Jika Anda hanya ingin menyejajarkan dengan tag rilis tertentu, misalnya `v3.4.7`, konfirmasi terlebih dahulu apakah tag tersebut sudah tercakup dalam `upstream/main`:
```powershell
git merge-base --is-ancestor v3.4.7 upstream/main
```
返回成功表示 `upstream/main` 已经包含该版本,直接合并 `upstream/main` 即可。
Jika berhasil, berarti `upstream/main` sudah mengandung versi tersebut dan Anda dapat langsung menggabungkan `upstream/main`.
### 9.2 同步上游后的标准发布顺序
### 9.2 Urutan Publikasi Standar Setelah Sinkronisasi Upstream
同步原仓库完成后,推荐按下面顺序发布:
Setelah selesai menyinkronkan repositori asal, ikuti urutan publikasi berikut:
1. `git fetch upstream --tags`
2. `git merge upstream/main`
3. 恢复 fork 的 `fly.toml`
3. Pulihkan `fly.toml` dari fork
4. `git push origin main`
5. `flyctl deploy`
6. `flyctl status -a omniroute`
7. `flyctl logs --no-tail -a omniroute`
这就是当前项目升级到 `v3.4.7` 时使用的实际流程。
Inilah alur yang digunakan saat proyek ini diperbarui ke `v3.4.7`.
---
## 10. 发布后检查
## 10. Pemeriksaan Setelah Deployment
### 10.1 查看应用状态
### 10.1 Lihat Status Aplikasi
```powershell
flyctl status -a omniroute
```
### 10.2 查看启动日志
### 10.2 Lihat Log Startup
```powershell
flyctl logs --no-tail -a omniroute
```
### 10.3 检查网站可访问
### 10.3 Periksa Aksesibilitas Situs
```powershell
try {
@@ -355,82 +355,82 @@ try {
}
```
返回 `200` 说明站点已正常响应。
Jika mengembalikan `200`, berarti situs sudah merespons dengan normal.
---
## 11. 成功标志
## 11. Indikator Keberhasilan
部署成功后,日志里应看到类似内容:
Setelah deployment berhasil, Anda seharusnya melihat konten seperti berikut di log:
```text
[bootstrap] Secrets persisted to: /data/server.env
[DB] SQLite database ready: /data/storage.sqlite
```
这两个点很关键:
Dua poin ini sangat penting:
- `/data/server.env` 说明运行时密钥落到了持久卷
- `/data/storage.sqlite` 说明数据库写入持久卷
- `/data/server.env` menunjukkan bahwa kunci rahasia runtime telah tersimpan ke volume persisten
- `/data/storage.sqlite` menunjukkan bahwa database telah ditulis ke volume persisten
如果你看到的是 `/app/data/...`,说明 `DATA_DIR` 没配对,需要立即修正。
Jika yang Anda lihat adalah `/app/data/...`, berarti `DATA_DIR` tidak dikonfigurasi dengan benar dan harus segera diperbaiki.
---
## 12. 常见问题
## 12. Masalah Umum
### 12.1 `Secrets` 页面是空的
### 12.1 Halaman `Secrets` Kosong
通常有两种原因:
Biasanya ada dua penyebab:
- 你还没执行 `flyctl secrets set`
- 你打开的是另一个应用,例如 `oroute`,不是 `omniroute`
- Anda belum menjalankan `flyctl secrets set`
- Anda membuka aplikasi yang salah, misalnya `oroute`, bukan `omniroute`
### 12.2 `flyctl deploy` `app not found`
### 12.2 `flyctl deploy` Melaporkan `app not found`
先创建应用:
Buat aplikasinya terlebih dahulu:
```powershell
flyctl apps create omniroute
```
### 12.3 `fly.toml` 解析失败
### 12.3 Parsing `fly.toml` Gagal
重点检查:
Periksa secara khusus:
- 注释里是否有乱码字符
- TOML 引号和缩进是否正确
- Apakah ada karakter tidak valid di dalam komentar
- Apakah tanda kutip dan indentasi TOML sudah benar
### 12.4 数据没有持久化
### 12.4 Data Tidak Tersimpan Secara Persisten
检查以下两点:
Periksa dua hal berikut:
- `fly.toml` 中是否存在 `destination = '/data'`
- `DATA_DIR` 是否设置为 `/data`
- Apakah `destination = '/data'` ada di `fly.toml`
- Apakah `DATA_DIR` sudah disetel ke `/data`
### 12.5 不设置 `INITIAL_PASSWORD` 是否能跑
### 12.5 Apakah Bisa Berjalan Tanpa Menyetel `INITIAL_PASSWORD`
可以运行,但会回退到默认 `CHANGEME`。生产环境建议尽快修改后台密码。
Bisa berjalan, tetapi akan menggunakan kata sandi default `CHANGEME`. Untuk lingkungan produksi, disarankan untuk segera mengubah kata sandi panel admin.
---
## 13. 新项目复用建议
## 13. Rekomendasi untuk Penggunaan Ulang pada Proyek Baru
如果以后是新项目照着这份文档部署,最少改这几项:
Jika di kemudian hari Anda melakukan deployment proyek baru mengikuti panduan ini, setidaknya ubah item-item berikut:
1. 修改 `fly.toml` 里的 `app`
2. 修改 `NEXT_PUBLIC_BASE_URL`
3. 保持 `DATA_DIR=/data`
4. 重新生成 `API_KEY_SECRET``JWT_SECRET``MACHINE_ID_SALT``STORAGE_ENCRYPTION_KEY`
5. 首次部署后检查日志是否写入 `/data`
1. Ubah nilai `app` di `fly.toml`
2. Ubah `NEXT_PUBLIC_BASE_URL`
3. Pertahankan `DATA_DIR=/data`
4. Buat ulang `API_KEY_SECRET`, `JWT_SECRET`, `MACHINE_ID_SALT`, dan `STORAGE_ENCRYPTION_KEY`
5. Setelah deployment pertama, periksa log apakah data sudah ditulis ke `/data`
不要直接复用旧项目的密钥。
Jangan gunakan ulang kunci dari proyek lama.
---
## 14. 当前项目的最小发布清单
## 14. Daftar Periksa Publikasi Minimal untuk Proyek Saat Ini
当前项目后续最常用的命令如下:
Berikut adalah perintah yang paling sering digunakan untuk proyek saat ini:
```powershell
flyctl auth whoami
@@ -440,13 +440,13 @@ flyctl deploy
flyctl logs --no-tail -a omniroute
```
如果只是正常发版,核心就是:
Untuk publikasi rutin biasa, perintah intinya adalah:
```powershell
flyctl deploy
```
如果是新环境首次部署,核心就是:
Untuk deployment pertama di lingkungan baru, langkah intinya adalah:
1. `flyctl auth login`
2. `flyctl apps create omniroute`

View File

@@ -1,44 +1,44 @@
# Release Checklist (Bahasa Indonesia)
# Daftar Periksa Rilis (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇧🇩 [bn](../../bn/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇮🇷 [fa](../../fa/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [gu](../../gu/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [hi](../../hi/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [mr](../../mr/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇰🇪 [sw](../../sw/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [ta](../../ta/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [te](../../te/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇹🇷 [tr](../../tr/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇵🇰 [ur](../../ur/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md)
---
Use this checklist before tagging or publishing a new OmniRoute release.
Gunakan daftar periksa ini sebelum memberi tag atau menerbitkan rilis OmniRoute baru.
## Version and Changelog
## Versi dan Changelog
1. Bump `package.json` version (`x.y.z`) in the release branch.
2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
1. Naikkan versi `package.json` (`x.y.z`) di cabang rilis.
2. Pindahkan catatan rilis dari `## [Unreleased]` di `CHANGELOG.md` ke bagian bertanggal:
- `## [x.y.z] — YYYY-MM-DD`
3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
3. Pertahankan `## [Unreleased]` sebagai bagian changelog pertama untuk pekerjaan mendatang.
4. Pastikan bagian semver terbaru di `CHANGELOG.md` sama dengan versi `package.json`.
## API Docs
## Dokumentasi API
1. Update `docs/reference/openapi.yaml`:
- `info.version` must equal `package.json` version.
2. Validate endpoint examples if API contracts changed.
1. Perbarui `docs/reference/openapi.yaml`:
- `info.version` harus sama dengan versi `package.json`.
2. Validasi contoh endpoint jika kontrak API berubah.
## Runtime Docs
## Dokumentasi Runtime
1. Review `docs/architecture/ARCHITECTURE.md` for storage/runtime drift.
2. Review `docs/guides/TROUBLESHOOTING.md` for env var and operational drift.
3. Verify the release/runtime Node.js version still satisfies the supported secure floor:
- `>=20.20.2 <21` or `>=22.22.2 <23`
1. Tinjau `docs/architecture/ARCHITECTURE.md` untuk penyimpangan storage/runtime.
2. Tinjau `docs/guides/TROUBLESHOOTING.md` untuk penyimpangan variabel env dan operasional.
3. Verifikasi bahwa versi Node.js rilis/runtime masih memenuhi batas aman yang didukung:
- `>=20.20.2 <21` atau `>=22.22.2 <23`
- `npm run check:node-runtime`
4. Validate the npm publish artifact after building the standalone package:
4. Validasi artefak penerbitan npm setelah membangun paket standalone:
- `npm run build:cli`
- `npm run check:pack-artifact`
- confirm no `app.__qa_backup`, `scripts/scratch`, `package-lock.json`, or other local residue
5. Update localized docs if source docs changed significantly.
- konfirmasi tidak ada `app.__qa_backup`, `scripts/scratch`, `package-lock.json`, atau residu lokal lainnya
5. Perbarui dokumentasi terlokalisasi jika dokumentasi sumber berubah secara signifikan.
## Automated Check
## Pemeriksaan Otomatis
Run the sync guard locally before opening PR:
Jalankan penjaga sinkronisasi secara lokal sebelum membuka PR:
```bash
npm run check:docs-sync
```
CI also runs this check in `.github/workflows/ci.yml` (lint job).
CI juga menjalankan pemeriksaan ini di `.github/workflows/ci.yml` (pekerjaan lint).

View File

@@ -1,52 +1,52 @@
# OmniRoute — Deployment Guide on VM with Cloudflare (Bahasa Indonesia)
# OmniRoute — Panduan Deployment di VM dengan Cloudflare (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇩 [bn](../../bn/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇷 [fa](../../fa/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [gu](../../gu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [hi](../../hi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [mr](../../mr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇪 [sw](../../sw/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [ta](../../ta/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [te](../../te/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇷 [tr](../../tr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇰 [ur](../../ur/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md)
---
Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
Panduan lengkap untuk menginstal dan mengkonfigurasi OmniRoute pada sebuah VM (VPS) dengan domain yang dikelola melalui Cloudflare.
---
## Prerequisites
## Prasyarat
| Item | Minimum | Recommended |
| Item | Minimum | Direkomendasikan |
| ---------- | ------------------------ | ---------------- |
| **CPU** | 1 vCPU | 2 vCPU |
| **RAM** | 1 GB | 2 GB |
| **Disk** | 10 GB SSD | 25 GB SSD |
| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
| **Domain** | Registered on Cloudflare | — |
| **Domain** | Terdaftar di Cloudflare | — |
| **Docker** | Docker Engine 24+ | Docker 27+ |
**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
**Provider yang telah diuji**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
---
## 1. Configure the VM
## 1. Konfigurasi VM
### 1.1 Create the instance
### 1.1 Buat instans
On your preferred VPS provider:
Pada provider VPS pilihan Anda:
- Choose Ubuntu 24.04 LTS
- Select the minimum plan (1 vCPU / 1 GB RAM)
- Set a strong root password or configure SSH key
- Note the **public IP** (e.g., `203.0.113.10`)
- Pilih Ubuntu 24.04 LTS
- Pilih paket minimum (1 vCPU / 1 GB RAM)
- Tetapkan kata sandi root yang kuat atau konfigurasikan SSH key
- Catat **IP publik** (misalnya, `203.0.113.10`)
### 1.2 Connect via SSH
### 1.2 Hubungkan melalui SSH
```bash
ssh root@203.0.113.10
```
### 1.3 Update the system
### 1.3 Perbarui sistem
```bash
apt update && apt upgrade -y
```
### 1.4 Install Docker
### 1.4 Instal Docker
```bash
# Install dependencies
@@ -56,18 +56,18 @@ apt install -y ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo $VERSION_CODENAME) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
```
### 1.5 Install nginx
### 1.5 Instal nginx
```bash
apt install -y nginx
```
### 1.6 Configure Firewall (UFW)
### 1.6 Konfigurasi Firewall (UFW)
```bash
ufw default deny incoming
@@ -78,22 +78,22 @@ ufw allow 443/tcp # HTTPS
ufw enable
```
> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
> **Tips**: Untuk keamanan maksimal, batasi port 80 dan 443 hanya untuk IP Cloudflare. Lihat bagian [Keamanan Lanjutan](#keamanan-lanjutan).
---
## 2. Install OmniRoute
## 2. Instal OmniRoute
### 2.1 Create configuration directory
### 2.1 Buat direktori konfigurasi
```bash
mkdir -p /opt/omniroute
```
### 2.2 Create environment variables file
### 2.2 Buat file variabel lingkungan
```bash
cat > /opt/omniroute/.env << EOF
cat > /opt/omniroute/.env << 'EOF'
# === Security ===
JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
INITIAL_PASSWORD=YourSecurePassword123!
@@ -122,9 +122,9 @@ NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
EOF
```
> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
> ⚠️ **PENTING**: Buat secret key yang unik! Gunakan `openssl rand -hex 32` untuk setiap key.
### 2.3 Start the container
### 2.3 Jalankan container
```bash
docker pull diegosouzapw/omniroute:latest
@@ -138,27 +138,27 @@ docker run -d \
diegosouzapw/omniroute:latest
```
### 2.4 Verify that it is running
### 2.4 Verifikasi bahwa container berjalan
```bash
docker ps | grep omniroute
docker logs omniroute --tail 20
```
It should display: `[DB] SQLite database ready` and `listening on port 20128`.
Seharusnya menampilkan: `[DB] SQLite database ready` dan `listening on port 20128`.
---
## 3. Configure nginx (Reverse Proxy)
## 3. Konfigurasi nginx (Reverse Proxy)
### 3.1 Generate SSL certificate (Cloudflare Origin)
### 3.1 Buat sertifikat SSL (Cloudflare Origin)
In the Cloudflare dashboard:
Di dasbor Cloudflare:
1. Go to **SSL/TLS → Origin Server**
2. Click **Create Certificate**
3. Keep the defaults (15 years, \*.yourdomain.com)
4. Copy the **Origin Certificate** and the **Private Key**
1. Buka **SSL/TLS → Origin Server**
2. Klik **Create Certificate**
3. Biarkan pengaturan default (15 tahun, \*.yourdomain.com)
4. Salin **Origin Certificate** dan **Private Key**
```bash
mkdir -p /etc/nginx/ssl
@@ -172,10 +172,10 @@ nano /etc/nginx/ssl/origin.key
chmod 600 /etc/nginx/ssl/origin.key
```
### 3.2 Nginx Configuration
### 3.2 Konfigurasi Nginx
```bash
cat > /etc/nginx/sites-available/omniroute << NGINX
cat > /etc/nginx/sites-available/omniroute << 'NGINX'
# Default server — blocks direct access via IP
server {
listen 80 default_server;
@@ -210,7 +210,7 @@ server {
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Connection "upgrade";
# SSE (Server-Sent Events) — streaming AI responses
proxy_buffering off;
@@ -230,11 +230,11 @@ server {
NGINX
```
Keep reverse-proxy stream timeouts aligned with your OmniRoute timeout env vars. If you raise
`FETCH_TIMEOUT_MS` / `STREAM_IDLE_TIMEOUT_MS`, raise `proxy_read_timeout` / `proxy_send_timeout`
above the same threshold.
Jaga agar timeout stream reverse-proxy tetap selaras dengan variabel lingkungan timeout OmniRoute Anda. Jika Anda menaikkan
`FETCH_TIMEOUT_MS` / `STREAM_IDLE_TIMEOUT_MS`, naikkan juga `proxy_read_timeout` / `proxy_send_timeout`
di atas nilai yang sama.
### 3.3 Enable and Test
### 3.3 Aktifkan dan Uji
```bash
# Remove default configuration
@@ -249,29 +249,29 @@ nginx -t && systemctl reload nginx
---
## 4. Configure Cloudflare DNS
## 4. Konfigurasi DNS Cloudflare
### 4.1 Add DNS record
### 4.1 Tambahkan rekaman DNS
In the Cloudflare dashboard → DNS:
Di dasbor Cloudflare → DNS:
| Type | Name | Content | Proxy |
| ---- | ------ | ---------------------- | ---------- |
| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
| Tipe | Nama | Konten | Proxy |
| ---- | ------ | ----------------------- | ----------- |
| A | `llms` | `203.0.113.10` (IP VM) | ✅ Proxied |
### 4.2 Configure SSL
### 4.2 Konfigurasi SSL
Under **SSL/TLS → Overview**:
Di bawah **SSL/TLS → Overview**:
- Mode: **Full (Strict)**
Under **SSL/TLS → Edge Certificates**:
Di bawah **SSL/TLS → Edge Certificates**:
- Always Use HTTPS: ✅ On
- Minimum TLS Version: TLS 1.2
- Automatic HTTPS Rewrites: ✅ On
### 4.3 Testing
### 4.3 Pengujian
```bash
curl -sI https://llms.seudominio.com/health
@@ -280,9 +280,9 @@ curl -sI https://llms.seudominio.com/health
---
## 5. Operations and Maintenance
## 5. Operasi dan Pemeliharaan
### Upgrade to a new version
### Upgrade ke versi baru
```bash
docker pull diegosouzapw/omniroute:latest
@@ -294,14 +294,14 @@ docker run -d --name omniroute --restart unless-stopped \
diegosouzapw/omniroute:latest
```
### View logs
### Lihat log
```bash
docker logs -f omniroute # Real-time stream
docker logs omniroute --tail 50 # Last 50 lines
```
### Manual database backup
### Pencadangan database secara manual
```bash
# Copy data from the volume to the host
@@ -312,23 +312,23 @@ docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
```
### Restore from backup
### Pulihkan dari cadangan
```bash
docker stop omniroute
docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
alpine sh -c rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /
alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /"
docker start omniroute
```
---
## 6. Advanced Security
## 6. Keamanan Lanjutan
### Restrict nginx to Cloudflare IPs
### Batasi nginx ke IP Cloudflare
```bash
cat > /etc/nginx/cloudflare-ips.conf << CF
cat > /etc/nginx/cloudflare-ips.conf << 'CF'
# Cloudflare IPv4 ranges — update periodically
# https://www.cloudflare.com/ips-v4/
set_real_ip_from 173.245.48.0/20;
@@ -350,13 +350,13 @@ real_ip_header CF-Connecting-IP;
CF
```
Add the following to `nginx.conf` inside the `http {}` block:
Tambahkan baris berikut ke `nginx.conf` di dalam blok `http {}`:
```nginx
include /etc/nginx/cloudflare-ips.conf;
```
### Install fail2ban
### Instal fail2ban
```bash
apt install -y fail2ban
@@ -367,7 +367,7 @@ systemctl start fail2ban
fail2ban-client status sshd
```
### Block direct access to the Docker port
### Blokir akses langsung ke port Docker
```bash
# Prevent direct external access to port 20128
@@ -381,9 +381,9 @@ netfilter-persistent save
---
## 7. Deploy to Cloudflare Workers (Optional)
## 7. Deploy ke Cloudflare Workers (Opsional)
For remote access via Cloudflare Workers (without exposing the VM directly):
Untuk akses jarak jauh melalui Cloudflare Workers (tanpa mengekspos VM secara langsung):
```bash
# In the local repository
@@ -393,15 +393,15 @@ npx wrangler login
npx wrangler deploy
```
See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
Lihat dokumentasi lengkap di [omnirouteCloud/README.md](../omnirouteCloud/README.md).
---
## Port Summary
## Ringkasan Port
| Port | Service | Access |
| ----- | ----------- | -------------------------- |
| 22 | SSH | Public (with fail2ban) |
| 80 | nginx HTTP | Redirect → HTTPS |
| 443 | nginx HTTPS | Via Cloudflare Proxy |
| 20128 | OmniRoute | Localhost only (via nginx) |
| Port | Layanan | Akses |
| ----- | ----------- | ------------------------------- |
| 22 | SSH | Publik (dengan fail2ban) |
| 80 | nginx HTTP | Redirect → HTTPS |
| 443 | nginx HTTPS | Melalui Cloudflare Proxy |
| 20128 | OmniRoute | Hanya localhost (melalui nginx) |

View File

@@ -1,24 +1,24 @@
# API Reference (Bahasa Indonesia)
# Referensi API (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇧🇩 [bn](../../bn/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇮🇷 [fa](../../fa/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇮🇳 [gu](../../gu/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇮🇳 [hi](../../hi/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇮🇳 [mr](../../mr/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇰🇪 [sw](../../sw/docs/API_REFERENCE.md) · 🇮🇳 [ta](../../ta/docs/API_REFERENCE.md) · 🇮🇳 [te](../../te/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇹🇷 [tr](../../tr/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇵🇰 [ur](../../ur/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md)
---
Complete reference for all OmniRoute API endpoints.
Referensi lengkap untuk semua titik akhir API OmniRoute.
---
## Table of Contents
## Daftar Isi
- [Chat Completions](#chat-completions)
- [Embeddings](#embeddings)
- [Image Generation](#image-generation)
- [List Models](#list-models)
- [Compatibility Endpoints](#compatibility-endpoints)
- [Semantic Cache](#semantic-cache)
- [Dashboard & Management](#dashboard--management)
- [Request Processing](#request-processing)
- [Authentication](#authentication)
- [Pembuatan Gambar](#image-generation)
- [Daftar Model](#list-models)
- [Titik Akhir Kompatibilitas](#compatibility-endpoints)
- [Cache Semantik](#semantic-cache)
- [Dasbor & Manajemen](#dashboard--management)
- [Pemrosesan Permintaan](#request-processing)
- [Otentikasi](#authentication)
---
@@ -38,22 +38,22 @@ Content-Type: application/json
}
```
### Custom Headers
### Header Kustom
| Header | Direction | Description |
| ------------------------ | --------- | ------------------------------------------------ |
| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
| `X-Session-Id` | Request | Sticky session key for external session affinity |
| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
| `Idempotency-Key` | Request | Dedup key (5s window) |
| `X-Request-Id` | Request | Alternative dedup key |
| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
| Header | Arah | Deskripsi |
| ------------------------ | --------- | ------------------------------------------------------------ |
| `X-OmniRoute-No-Cache` | Permintaan | Atur ke `true` untuk melewati cache |
| `X-OmniRoute-Progress` | Permintaan | Atur ke `true` untuk event progres |
| `X-Session-Id` | Permintaan | Kunci sesi tetap untuk afinitas sesi eksternal |
| `x_session_id` | Permintaan | Varian garis bawah juga diterima (HTTP langsung) |
| `Idempotency-Key` | Permintaan | Kunci deduplikasi (jendela 5 detik) |
| `X-Request-Id` | Permintaan | Kunci deduplikasi alternatif |
| `X-OmniRoute-Cache` | Respons | `HIT` atau `MISS` (non-streaming) |
| `X-OmniRoute-Idempotent` | Respons | `true` jika dideduplikasi |
| `X-OmniRoute-Progress` | Respons | `enabled` jika pelacakan progres aktif |
| `X-OmniRoute-Session-Id` | Respons | ID sesi efektif yang digunakan OmniRoute |
> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
> Catatan Nginx: jika Anda mengandalkan header bergaris bawah (misalnya `x_session_id`), aktifkan `underscores_in_headers on;`.
---
@@ -70,7 +70,7 @@ Content-Type: application/json
}
```
Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA, **OpenRouter**, **GitHub Models**.
Penyedia yang tersedia: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA, **OpenRouter**, **GitHub Models**.
```bash
# List all embedding models
@@ -93,7 +93,7 @@ Content-Type: application/json
}
```
Available providers: OpenAI (GPT Image 2), xAI (Grok Image), Together AI (FLUX), Fireworks AI, Nebius (FLUX), Hyperbolic, NanoBanana, **OpenRouter**, SD WebUI (local), ComfyUI (local).
Penyedia yang tersedia: OpenAI (GPT Image 2), xAI (Grok Image), Together AI (FLUX), Fireworks AI, Nebius (FLUX), Hyperbolic, NanoBanana, **OpenRouter**, SD WebUI (lokal), ComfyUI (lokal).
```bash
# List all image models
@@ -102,7 +102,7 @@ GET /v1/images/generations
---
## List Models
## Daftar Model
```bash
GET /v1/models
@@ -113,9 +113,9 @@ Authorization: Bearer your-api-key
---
## Compatibility Endpoints
## Titik Akhir Kompatibilitas
| Method | Path | Format |
| Metode | Path | Format |
| ------ | --------------------------- | ---------------------- |
| POST | `/v1/chat/completions` | OpenAI |
| POST | `/v1/messages` | Anthropic |
@@ -128,7 +128,7 @@ Authorization: Bearer your-api-key
| POST | `/v1beta/models/{...path}` | Gemini generateContent |
| POST | `/v1/api/chat` | Ollama |
### Dedicated Provider Routes
### Rute Penyedia Khusus
```bash
POST /v1/providers/{provider}/chat/completions
@@ -136,11 +136,11 @@ POST /v1/providers/{provider}/embeddings
POST /v1/providers/{provider}/images/generations
```
The provider prefix is auto-added if missing. Mismatched models return `400`.
Prefiks penyedia ditambahkan secara otomatis jika tidak ada. Model yang tidak cocok mengembalikan `400`.
---
## Semantic Cache
## Cache Semantik
```bash
# Get cache stats
@@ -150,7 +150,7 @@ GET /api/cache/stats
DELETE /api/cache/stats
```
Response example:
Contoh respons:
```json
{
@@ -169,171 +169,171 @@ Response example:
---
## Dashboard & Management
## Dasbor & Manajemen
### Authentication
### Otentikasi
| Endpoint | Method | Description |
| ----------------------------- | ------- | --------------------- |
| `/api/auth/login` | POST | Login |
| `/api/auth/logout` | POST | Logout |
| `/api/settings/require-login` | GET/PUT | Toggle login required |
| Titik Akhir | Metode | Deskripsi |
| ----------------------------- | ------- | ---------------------------------- |
| `/api/auth/login` | POST | Masuk |
| `/api/auth/logout` | POST | Keluar |
| `/api/settings/require-login` | GET/PUT | Aktifkan/nonaktifkan wajib login |
### Provider Management
### Manajemen Penyedia
| Endpoint | Method | Description |
| ---------------------------- | --------------------- | ---------------------------------------------- |
| `/api/providers` | GET/POST | List / create providers |
| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
| `/api/providers/[id]/test` | POST | Test provider connection |
| `/api/providers/[id]/models` | GET | List provider models |
| `/api/providers/validate` | POST | Validate provider config |
| `/api/provider-nodes*` | Various | Provider node management |
| `/api/provider-models` | GET/POST/PATCH/DELETE | Custom models (add, update, hide/show, delete) |
| Titik Akhir | Metode | Deskripsi |
| ---------------------------- | --------------------- | ---------------------------------------------------------- |
| `/api/providers` | GET/POST | Daftar / buat penyedia |
| `/api/providers/[id]` | GET/PUT/DELETE | Kelola penyedia |
| `/api/providers/[id]/test` | POST | Uji koneksi penyedia |
| `/api/providers/[id]/models` | GET | Daftar model penyedia |
| `/api/providers/validate` | POST | Validasi konfigurasi penyedia |
| `/api/provider-nodes*` | Berbagai | Manajemen simpul penyedia |
| `/api/provider-models` | GET/POST/PATCH/DELETE | Model kustom (tambah, perbarui, sembunyikan/tampilkan, hapus) |
### OAuth Flows
### Alur OAuth
| Endpoint | Method | Description |
| -------------------------------- | ------- | ----------------------- |
| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
| Titik Akhir | Metode | Deskripsi |
| -------------------------------- | -------- | ----------------------------- |
| `/api/oauth/[provider]/[action]` | Berbagai | OAuth khusus penyedia |
### Routing & Config
### Perutean & Konfigurasi
| Endpoint | Method | Description |
| --------------------- | -------- | ----------------------------- |
| `/api/models/alias` | GET/POST | Model aliases |
| `/api/models/catalog` | GET | All models by provider + type |
| `/api/combos*` | Various | Combo management |
| `/api/keys*` | Various | API key management |
| `/api/pricing` | GET | Model pricing |
| Titik Akhir | Metode | Deskripsi |
| --------------------- | -------- | ----------------------------------- |
| `/api/models/alias` | GET/POST | Alias model |
| `/api/models/catalog` | GET | Semua model berdasarkan penyedia + tipe |
| `/api/combos*` | Berbagai | Manajemen combo |
| `/api/keys*` | Berbagai | Manajemen kunci API |
| `/api/pricing` | GET | Harga model |
### Usage & Analytics
### Penggunaan & Analitik
| Endpoint | Method | Description |
| --------------------------- | ------ | -------------------- |
| `/api/usage/history` | GET | Usage history |
| `/api/usage/logs` | GET | Usage logs |
| `/api/usage/request-logs` | GET | Request-level logs |
| `/api/usage/[connectionId]` | GET | Per-connection usage |
| Titik Akhir | Metode | Deskripsi |
| --------------------------- | ------ | ------------------------------ |
| `/api/usage/history` | GET | Riwayat penggunaan |
| `/api/usage/logs` | GET | Log penggunaan |
| `/api/usage/request-logs` | GET | Log tingkat permintaan |
| `/api/usage/[connectionId]` | GET | Penggunaan per koneksi |
### Settings
### Pengaturan
| Endpoint | Method | Description |
| ------------------------------- | ------------- | ---------------------- |
| `/api/settings` | GET/PUT/PATCH | General settings |
| `/api/settings/proxy` | GET/PUT | Network proxy config |
| `/api/settings/proxy/test` | POST | Test proxy connection |
| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
| Titik Akhir | Metode | Deskripsi |
| ------------------------------- | ------------- | ------------------------------- |
| `/api/settings` | GET/PUT/PATCH | Pengaturan umum |
| `/api/settings/proxy` | GET/PUT | Konfigurasi proksi jaringan |
| `/api/settings/proxy/test` | POST | Uji koneksi proksi |
| `/api/settings/ip-filter` | GET/PUT | Daftar izin/blokir IP |
| `/api/settings/thinking-budget` | GET/PUT | Anggaran token penalaran |
| `/api/settings/system-prompt` | GET/PUT | Prompt sistem global |
### Monitoring
### Pemantauan
| Endpoint | Method | Description |
| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
| `/api/sessions` | GET | Active session tracking |
| `/api/rate-limits` | GET | Per-account rate limits |
| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
| Titik Akhir | Metode | Deskripsi |
| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------- |
| `/api/sessions` | GET | Pelacakan sesi aktif |
| `/api/rate-limits` | GET | Batas laju per akun |
| `/api/monitoring/health` | GET | Pemeriksaan kesehatan + ringkasan penyedia (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
| `/api/cache/stats` | GET/DELETE | Statistik cache / hapus |
### Backup & Export/Import
### Cadangan & Ekspor/Impor
| Endpoint | Method | Description |
| --------------------------- | ------ | --------------------------------------- |
| `/api/db-backups` | GET | List available backups |
| `/api/db-backups` | PUT | Create a manual backup |
| `/api/db-backups` | POST | Restore from a specific backup |
| `/api/db-backups/export` | GET | Download database as .sqlite file |
| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
| Titik Akhir | Metode | Deskripsi |
| --------------------------- | ------ | ------------------------------------------------ |
| `/api/db-backups` | GET | Daftar cadangan yang tersedia |
| `/api/db-backups` | PUT | Buat cadangan manual |
| `/api/db-backups` | POST | Pulihkan dari cadangan tertentu |
| `/api/db-backups/export` | GET | Unduh database sebagai file .sqlite |
| `/api/db-backups/import` | POST | Unggah file .sqlite untuk mengganti database |
| `/api/db-backups/exportAll` | GET | Unduh cadangan lengkap sebagai arsip .tar.gz |
### Cloud Sync
### Sinkronisasi Cloud
| Endpoint | Method | Description |
| ---------------------- | ------- | --------------------- |
| `/api/sync/cloud` | Various | Cloud sync operations |
| `/api/sync/initialize` | POST | Initialize sync |
| `/api/cloud/*` | Various | Cloud management |
| Titik Akhir | Metode | Deskripsi |
| ---------------------- | -------- | ------------------------------ |
| `/api/sync/cloud` | Berbagai | Operasi sinkronisasi cloud |
| `/api/sync/initialize` | POST | Inisialisasi sinkronisasi |
| `/api/cloud/*` | Berbagai | Manajemen cloud |
### Tunnels
### Terowongan
| Endpoint | Method | Description |
| -------------------------- | ------ | ----------------------------------------------------------------------- |
| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
| Titik Akhir | Metode | Deskripsi |
| -------------------------- | ------ | ----------------------------------------------------------------------------------------------- |
| `/api/tunnels/cloudflared` | GET | Baca status instalasi/runtime Cloudflare Quick Tunnel untuk dasbor |
| `/api/tunnels/cloudflared` | POST | Aktifkan atau nonaktifkan Cloudflare Quick Tunnel (`action=enable/disable`) |
### CLI Tools
### Alat CLI
| Endpoint | Method | Description |
| ---------------------------------- | ------ | ------------------- |
| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
| Titik Akhir | Metode | Deskripsi |
| ---------------------------------- | ------ | ---------------------- |
| `/api/cli-tools/claude-settings` | GET | Status CLI Claude |
| `/api/cli-tools/codex-settings` | GET | Status CLI Codex |
| `/api/cli-tools/droid-settings` | GET | Status CLI Droid |
| `/api/cli-tools/openclaw-settings` | GET | Status CLI OpenClaw |
| `/api/cli-tools/runtime/[toolId]` | GET | Runtime CLI generik |
CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
Respons CLI mencakup: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
### ACP Agents
### Agen ACP
| Endpoint | Method | Description |
| ----------------- | ------ | -------------------------------------------------------- |
| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
| Titik Akhir | Metode | Deskripsi |
| ----------------- | ------ | ------------------------------------------------------------------ |
| `/api/acp/agents` | GET | Daftar semua agen yang terdeteksi (bawaan + kustom) beserta status |
| `/api/acp/agents` | POST | Tambah agen kustom atau segarkan cache deteksi |
| `/api/acp/agents` | DELETE | Hapus agen kustom berdasarkan parameter kueri `id` |
GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
Respons GET mencakup `agents[]` (id, name, binary, version, installed, protocol, isCustom) dan `summary` (total, installed, notFound, builtIn, custom).
### Resilience & Rate Limits
### Ketahanan & Batas Laju
| Endpoint | Method | Description |
| ----------------------- | --------- | ---------------------------------------------------------------------------------- |
| `/api/resilience` | GET/PATCH | Get/update request queue, connection cooldown, provider breaker, and wait settings |
| `/api/resilience/reset` | POST | Reset provider circuit breakers |
| `/api/rate-limits` | GET | Per-account rate limit status |
| `/api/rate-limit` | GET | Global rate limit configuration |
| Titik Akhir | Metode | Deskripsi |
| ----------------------- | --------- | -------------------------------------------------------------------------------------------------- |
| `/api/resilience` | GET/PATCH | Ambil/perbarui antrean permintaan, cooldown koneksi, pemutus sirkuit penyedia, dan pengaturan tunggu |
| `/api/resilience/reset` | POST | Reset pemutus sirkuit penyedia |
| `/api/rate-limits` | GET | Status batas laju per akun |
| `/api/rate-limit` | GET | Konfigurasi batas laju global |
### Evals
### Eval
| Endpoint | Method | Description |
| ------------ | -------- | --------------------------------- |
| `/api/evals` | GET/POST | List eval suites / run evaluation |
| Titik Akhir | Metode | Deskripsi |
| ------------ | -------- | -------------------------------------- |
| `/api/evals` | GET/POST | Daftar suite eval / jalankan evaluasi |
### Policies
### Kebijakan
| Endpoint | Method | Description |
| --------------- | --------------- | ----------------------- |
| `/api/policies` | GET/POST/DELETE | Manage routing policies |
| Titik Akhir | Metode | Deskripsi |
| --------------- | --------------- | ------------------------------ |
| `/api/policies` | GET/POST/DELETE | Kelola kebijakan perutean |
### Compliance
### Kepatuhan
| Endpoint | Method | Description |
| --------------------------- | ------ | ----------------------------- |
| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
| Titik Akhir | Metode | Deskripsi |
| --------------------------- | ------ | ----------------------------------- |
| `/api/compliance/audit-log` | GET | Log audit kepatuhan (N terakhir) |
### v1beta (Gemini-Compatible)
### v1beta (Kompatibel dengan Gemini)
| Endpoint | Method | Description |
| -------------------------- | ------ | --------------------------------- |
| `/v1beta/models` | GET | List models in Gemini format |
| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
| Titik Akhir | Metode | Deskripsi |
| -------------------------- | ------ | ----------------------------------- |
| `/v1beta/models` | GET | Daftar model dalam format Gemini |
| `/v1beta/models/{...path}` | POST | Titik akhir `generateContent` Gemini |
These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
Titik akhir ini mencerminkan format API Gemini untuk klien yang mengharapkan kompatibilitas SDK Gemini asli.
### Internal / System APIs
### API Internal / Sistem
| Endpoint | Method | Description |
| ------------------------ | ------ | ---------------------------------------------------- |
| `/api/init` | GET | Application initialization check (used on first run) |
| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
| `/api/restart` | POST | Trigger graceful server restart |
| `/api/shutdown` | POST | Trigger graceful server shutdown |
| `/api/system/env/repair` | POST | Repair OAuth provider environment variables |
| `/api/system-info` | GET | Generate system diagnostics report |
| Titik Akhir | Metode | Deskripsi |
| ------------------------ | ------ | ---------------------------------------------------------------- |
| `/api/init` | GET | Pemeriksaan inisialisasi aplikasi (digunakan saat pertama kali) |
| `/api/tags` | GET | Tag model kompatibel Ollama (untuk klien Ollama) |
| `/api/restart` | POST | Picu restart server secara halus |
| `/api/shutdown` | POST | Picu penghentian server secara halus |
| `/api/system/env/repair` | POST | Perbaiki variabel lingkungan penyedia OAuth |
| `/api/system-info` | GET | Buat laporan diagnostik sistem |
> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
> **Catatan:** Titik akhir ini digunakan secara internal oleh sistem atau untuk kompatibilitas klien Ollama. Biasanya tidak dipanggil langsung oleh pengguna akhir.
### OAuth Environment Repair _(v3.6.1+)_
### Perbaikan Lingkungan OAuth _(v3.6.1+)_
```bash
POST /api/system/env/repair
@@ -344,7 +344,7 @@ Content-Type: application/json
}
```
Repairs missing or corrupted OAuth environment variables for a specific provider. Returns:
Memperbaiki variabel lingkungan OAuth yang hilang atau rusak untuk penyedia tertentu. Mengembalikan:
```json
{
@@ -356,7 +356,7 @@ Repairs missing or corrupted OAuth environment variables for a specific provider
---
## Audio Transcription
## Transkripsi Audio
```bash
POST /v1/audio/transcriptions
@@ -364,9 +364,9 @@ Authorization: Bearer your-api-key
Content-Type: multipart/form-data
```
Transcribe audio files using Deepgram or AssemblyAI.
Transkripsi file audio menggunakan Deepgram atau AssemblyAI.
**Request:**
**Permintaan:**
```bash
curl -X POST http://localhost:20128/v1/audio/transcriptions \
@@ -375,7 +375,7 @@ curl -X POST http://localhost:20128/v1/audio/transcriptions \
-F "model=deepgram/nova-3"
```
**Response:**
**Respons:**
```json
{
@@ -386,15 +386,15 @@ curl -X POST http://localhost:20128/v1/audio/transcriptions \
}
```
**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
**Penyedia yang didukung:** `deepgram/nova-3`, `assemblyai/best`.
**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
**Format yang didukung:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
---
## Ollama Compatibility
## Kompatibilitas Ollama
For clients that use Ollama's API format:
Untuk klien yang menggunakan format API Ollama:
```bash
# Chat endpoint (Ollama format)
@@ -404,18 +404,18 @@ POST /v1/api/chat
GET /api/tags
```
Requests are automatically translated between Ollama and internal formats.
Permintaan diterjemahkan secara otomatis antara format Ollama dan format internal.
---
## Telemetry
## Telemetri
```bash
# Get latency telemetry summary (p50/p95/p99 per provider)
GET /api/telemetry/summary
```
**Response:**
**Respons:**
```json
{
@@ -428,7 +428,7 @@ GET /api/telemetry/summary
---
## Budget
## Anggaran
```bash
# Get budget status for all API keys
@@ -445,25 +445,25 @@ Content-Type: application/json
}
```
## Request Processing
## Pemrosesan Permintaan
1. Client sends request to `/v1/*`
2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
3. Model is resolved (direct provider/model or alias/combo)
4. Credentials selected from local DB with account availability filtering
5. For chat: `handleChatCore`format detection, translation, cache check, idempotency check
6. Provider executor sends upstream request
7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
8. Usage/logging recorded
9. Fallback applies on errors according to combo rules
1. Klien mengirim permintaan ke `/v1/*`
2. Handler rute memanggil `handleChat`, `handleEmbedding`, `handleAudioTranscription`, atau `handleImageGeneration`
3. Model diselesaikan (penyedia/model langsung, alias, atau combo)
4. Kredensial dipilih dari DB lokal dengan penyaringan ketersediaan akun
5. Untuk chat: `handleChatCore`deteksi format, translasi, pemeriksaan cache, pemeriksaan idempoten
6. Eksekutor penyedia mengirim permintaan upstream
7. Respons diterjemahkan kembali ke format klien (chat) atau dikembalikan apa adanya (embeddings/gambar/audio)
8. Penggunaan/logging dicatat
9. Fallback diterapkan pada error sesuai aturan combo
Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
Referensi arsitektur lengkap: [`ARCHITECTURE.md`](ARCHITECTURE.md)
---
## Authentication
## Otentikasi
- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
- `requireLogin` toggleable via `/api/settings/require-login`
- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
- Rute dasbor (`/dashboard/*`) menggunakan cookie `auth_token`
- Login menggunakan hash kata sandi yang tersimpan; fallback ke `INITIAL_PASSWORD`
- `requireLogin` dapat diaktifkan/nonaktifkan melalui `/api/settings/require-login`
- Rute `/v1/*` secara opsional memerlukan kunci API Bearer saat `REQUIRE_API_KEY=true`

View File

@@ -1,86 +1,86 @@
# CLI Tools Setup Guide — OmniRoute (Bahasa Indonesia)
# Panduan Pengaturan Alat CLI — OmniRoute (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇧🇩 [bn](../../bn/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇮🇷 [fa](../../fa/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇮🇳 [gu](../../gu/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇮🇳 [hi](../../hi/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇮🇳 [mr](../../mr/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇰🇪 [sw](../../sw/docs/CLI-TOOLS.md) · 🇮🇳 [ta](../../ta/docs/CLI-TOOLS.md) · 🇮🇳 [te](../../te/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇹🇷 [tr](../../tr/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇵🇰 [ur](../../ur/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md)
---
This guide explains how to install and configure all supported AI coding CLI tools
to use **OmniRoute** as the unified backend, giving you centralized key management,
cost tracking, model switching, and request logging across every tool.
Panduan ini menjelaskan cara menginstal dan mengonfigurasi semua alat CLI coding AI yang didukung
untuk menggunakan **OmniRoute** sebagai backend terpadu, memberikan manajemen kunci terpusat,
pelacakan biaya, pergantian model, dan pencatatan permintaan di semua alat.
---
## How It Works
## Cara Kerjanya
```
Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
▼ (all point to OmniRoute)
▼ (semua mengarah ke OmniRoute)
http://YOUR_SERVER:20128/v1
▼ (OmniRoute routes to the right provider)
▼ (OmniRoute meneruskan ke penyedia yang tepat)
Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
```
**Benefits:**
**Manfaat:**
- One API key to manage all tools
- Cost tracking across all CLIs in the dashboard
- Model switching without reconfiguring every tool
- Works locally and on remote servers (VPS)
- Satu API key untuk mengelola semua alat
- Pelacakan biaya di semua CLI melalui dashboard
- Pergantian model tanpa mengonfigurasi ulang setiap alat
- Berjalan secara lokal maupun di server jarak jauh (VPS)
---
## Supported Tools (Dashboard Source of Truth)
## Alat yang Didukung (Sumber Kebenaran Dashboard)
The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
Current list (v3.0.0-rc.16):
Kartu dashboard di `/dashboard/cli-tools` dibuat dari `src/shared/constants/cliTools.ts`.
Daftar saat ini (v3.0.0-rc.16):
| Tool | ID | Command | Setup Mode | Install Method |
| ------------------ | ------------- | ---------- | ---------- | -------------- |
| **Claude Code** | `claude` | `claude` | env | npm |
| **OpenAI Codex** | `codex` | `codex` | custom | npm |
| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
| **Cursor** | `cursor` | app | guide | desktop app |
| **Cline** | `cline` | `cline` | custom | npm |
| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
| **Continue** | `continue` | extension | guide | VS Code |
| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
| **OpenCode** | `opencode` | `opencode` | guide | npm |
| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
| **Qwen Code** | `qwen` | `qwen` | custom | npm |
| Alat | ID | Perintah | Mode Pengaturan | Metode Instalasi |
| ------------------ | ------------- | ---------- | --------------- | ---------------- |
| **Claude Code** | `claude` | `claude` | env | npm |
| **OpenAI Codex** | `codex` | `codex` | custom | npm |
| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
| **Cursor** | `cursor` | app | guide | desktop app |
| **Cline** | `cline` | `cline` | custom | npm |
| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
| **Continue** | `continue` | extension | guide | VS Code |
| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
| **OpenCode** | `opencode` | `opencode` | guide | npm |
| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
| **Qwen Code** | `qwen` | `qwen` | custom | npm |
### CLI fingerprint sync (Agents + Settings)
### Sinkronisasi fingerprint CLI (Agents + Pengaturan)
`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
This keeps provider IDs aligned with CLI cards and legacy IDs.
`/dashboard/agents` dan `Settings > CLI Fingerprint` menggunakan `src/shared/constants/cliCompatProviders.ts`.
Ini menjaga ID penyedia tetap selaras dengan kartu CLI dan ID lama.
| CLI ID | Fingerprint Provider ID |
| CLI ID | ID Penyedia Fingerprint |
| ---------------------------------------------------------------------------------------------------- | ----------------------- |
| `kilo` | `kilocode` |
| `copilot` | `github` |
| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
ID lama yang masih diterima untuk kompatibilitas: `copilot`, `kimi-coding`, `qwen`.
---
## Step 1 — Get an OmniRoute API Key
## Langkah 1 — Dapatkan API Key OmniRoute
1. Open the OmniRoute dashboard**API Manager** (`/dashboard/api-manager`)
2. Click **Create API Key**
3. Give it a name (e.g. `cli-tools`) and select all permissions
4. Copy the key — you'll need it for every CLI below
1. Buka dashboard OmniRoute**API Manager** (`/dashboard/api-manager`)
2. Klik **Create API Key**
3. Beri nama (misalnya `cli-tools`) dan pilih semua izin
4. Salin kunci tersebut — Anda akan membutuhkannya untuk setiap CLI di bawah
> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
> Kunci Anda terlihat seperti: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
---
## Step 2 — Install CLI Tools
## Langkah 2 — Instal Alat CLI
All npm-based tools require Node.js 18+:
Semua alat berbasis npm memerlukan Node.js 18+:
```bash
# Claude Code (Anthropic)
@@ -104,7 +104,7 @@ curl -fsSL https://cli.kiro.dev/install | bash
export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
```
**Verify:**
**Verifikasi:**
```bash
claude --version # 2.x.x
@@ -117,9 +117,9 @@ kiro-cli --version # 1.x.x
---
## Step 3 — Set Global Environment Variables
## Langkah 3 — Tetapkan Variabel Lingkungan Global
Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
Tambahkan ke `~/.bashrc` (atau `~/.zshrc`), lalu jalankan `source ~/.bashrc`:
```bash
# OmniRoute Universal Endpoint
@@ -131,20 +131,20 @@ export GEMINI_BASE_URL="http://localhost:20128/v1"
export GEMINI_API_KEY="sk-your-omniroute-key"
```
> For a **remote server** replace `localhost:20128` with the server IP or domain,
> e.g. `http://192.168.0.15:20128`.
> Untuk **server jarak jauh**, ganti `localhost:20128` dengan IP atau domain server,
> misalnya `http://192.168.0.15:20128`.
---
## Step 4 — Configure Each Tool
## Langkah 4 — Konfigurasi Setiap Alat
### Claude Code
```bash
# Via CLI:
# Melalui CLI:
claude config set --global api-base-url http://localhost:20128/v1
# Or create ~/.claude/settings.json:
# Atau buat ~/.claude/settings.json:
mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
{
"apiBaseUrl": "http://localhost:20128/v1",
@@ -153,7 +153,7 @@ mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
EOF
```
**Test:** `claude "say hello"`
**Uji:** `claude "say hello"`
---
@@ -167,7 +167,7 @@ apiBaseUrl: http://localhost:20128/v1
EOF
```
**Test:** `codex "what is 2+2?"`
**Uji:** `codex "what is 2+2?"`
---
@@ -181,13 +181,13 @@ api_key = "sk-your-omniroute-key"
EOF
```
**Test:** `opencode`
**Uji:** `opencode`
---
### Cline (CLI or VS Code)
### Cline (CLI atau VS Code)
**CLI mode:**
**Mode CLI:**
```bash
mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
@@ -199,22 +199,22 @@ mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
EOF
```
**VS Code mode:**
Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
**Mode VS Code:**
Pengaturan ekstensi Cline → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
Or use the OmniRoute dashboard**CLI Tools → Cline → Apply Config**.
Atau gunakan dashboard OmniRoute**CLI Tools → Cline → Apply Config**.
---
### KiloCode (CLI or VS Code)
### KiloCode (CLI atau VS Code)
**CLI mode:**
**Mode CLI:**
```bash
kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
```
**VS Code settings:**
**Pengaturan VS Code:**
```json
{
@@ -223,11 +223,11 @@ kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
}
```
Or use the OmniRoute dashboard**CLI Tools → KiloCode → Apply Config**.
Atau gunakan dashboard OmniRoute**CLI Tools → KiloCode → Apply Config**.
---
### Continue (VS Code Extension)
### Continue (Ekstensi VS Code)
Edit `~/.continue/config.yaml`:
@@ -241,18 +241,18 @@ models:
default: true
```
Restart VS Code after editing.
Mulai ulang VS Code setelah mengedit.
---
### Kiro CLI (Amazon)
```bash
# Login to your AWS/Kiro account:
# Login ke akun AWS/Kiro Anda:
kiro-cli login
# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
# Use kiro-cli alongside OmniRoute for other tools.
# CLI ini menggunakan autentikasinya sendiri — OmniRoute tidak diperlukan sebagai backend untuk Kiro CLI itu sendiri.
# Gunakan kiro-cli bersama OmniRoute untuk alat lainnya.
kiro-cli status
```
@@ -260,9 +260,9 @@ kiro-cli status
### Qwen Code (Alibaba)
Qwen Code supports OpenAI-compatible API endpoints via environment variables or `settings.json`.
Qwen Code mendukung endpoint API yang kompatibel dengan OpenAI melalui variabel lingkungan atau `settings.json`.
**Option 1: Environment variables (`~/.qwen/.env`)**
**Opsi 1: Variabel lingkungan (`~/.qwen/.env`)**
```bash
mkdir -p ~/.qwen && cat > ~/.qwen/.env << EOF
@@ -272,7 +272,7 @@ OPENAI_MODEL="auto"
EOF
```
**Option 2: `settings.json` with model providers**
**Opsi 2: `settings.json` dengan penyedia model**
```json
// ~/.qwen/settings.json
@@ -294,7 +294,7 @@ EOF
}
```
**Option 3: Inline CLI flags**
**Opsi 3: Flag CLI langsung**
```bash
OPENAI_BASE_URL="http://localhost:20128/v1" \
@@ -303,76 +303,76 @@ OPENAI_MODEL="auto" \
qwen
```
> For a **remote server** replace `localhost:20128` with the server IP or domain.
> Untuk **server jarak jauh**, ganti `localhost:20128` dengan IP atau domain server.
**Test:** `qwen "say hello"`
**Uji:** `qwen "say hello"`
### Cursor (Desktop App)
### Cursor (Aplikasi Desktop)
> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
> **Catatan:** Cursor merutekan permintaan melalui cloudnya sendiri. Untuk integrasi OmniRoute,
> aktifkan **Cloud Endpoint** di Pengaturan OmniRoute dan gunakan URL domain publik Anda.
Via GUI: **Settings → Models → OpenAI API Key**
Melalui GUI: **Settings → Models → OpenAI API Key**
- Base URL: `https://your-domain.com/v1`
- API Key: your OmniRoute key
- API Key: kunci OmniRoute Anda
---
## Dashboard Auto-Configuration
## Konfigurasi Otomatis Dashboard
The OmniRoute dashboard automates configuration for most tools:
Dashboard OmniRoute mengotomatiskan konfigurasi untuk sebagian besar alat:
1. Go to `http://localhost:20128/dashboard/cli-tools`
2. Expand any tool card
3. Select your API key from the dropdown
4. Click **Apply Config** (if tool is detected as installed)
5. Or copy the generated config snippet manually
1. Buka `http://localhost:20128/dashboard/cli-tools`
2. Perluas kartu alat mana pun
3. Pilih API key Anda dari menu tarik-turun
4. Klik **Apply Config** (jika alat terdeteksi telah terinstal)
5. Atau salin cuplikan konfigurasi yang dihasilkan secara manual
---
## Built-in Agents: Droid & OpenClaw
## Agen Bawaan: Droid & OpenClaw
**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
They run as internal routes and use OmniRoute's model routing automatically.
**Droid** dan **OpenClaw** adalah agen AI yang dibangun langsung ke dalam OmniRoute — tidak perlu instalasi.
Keduanya berjalan sebagai rute internal dan menggunakan perutean model OmniRoute secara otomatis.
- Access: `http://localhost:20128/dashboard/agents`
- Configure: same combos and providers as all other tools
- No API key or CLI install required
- Akses: `http://localhost:20128/dashboard/agents`
- Konfigurasi: combo dan penyedia yang sama seperti semua alat lainnya
- Tidak memerlukan API key atau instalasi CLI
---
## Available API Endpoints
## Endpoint API yang Tersedia
| Endpoint | Description | Use For |
| -------------------------- | ----------------------------- | --------------------------- |
| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
| `/v1/embeddings` | Text embeddings | RAG, search |
| `/v1/images/generations` | Image generation | GPT-Image, Flux, etc. |
| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
| Endpoint | Deskripsi | Digunakan Untuk |
| -------------------------- | --------------------------------- | --------------------------- |
| `/v1/chat/completions` | Chat standar (semua penyedia) | Semua alat modern |
| `/v1/responses` | Responses API (format OpenAI) | Codex, alur kerja agentik |
| `/v1/completions` | Penyelesaian teks lama | Alat lama yang menggunakan `prompt:` |
| `/v1/embeddings` | Embedding teks | RAG, pencarian |
| `/v1/images/generations` | Pembuatan gambar | GPT-Image, Flux, dll. |
| `/v1/audio/speech` | Teks ke ucapan | ElevenLabs, OpenAI TTS |
| `/v1/audio/transcriptions` | Ucapan ke teks | Deepgram, AssemblyAI |
---
## Pemecahan Masalah
| Error | Cause | Fix |
| ------------------------- | ----------------------- | ------------------------------------------ |
| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
| CLI shows "not installed" | Binary not in PATH | Check `which <command>` |
| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
| Error | Penyebab | Solusi |
| ------------------------- | --------------------------------- | ------------------------------------------ |
| `Connection refused` | OmniRoute tidak berjalan | `pm2 start omniroute` |
| `401 Unauthorized` | API key salah | Periksa di `/dashboard/api-manager` |
| `No combo configured` | Tidak ada combo perutean aktif | Atur di `/dashboard/combos` |
| `invalid model` | Model tidak ada dalam katalog | Gunakan `auto` atau periksa `/dashboard/providers` |
| CLI menampilkan "not installed" | Biner tidak ada di PATH | Periksa `which <command>` |
| `kiro-cli: not found` | Tidak ada di PATH | `export PATH="$HOME/.local/bin:$PATH"` |
---
## Quick Setup Script (One Command)
## Skrip Pengaturan Cepat (Satu Perintah)
```bash
# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
# Instal semua CLI dan konfigurasi untuk OmniRoute (ganti dengan kunci dan URL server Anda)
OMNIROUTE_URL="http://localhost:20128/v1"
OMNIROUTE_KEY="sk-your-omniroute-key"
@@ -381,7 +381,7 @@ npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocod
# Kiro CLI
apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
# Write configs
# Tulis konfigurasi
mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"

View File

@@ -1,55 +1,55 @@
# Environment Variables Reference (Bahasa Indonesia)
# Referensi Variabel Lingkungan (Bahasa Indonesia)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/ENVIRONMENT.md) · 🇸🇦 [ar](../../ar/docs/ENVIRONMENT.md) · 🇧🇬 [bg](../../bg/docs/ENVIRONMENT.md) · 🇧🇩 [bn](../../bn/docs/ENVIRONMENT.md) · 🇨🇿 [cs](../../cs/docs/ENVIRONMENT.md) · 🇩🇰 [da](../../da/docs/ENVIRONMENT.md) · 🇩🇪 [de](../../de/docs/ENVIRONMENT.md) · 🇪🇸 [es](../../es/docs/ENVIRONMENT.md) · 🇮🇷 [fa](../../fa/docs/ENVIRONMENT.md) · 🇫🇮 [fi](../../fi/docs/ENVIRONMENT.md) · 🇫🇷 [fr](../../fr/docs/ENVIRONMENT.md) · 🇮🇳 [gu](../../gu/docs/ENVIRONMENT.md) · 🇮🇱 [he](../../he/docs/ENVIRONMENT.md) · 🇮🇳 [hi](../../hi/docs/ENVIRONMENT.md) · 🇭🇺 [hu](../../hu/docs/ENVIRONMENT.md) · 🇮🇩 [id](../../id/docs/ENVIRONMENT.md) · 🇮🇹 [it](../../it/docs/ENVIRONMENT.md) · 🇯🇵 [ja](../../ja/docs/ENVIRONMENT.md) · 🇰🇷 [ko](../../ko/docs/ENVIRONMENT.md) · 🇮🇳 [mr](../../mr/docs/ENVIRONMENT.md) · 🇲🇾 [ms](../../ms/docs/ENVIRONMENT.md) · 🇳🇱 [nl](../../nl/docs/ENVIRONMENT.md) · 🇳🇴 [no](../../no/docs/ENVIRONMENT.md) · 🇵🇭 [phi](../../phi/docs/ENVIRONMENT.md) · 🇵🇱 [pl](../../pl/docs/ENVIRONMENT.md) · 🇵🇹 [pt](../../pt/docs/ENVIRONMENT.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ENVIRONMENT.md) · 🇷🇴 [ro](../../ro/docs/ENVIRONMENT.md) · 🇷🇺 [ru](../../ru/docs/ENVIRONMENT.md) · 🇸🇰 [sk](../../sk/docs/ENVIRONMENT.md) · 🇸🇪 [sv](../../sv/docs/ENVIRONMENT.md) · 🇰🇪 [sw](../../sw/docs/ENVIRONMENT.md) · 🇮🇳 [ta](../../ta/docs/ENVIRONMENT.md) · 🇮🇳 [te](../../te/docs/ENVIRONMENT.md) · 🇹🇭 [th](../../th/docs/ENVIRONMENT.md) · 🇹🇷 [tr](../../tr/docs/ENVIRONMENT.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ENVIRONMENT.md) · 🇵🇰 [ur](../../ur/docs/ENVIRONMENT.md) · 🇻🇳 [vi](../../vi/docs/ENVIRONMENT.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ENVIRONMENT.md)
---
> Complete reference for every environment variable recognized by OmniRoute.
> For a quick-start template, see [`.env.example`](../.env.example).
> Referensi lengkap untuk setiap variabel lingkungan yang dikenali oleh OmniRoute.
> Untuk template pengaturan cepat, lihat [`.env.example`](../.env.example).
---
## Table of Contents
## Daftar Isi
- [1. Required Secrets](#1-required-secrets)
- [2. Storage & Database](#2-storage--database)
- [3. Network & Ports](#3-network--ports)
- [4. Security & Authentication](#4-security--authentication)
- [5. Input Sanitization & PII Protection](#5-input-sanitization--pii-protection)
- [6. Tool & Routing Policies](#6-tool--routing-policies)
- [7. URLs & Cloud Sync](#7-urls--cloud-sync)
- [8. Outbound Proxy](#8-outbound-proxy)
- [9. CLI Tool Integration](#9-cli-tool-integration)
- [10. Internal Agent & MCP Integrations](#10-internal-agent--mcp-integrations)
- [11. OAuth Provider Credentials](#11-oauth-provider-credentials)
- [12. Provider User-Agent Overrides](#12-provider-user-agent-overrides)
- [13. CLI Fingerprint Compatibility](#13-cli-fingerprint-compatibility)
- [14. API Key Providers](#14-api-key-providers)
- [15. Timeout Settings](#15-timeout-settings)
- [1. Rahasia yang Wajib Ada](#1-required-secrets)
- [2. Penyimpanan & Database](#2-storage--database)
- [3. Jaringan & Port](#3-network--ports)
- [4. Keamanan & Autentikasi](#4-security--authentication)
- [5. Sanitasi Input & Perlindungan PII](#5-input-sanitization--pii-protection)
- [6. Kebijakan Alat & Routing](#6-tool--routing-policies)
- [7. URL & Sinkronisasi Cloud](#7-urls--cloud-sync)
- [8. Proxy Keluar](#8-outbound-proxy)
- [9. Integrasi Alat CLI](#9-cli-tool-integration)
- [10. Agen Internal & Integrasi MCP](#10-internal-agent--mcp-integrations)
- [11. Kredensial Provider OAuth](#11-oauth-provider-credentials)
- [12. Override User-Agent Provider](#12-provider-user-agent-overrides)
- [13. Kompatibilitas Fingerprint CLI](#13-cli-fingerprint-compatibility)
- [14. Provider Kunci API](#14-api-key-providers)
- [15. Pengaturan Batas Waktu](#15-timeout-settings)
- [16. Logging](#16-logging)
- [17. Memory Optimization](#17-memory-optimization)
- [18. Pricing Sync](#18-pricing-sync)
- [19. Model Sync (Dev)](#19-model-sync-dev)
- [20. Provider-Specific Settings](#20-provider-specific-settings)
- [21. Proxy Health](#21-proxy-health)
- [17. Optimasi Memori](#17-memory-optimization)
- [18. Sinkronisasi Harga](#18-pricing-sync)
- [19. Sinkronisasi Model (Dev)](#19-model-sync-dev)
- [20. Pengaturan Spesifik Provider](#20-provider-specific-settings)
- [21. Kesehatan Proxy](#21-proxy-health)
- [22. Debugging](#22-debugging)
- [23. GitHub Integration](#23-github-integration)
- [Deployment Scenarios](#deployment-scenarios)
- [Audit: Removed / Dead Variables](#audit-removed--dead-variables)
- [23. Integrasi GitHub](#23-github-integration)
- [Skenario Deployment](#deployment-scenarios)
- [Audit: Variabel yang Dihapus / Tidak Aktif](#audit-removed--dead-variables)
---
## 1. Required Secrets
## 1. Rahasia yang Wajib Ada
These **must** be set before the first run. Without them, the application will either refuse to start or operate with insecure defaults.
Variabel-variabel ini **harus** diatur sebelum menjalankan aplikasi pertama kali. Tanpa variabel ini, aplikasi akan menolak untuk berjalan atau beroperasi dengan pengaturan default yang tidak aman.
| Variable | Required | Default | Source File | Description |
| ------------------ | -------- | -------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `JWT_SECRET` | **Yes** | _(none)_ | `src/lib/auth` | Signs/verifies all dashboard session cookies (JWT). Generate with `openssl rand -base64 48`. |
| `API_KEY_SECRET` | **Yes** | _(none)_ | `src/lib/db/apiKeys.ts` | AES encryption key for API key values at rest in SQLite. Generate with `openssl rand -hex 32`. |
| `INITIAL_PASSWORD` | **Yes** | `123456` | Bootstrap script | Sets the initial admin dashboard password. **Change before first use.** After login, change via Dashboard → Settings → Security. |
| Variable | Wajib | Default | Source File | Deskripsi |
| ------------------ | -------- | -------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `JWT_SECRET` | **Ya** | _(none)_ | `src/lib/auth` | Menandatangani/memverifikasi semua cookie sesi dashboard (JWT). Buat dengan `openssl rand -base64 48`. |
| `API_KEY_SECRET` | **Ya** | _(none)_ | `src/lib/db/apiKeys.ts` | Kunci enkripsi AES untuk nilai kunci API yang disimpan di SQLite. Buat dengan `openssl rand -hex 32`. |
| `INITIAL_PASSWORD` | **Ya** | `123456` | Bootstrap script | Mengatur kata sandi awal admin dashboard. **Ubah sebelum pertama kali digunakan.** Setelah login, ubah melalui Dashboard → Settings → Security. |
### Generation Commands
### Perintah Pembuatan
```bash
# Generate all three secrets at once:
@@ -59,200 +59,200 @@ echo "INITIAL_PASSWORD=$(openssl rand -base64 16)"
```
> [!CAUTION]
> Never commit `.env` files with real secrets to version control. The `.gitignore` already excludes `.env`, but verify before pushing.
> Jangan pernah melakukan commit file `.env` yang berisi rahasia nyata ke version control. `.gitignore` sudah mengecualikan `.env`, namun verifikasi sebelum melakukan push.
---
## 2. Storage & Database
## 2. Penyimpanan & Database
OmniRoute uses **SQLite** (via `better-sqlite3`) for all persistence. These variables control data location, encryption, and lifecycle.
OmniRoute menggunakan **SQLite** (melalui `better-sqlite3`) untuk semua persistensi data. Variabel-variabel ini mengontrol lokasi data, enkripsi, dan siklus hidup data.
| Variable | Default | Source File | Description |
| -------------------------------- | -------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `DATA_DIR` | `~/.omniroute/` | `src/lib/db/core.ts` | Root directory for SQLite DB, backups, and data files. Override for Docker volumes or custom paths. |
| `STORAGE_ENCRYPTION_KEY` | _(empty = disabled)_ | `src/lib/db/encryption.ts` | AES key for full SQLite database encryption at rest. Generate with `openssl rand -hex 32`. |
| `STORAGE_ENCRYPTION_KEY_VERSION` | `v1` | `scripts/bootstrap-env.mjs`, `electron/main.js` | Version label for the encryption key. Increment when performing key rotation to support decryption of old backups. |
| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | `src/lib/db/backup.ts` | When `true`, skips the automatic database backup that runs before migrations on every startup. |
| `OMNIROUTE_CRYPT_KEY` | _(unset)_ | `src/lib/db/encryption.ts` | **Legacy alias** for `STORAGE_ENCRYPTION_KEY`. Accepted as a fallback when the primary variable is absent. |
| `OMNIROUTE_API_KEY_BASE64` | _(unset)_ | `src/lib/db/encryption.ts` | **Legacy alias** (Base64-encoded form) accepted as a fallback. Decoded automatically before use. |
| Variable | Default | Source File | Deskripsi |
| -------------------------------- | -------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `DATA_DIR` | `~/.omniroute/` | `src/lib/db/core.ts` | Direktori utama untuk DB SQLite, cadangan, dan file data. Override untuk volume Docker atau path khusus. |
| `STORAGE_ENCRYPTION_KEY` | _(empty = disabled)_ | `src/lib/db/encryption.ts` | Kunci AES untuk enkripsi penuh database SQLite saat disimpan. Buat dengan `openssl rand -hex 32`. |
| `STORAGE_ENCRYPTION_KEY_VERSION` | `v1` | `scripts/bootstrap-env.mjs`, `electron/main.js` | Label versi untuk kunci enkripsi. Naikkan nilainya saat melakukan rotasi kunci agar mendukung dekripsi cadangan lama. |
| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | `src/lib/db/backup.ts` | Saat bernilai `true`, melewati pencadangan database otomatis yang berjalan sebelum migrasi pada setiap startup. |
| `OMNIROUTE_CRYPT_KEY` | _(unset)_ | `src/lib/db/encryption.ts` | **Alias legacy** untuk `STORAGE_ENCRYPTION_KEY`. Diterima sebagai fallback ketika variabel utama tidak ada. |
| `OMNIROUTE_API_KEY_BASE64` | _(unset)_ | `src/lib/db/encryption.ts` | **Alias legacy** (bentuk yang dikodekan Base64) diterima sebagai fallback. Didekode secara otomatis sebelum digunakan. |
### Scenarios
### Skenario
| Scenario | Configuration |
| --------------------- | -------------------------------------------------------------------------------- |
| **Local development** | Leave all defaults. DB lives at `~/.omniroute/omniroute.db`. |
| **Docker** | `DATA_DIR=/data` + mount a volume at `/data`. |
| **Encrypted at rest** | Set `STORAGE_ENCRYPTION_KEY` + keep backups of the key! Losing it = losing data. |
| **CI/Testing** | `DATA_DIR=/tmp/omniroute-test`ephemeral, no encryption needed. |
| Skenario | Konfigurasi |
| -------------------------- | ------------------------------------------------------------------------------------------------ |
| **Pengembangan lokal** | Biarkan semua nilai default. DB berada di `~/.omniroute/omniroute.db`. |
| **Docker** | `DATA_DIR=/data` + mount volume di `/data`. |
| **Terenkripsi saat simpan**| Set `STORAGE_ENCRYPTION_KEY` + simpan cadangan kuncinya! Kehilangan kunci = kehilangan data. |
| **CI/Testing** | `DATA_DIR=/tmp/omniroute-test`bersifat sementara, tidak perlu enkripsi. |
---
## 3. Network & Ports
## 3. Jaringan & Port
| Variable | Default | Source File | Description |
| --------------------- | ------------ | -------------------------- | -------------------------------------------------------------------------------------- |
| `PORT` | `20128` | `src/lib/runtime/ports.ts` | Primary port for both Dashboard UI and API endpoints (single-port mode). |
| `API_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | When set, serves the `/v1/*` proxy API on this separate port. |
| `API_HOST` | `0.0.0.0` | `src/lib/runtime/ports.ts` | Bind address for the API port. |
| `DASHBOARD_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | When set, serves the Dashboard UI on this separate port. |
| `PROD_DASHBOARD_PORT` | `20130` | `docker-compose.prod.yml` | Host-side published port for the Dashboard in Docker production mode. |
| `PROD_API_PORT` | `20131` | `docker-compose.prod.yml` | Host-side published port for the API in Docker production mode. |
| `OMNIROUTE_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | Takes precedence over `PORT` when running inside Electron or other wrappers. |
| `NODE_ENV` | `production` | Next.js core | Controls logging verbosity, caching, error detail exposure, and Next.js optimizations. |
| Variable | Default | Source File | Deskripsi |
| --------------------- | ------------ | -------------------------- | ----------------------------------------------------------------------------------------------------- |
| `PORT` | `20128` | `src/lib/runtime/ports.ts` | Port utama untuk Dashboard UI dan endpoint API (mode port tunggal). |
| `API_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | Jika diatur, menyajikan API proxy `/v1/*` pada port terpisah ini. |
| `API_HOST` | `0.0.0.0` | `src/lib/runtime/ports.ts` | Alamat bind untuk port API. |
| `DASHBOARD_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | Jika diatur, menyajikan Dashboard UI pada port terpisah ini. |
| `PROD_DASHBOARD_PORT` | `20130` | `docker-compose.prod.yml` | Port yang dipublikasikan di sisi host untuk Dashboard dalam mode produksi Docker. |
| `PROD_API_PORT` | `20131` | `docker-compose.prod.yml` | Port yang dipublikasikan di sisi host untuk API dalam mode produksi Docker. |
| `OMNIROUTE_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | Mengambil prioritas di atas `PORT` saat berjalan di dalam Electron atau wrapper lainnya. |
| `NODE_ENV` | `production` | Next.js core | Mengontrol verbositas logging, caching, ekspos detail error, dan optimasi Next.js. |
### Port Modes
### Mode Port
```
┌─────────────────────────── Single Port (default) ─────────────────────────┐
┌─────────────────────────── Port Tunggal (default) ─────────────────────────┐
│ PORT=20128 │
│ → Dashboard: http://localhost:20128 │
│ → API: http://localhost:20128/v1/chat/completions │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────── Split Ports ─────────────────────────────────────┐
┌─────────────────────────── Port Terpisah ───────────────────────────────────┐
│ 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 │
Use case: Expose API to LAN while restricting Dashboard to localhost.
Kasus penggunaan: Ekspos API ke LAN sambil membatasi Dashboard ke localhost.│
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────── Docker Production ──────────────────────────────┐
│ PROD_DASHBOARD_PORT=443 PROD_API_PORT=8443 │
│ → Maps container ports to host ports in docker-compose.prod.yml.
│ → Memetakan port kontainer ke port host di docker-compose.prod.yml. │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## 4. Security & Authentication
## 4. Keamanan & Autentikasi
| Variable | Default | Source File | Description |
| ----------------------------- | --------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `MACHINE_ID_SALT` | `endpoint-proxy-salt` | `src/lib/auth` | Salt combined with hardware identifiers for machine fingerprinting. Change per-deployment for isolation. |
| `AUTH_COOKIE_SECURE` | `false` | `src/lib/auth` | Sets the `Secure` flag on session cookies. **Must be `true`** when running behind HTTPS. |
| `REQUIRE_API_KEY` | `false` | API middleware | When `true`, all `/v1/*` proxy requests must include a valid API key. |
| `ALLOW_API_KEY_REVEAL` | `false` | Dashboard providers page | Allows revealing full API key values in the Dashboard UI. Security risk on shared instances. |
| `NO_LOG_API_KEY_IDS` | _(empty)_ | `src/lib/compliance/index.ts` | Comma-separated API key IDs that bypass request logging (GDPR compliance). |
| `MAX_BODY_SIZE_BYTES` | `10485760` (10 MB) | `src/shared/middleware/bodySizeGuard.ts` | Maximum allowed request body size. Rejects payloads exceeding this limit. |
| `CORS_ORIGIN` | `*` | Next.js middleware | CORS `Access-Control-Allow-Origin` value. Restrict for production. |
| `OUTBOUND_SSRF_GUARD_ENABLED` | `true` | `src/shared/network/outboundUrlGuard.ts` | Block provider calls targeting private/loopback/link-local IP ranges. Disable only in isolated test envs. |
| Variable | Default | Source File | Deskripsi |
| ----------------------------- | --------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `MACHINE_ID_SALT` | `endpoint-proxy-salt` | `src/lib/auth` | Salt yang digabungkan dengan pengenal perangkat keras untuk fingerprinting mesin. Ubah per-deployment untuk isolasi. |
| `AUTH_COOKIE_SECURE` | `false` | `src/lib/auth` | Mengatur flag `Secure` pada cookie sesi. **Harus bernilai `true`** saat berjalan di balik HTTPS. |
| `REQUIRE_API_KEY` | `false` | API middleware | Saat bernilai `true`, semua permintaan proxy `/v1/*` harus menyertakan kunci API yang valid. |
| `ALLOW_API_KEY_REVEAL` | `false` | Dashboard providers page | Memungkinkan pengungkapan nilai kunci API penuh di Dashboard UI. Berisiko pada instansi bersama. |
| `NO_LOG_API_KEY_IDS` | _(empty)_ | `src/lib/compliance/index.ts` | ID kunci API yang dipisahkan koma yang melewati pencatatan permintaan (kepatuhan GDPR). |
| `MAX_BODY_SIZE_BYTES` | `10485760` (10 MB) | `src/shared/middleware/bodySizeGuard.ts` | Ukuran body permintaan maksimum yang diizinkan. Menolak payload yang melebihi batas ini. |
| `CORS_ORIGIN` | `*` | Next.js middleware | Nilai CORS `Access-Control-Allow-Origin`. Batasi untuk produksi. |
| `OUTBOUND_SSRF_GUARD_ENABLED` | `true` | `src/shared/network/outboundUrlGuard.ts` | Memblokir panggilan provider yang menarget rentang IP privat/loopback/link-local. Nonaktifkan hanya di lingkungan pengujian terisolasi. |
### Hardening Checklist
### Daftar Periksa Penguatan Keamanan
```bash
# Production security minimum:
AUTH_COOKIE_SECURE=true # Requires HTTPS
REQUIRE_API_KEY=true # Authenticate all proxy calls
ALLOW_API_KEY_REVEAL=false # Never expose keys in UI
# Minimum keamanan produksi:
AUTH_COOKIE_SECURE=true # Memerlukan HTTPS
REQUIRE_API_KEY=true # Autentikasi semua panggilan proxy
ALLOW_API_KEY_REVEAL=false # Jangan pernah ekspos kunci di UI
CORS_ORIGIN=https://your.domain.com
MAX_BODY_SIZE_BYTES=5242880 # 5 MB limit
MAX_BODY_SIZE_BYTES=5242880 # Batas 5 MB
```
---
## 5. Input Sanitization & PII Protection
## 5. Sanitasi Input & Perlindungan PII
OmniRoute provides a two-layer defense: request-side injection scanning and response-side PII stripping.
OmniRoute menyediakan pertahanan dua lapis: pemindaian injeksi di sisi permintaan dan penghapusan PII di sisi respons.
### Request-Side: Prompt Injection Guard
### Sisi Permintaan: Penjaga Injeksi Prompt
| Variable | Default | Source File | Description |
| ------------------------- | --------- | ---------------------------------------- | ------------------------------------------------------------------------------------------- |
| `INPUT_SANITIZER_ENABLED` | `false` | `src/middleware/promptInjectionGuard.ts` | Enable scanning of incoming messages for prompt injection patterns. |
| `INPUT_SANITIZER_MODE` | `warn` | `src/middleware/promptInjectionGuard.ts` | `warn` = log only, `block` = reject request with 400, `redact` = strip suspicious patterns. |
| `INJECTION_GUARD_MODE` | _(unset)_ | `src/middleware/promptInjectionGuard.ts` | Legacy alias for `INPUT_SANITIZER_MODE`same behavior. |
| `PII_REDACTION_ENABLED` | `false` | `src/middleware/promptInjectionGuard.ts` | Detect PII (emails, phones, SSNs) in incoming requests. |
| Variable | Default | Source File | Deskripsi |
| ------------------------- | --------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `INPUT_SANITIZER_ENABLED` | `false` | `src/middleware/promptInjectionGuard.ts` | Aktifkan pemindaian pesan masuk untuk pola injeksi prompt. |
| `INPUT_SANITIZER_MODE` | `warn` | `src/middleware/promptInjectionGuard.ts` | `warn` = hanya log, `block` = tolak permintaan dengan 400, `redact` = hapus pola mencurigakan. |
| `INJECTION_GUARD_MODE` | _(unset)_ | `src/middleware/promptInjectionGuard.ts` | Alias legacy untuk `INPUT_SANITIZER_MODE`perilaku sama. |
| `PII_REDACTION_ENABLED` | `false` | `src/middleware/promptInjectionGuard.ts` | Deteksi PII (email, telepon, SSN) dalam permintaan masuk. |
### Response-Side: PII Sanitizer
### Sisi Respons: Sanitizer PII
| Variable | Default | Source File | Description |
| -------------------------------- | -------- | ------------------------- | ----------------------------------------------------------------------- |
| `PII_RESPONSE_SANITIZATION` | `false` | `src/lib/piiSanitizer.ts` | Scan LLM responses for leaked PII before returning to client. |
| `PII_RESPONSE_SANITIZATION_MODE` | `redact` | `src/lib/piiSanitizer.ts` | `redact` = mask PII, `warn` = log only, `block` = drop entire response. |
| Variable | Default | Source File | Deskripsi |
| -------------------------------- | -------- | ------------------------- | -------------------------------------------------------------------------------------------- |
| `PII_RESPONSE_SANITIZATION` | `false` | `src/lib/piiSanitizer.ts` | Pindai respons LLM untuk PII yang bocor sebelum dikembalikan ke klien. |
| `PII_RESPONSE_SANITIZATION_MODE` | `redact` | `src/lib/piiSanitizer.ts` | `redact` = sembunyikan PII, `warn` = hanya log, `block` = buang seluruh respons. |
### Scenarios
### Skenario
| Scenario | Configuration |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Enterprise compliance** | `INPUT_SANITIZER_ENABLED=true`, `INPUT_SANITIZER_MODE=block`, `PII_REDACTION_ENABLED=true`, `PII_RESPONSE_SANITIZATION=true` |
| **Monitoring only** | `INPUT_SANITIZER_ENABLED=true`, `INPUT_SANITIZER_MODE=warn`logs but never blocks |
| **Personal use** | Leave all disabled — zero overhead |
| Skenario | Konfigurasi |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| **Kepatuhan enterprise** | `INPUT_SANITIZER_ENABLED=true`, `INPUT_SANITIZER_MODE=block`, `PII_REDACTION_ENABLED=true`, `PII_RESPONSE_SANITIZATION=true` |
| **Hanya pemantauan** | `INPUT_SANITIZER_ENABLED=true`, `INPUT_SANITIZER_MODE=warn`mencatat log namun tidak pernah memblokir |
| **Penggunaan pribadi** | Biarkan semua dinonaktifkan — tanpa overhead |
---
## 6. Tool & Routing Policies
## 6. Kebijakan Alat & Routing
| Variable | Default | Source File | Description |
| ------------------ | ---------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `TOOL_POLICY_MODE` | `disabled` | `src/lib/toolPolicy.ts` | Controls LLM tool/function-calling access. `allowlist` = only listed tools, `denylist` = all except listed, `disabled` = no restrictions. |
| Variable | Default | Source File | Deskripsi |
| ------------------ | ---------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `TOOL_POLICY_MODE` | `disabled` | `src/lib/toolPolicy.ts` | Mengontrol akses pemanggilan alat/fungsi LLM. `allowlist` = hanya alat yang terdaftar, `denylist` = semua kecuali yang terdaftar, `disabled` = tanpa batasan. |
---
## 7. URLs & Cloud Sync
## 7. URL & Sinkronisasi Cloud
| Variable | Default | Source File | Description |
| ----------------------- | ------------------------ | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `BASE_URL` | `http://localhost:20128` | `src/lib/cloudSync.ts` | Server-side URL for internal sync jobs to call `/api/sync/cloud`. |
| `CLOUD_URL` | _(empty)_ | `src/lib/cloudSync.ts` | Cloud relay endpoint URL (premium feature). |
| `CLOUD_SYNC_TIMEOUT_MS` | `12000` | `src/lib/cloudSync.ts` | HTTP timeout for cloud sync requests. |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | OAuth, Dashboard, sync | Public-facing URL for OAuth redirect_uri, Dashboard links. **Must match your public URL behind reverse proxy.** |
| `NEXT_PUBLIC_CLOUD_URL` | _(empty)_ | Client-side | Client-side mirror of `CLOUD_URL`. |
| `NEXT_PUBLIC_APP_URL` | _(unset)_ | `src/shared/services/cloudSyncScheduler.ts` | Legacy fallback for `NEXT_PUBLIC_BASE_URL`. |
| Variable | Default | Source File | Deskripsi |
| ----------------------- | ------------------------ | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `BASE_URL` | `http://localhost:20128` | `src/lib/cloudSync.ts` | URL sisi server untuk pekerjaan sinkronisasi internal memanggil `/api/sync/cloud`. |
| `CLOUD_URL` | _(empty)_ | `src/lib/cloudSync.ts` | URL endpoint relay cloud (fitur premium). |
| `CLOUD_SYNC_TIMEOUT_MS` | `12000` | `src/lib/cloudSync.ts` | Batas waktu HTTP untuk permintaan sinkronisasi cloud. |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | OAuth, Dashboard, sync | URL publik untuk redirect_uri OAuth, tautan Dashboard. **Harus cocok dengan URL publik Anda di balik reverse proxy.** |
| `NEXT_PUBLIC_CLOUD_URL` | _(empty)_ | Client-side | Cerminan sisi klien dari `CLOUD_URL`. |
| `NEXT_PUBLIC_APP_URL` | _(unset)_ | `src/shared/services/cloudSyncScheduler.ts` | Fallback legacy untuk `NEXT_PUBLIC_BASE_URL`. |
> [!IMPORTANT]
> When deploying behind a reverse proxy (nginx, Caddy), `NEXT_PUBLIC_BASE_URL` **must** be set to your public URL (e.g., `https://omniroute.example.com`). Without this, OAuth callbacks will fail because the redirect_uri won't match.
> Saat melakukan deployment di balik reverse proxy (nginx, Caddy), `NEXT_PUBLIC_BASE_URL` **harus** diatur ke URL publik Anda (misalnya, `https://omniroute.example.com`). Tanpa ini, callback OAuth akan gagal karena redirect_uri tidak akan cocok.
---
## 8. Outbound Proxy
## 8. Proxy Keluar
Route upstream LLM provider calls through an HTTP or SOCKS5 proxy for egress control, geo-routing, or IP masking.
Arahkan panggilan provider LLM upstream melalui proxy HTTP atau SOCKS5 untuk kontrol egress, geo-routing, atau penyembunyian IP.
| Variable | Default | Source File | Description |
| --------------------------------- | --------- | -------------------- | ----------------------------------------------------------------------------------- |
| `ENABLE_SOCKS5_PROXY` | `true` | `open-sse/executors` | Enable SOCKS5 proxy agent for upstream calls. |
| `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` | `true` | Client-side | Client-side awareness of SOCKS5 availability. |
| `HTTP_PROXY` | _(unset)_ | Node.js standard | HTTP proxy for upstream calls. |
| `HTTPS_PROXY` | _(unset)_ | Node.js standard | HTTPS proxy for upstream calls. |
| `ALL_PROXY` | _(unset)_ | Node.js standard | Universal proxy (supports `socks5://`). |
| `NO_PROXY` | _(unset)_ | Node.js standard | Comma-separated hostnames/IPs to bypass the proxy. |
| `ENABLE_TLS_FINGERPRINT` | `false` | `open-sse/executors` | Spoof TLS fingerprint using wreq-js (mimics Chrome 124). Counters JA3/JA4 blocking. |
| Variable | Default | Source File | Deskripsi |
| --------------------------------- | --------- | -------------------- | ---------------------------------------------------------------------------------------------------------- |
| `ENABLE_SOCKS5_PROXY` | `true` | `open-sse/executors` | Aktifkan agen proxy SOCKS5 untuk panggilan upstream. |
| `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` | `true` | Client-side | Kesadaran sisi klien tentang ketersediaan SOCKS5. |
| `HTTP_PROXY` | _(unset)_ | Node.js standard | Proxy HTTP untuk panggilan upstream. |
| `HTTPS_PROXY` | _(unset)_ | Node.js standard | Proxy HTTPS untuk panggilan upstream. |
| `ALL_PROXY` | _(unset)_ | Node.js standard | Proxy universal (mendukung `socks5://`). |
| `NO_PROXY` | _(unset)_ | Node.js standard | Nama host/IP yang dipisahkan koma untuk melewati proxy. |
| `ENABLE_TLS_FINGERPRINT` | `false` | `open-sse/executors` | Memalsukan fingerprint TLS menggunakan wreq-js (meniru Chrome 124). Mengatasi pemblokiran JA3/JA4. |
### Scenarios
### Skenario
| Scenario | Configuration |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| **SOCKS5 through SSH tunnel** | `ALL_PROXY=socks5://127.0.0.1:7890`, `ENABLE_SOCKS5_PROXY=true` |
| **Corporate HTTP proxy** | `HTTP_PROXY=http://proxy.corp.com:3128`, `HTTPS_PROXY=http://proxy.corp.com:3128`, `NO_PROXY=localhost,internal.corp.com` |
| **Anti-fingerprint** | `ENABLE_TLS_FINGERPRINT=true`requires `wreq-js` (included) |
| Skenario | Konfigurasi |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| **SOCKS5 melalui tunnel SSH** | `ALL_PROXY=socks5://127.0.0.1:7890`, `ENABLE_SOCKS5_PROXY=true` |
| **Proxy HTTP korporat** | `HTTP_PROXY=http://proxy.corp.com:3128`, `HTTPS_PROXY=http://proxy.corp.com:3128`, `NO_PROXY=localhost,internal.corp.com` |
| **Anti-fingerprint** | `ENABLE_TLS_FINGERPRINT=true`memerlukan `wreq-js` (sudah disertakan) |
---
## 9. CLI Tool Integration
## 9. Integrasi Alat CLI
Controls how OmniRoute discovers and launches CLI sidecars (Claude Code, Codex, etc.).
Mengontrol bagaimana OmniRoute menemukan dan menjalankan sidecar CLI (Claude Code, Codex, dll.).
| Variable | Default | Source File | Description |
| ------------------------- | ---------- | ----------------------------------- | -------------------------------------------------------------------------- |
| `CLI_MODE` | `auto` | `src/shared/services/cliRuntime.ts` | `auto` = search system PATH; `manual` = use explicit paths only. |
| `CLI_EXTRA_PATHS` | _(unset)_ | `src/shared/services/cliRuntime.ts` | Additional PATH entries for CLI binary discovery (colon-separated). |
| `CLI_CONFIG_HOME` | _(unset)_ | `src/shared/services/cliRuntime.ts` | Override home directory for reading CLI configs (`~/.claude`, `~/.codex`). |
| `CLI_ALLOW_CONFIG_WRITES` | `false` | `src/shared/services/cliRuntime.ts` | Allow OmniRoute to write CLI config files (token refresh, session data). |
| `CLI_CLAUDE_BIN` | `claude` | `src/shared/services/cliRuntime.ts` | Custom path to Claude CLI binary. |
| `CLI_CODEX_BIN` | `codex` | `src/shared/services/cliRuntime.ts` | Custom path to Codex CLI binary. |
| `CLI_DROID_BIN` | `droid` | `src/shared/services/cliRuntime.ts` | Custom path to Droid CLI binary. |
| `CLI_OPENCLAW_BIN` | `openclaw` | `src/shared/services/cliRuntime.ts` | Custom path to OpenClaw CLI binary. |
| `CLI_CURSOR_BIN` | `agent` | `src/shared/services/cliRuntime.ts` | Custom path to Cursor agent binary. |
| `CLI_CLINE_BIN` | `cline` | `src/shared/services/cliRuntime.ts` | Custom path to Cline CLI binary. |
| `CLI_CONTINUE_BIN` | `cn` | `src/shared/services/cliRuntime.ts` | Custom path to Continue CLI binary. |
| `CLI_QODER_BIN` | `qoder` | `src/shared/services/cliRuntime.ts` | Custom path to Qoder CLI binary. |
| Variable | Default | Source File | Deskripsi |
| ------------------------- | ---------- | ----------------------------------- | ------------------------------------------------------------------------------------------------ |
| `CLI_MODE` | `auto` | `src/shared/services/cliRuntime.ts` | `auto` = cari di PATH sistem; `manual` = gunakan hanya path eksplisit. |
| `CLI_EXTRA_PATHS` | _(unset)_ | `src/shared/services/cliRuntime.ts` | Entri PATH tambahan untuk penemuan biner CLI (dipisahkan titik dua). |
| `CLI_CONFIG_HOME` | _(unset)_ | `src/shared/services/cliRuntime.ts` | Override direktori home untuk membaca konfigurasi CLI (`~/.claude`, `~/.codex`). |
| `CLI_ALLOW_CONFIG_WRITES` | `false` | `src/shared/services/cliRuntime.ts` | Izinkan OmniRoute menulis file konfigurasi CLI (penyegaran token, data sesi). |
| `CLI_CLAUDE_BIN` | `claude` | `src/shared/services/cliRuntime.ts` | Path kustom ke biner CLI Claude. |
| `CLI_CODEX_BIN` | `codex` | `src/shared/services/cliRuntime.ts` | Path kustom ke biner CLI Codex. |
| `CLI_DROID_BIN` | `droid` | `src/shared/services/cliRuntime.ts` | Path kustom ke biner CLI Droid. |
| `CLI_OPENCLAW_BIN` | `openclaw` | `src/shared/services/cliRuntime.ts` | Path kustom ke biner CLI OpenClaw. |
| `CLI_CURSOR_BIN` | `agent` | `src/shared/services/cliRuntime.ts` | Path kustom ke biner agen Cursor. |
| `CLI_CLINE_BIN` | `cline` | `src/shared/services/cliRuntime.ts` | Path kustom ke biner CLI Cline. |
| `CLI_CONTINUE_BIN` | `cn` | `src/shared/services/cliRuntime.ts` | Path kustom ke biner CLI Continue. |
| `CLI_QODER_BIN` | `qoder` | `src/shared/services/cliRuntime.ts` | Path kustom ke biner CLI Qoder. |
### Docker Example
### Contoh Docker
```bash
# Mount host binaries into the container and tell OmniRoute where they are:
# Mount biner host ke kontainer dan beri tahu OmniRoute lokasinya:
CLI_EXTRA_PATHS=/host-cli/bin
CLI_CONFIG_HOME=/root
CLI_ALLOW_CONFIG_WRITES=true
@@ -261,139 +261,139 @@ CLI_CLAUDE_BIN=/host-cli/bin/claude
---
## 10. Internal Agent & MCP Integrations
## 10. Agen Internal & Integrasi MCP
| Variable | Default | Source File | Description |
| --------------------------------------- | ----------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_BASE_URL` | auto-detect | `open-sse/mcp-server/server.ts` | Explicit URL for MCP/A2A tools to reach OmniRoute. Overrides localhost auto-detection. |
| `OMNIROUTE_API_KEY` | _(unset)_ | MCP/A2A modules | API key for internal MCP tool and A2A skill calls. |
| `OMNIROUTE_API_KEY_ID` | _(unset)_ | `open-sse/mcp-server/audit.ts` | Key ID for MCP audit log attribution. |
| `ROUTER_API_KEY` | _(unset)_ | Legacy | Legacy alias for `OMNIROUTE_API_KEY`. |
| `OMNIROUTE_MCP_ENFORCE_SCOPES` | `false` | `open-sse/mcp-server/server.ts` | Enforce scope-based access control on MCP tool calls. |
| `OMNIROUTE_MCP_SCOPES` | _(all)_ | `open-sse/mcp-server/server.ts` | Comma-separated scopes: `admin`, `combos`, `health`, `models`, `routing`, `budget`, `metrics`, `pricing`, `memory`, `skills`. |
| `MODEL_SYNC_INTERVAL_HOURS` | `24` | `src/shared/services/modelSyncScheduler.ts` | Model catalog sync interval in hours. |
| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | `src/server-init.ts` | Provider rate-limit and quota polling interval. |
| `OMNIROUTE_DISABLE_BACKGROUND_SERVICES` | `false` | `src/instrumentation-node.ts` | Disable all background services (sync, pricing, model refresh). Useful for CI/test. |
| `OMNIROUTE_BOOTSTRAPPED` | `false` | `src/app/(dashboard)/dashboard/page.tsx` | Set `true` by bootstrap script after initial setup. Controls setup wizard visibility. |
| `OMNIROUTE_ALLOW_BODY_PROJECT_OVERRIDE` | `0` | `open-sse/executors/antigravity.ts` | Escape hatch: allow request body to override the Antigravity project field. |
| Variable | Default | Source File | Deskripsi |
| --------------------------------------- | ---------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_BASE_URL` | deteksi otomatis | `open-sse/mcp-server/server.ts` | URL eksplisit agar alat MCP/A2A dapat menjangkau OmniRoute. Menimpa deteksi otomatis localhost. |
| `OMNIROUTE_API_KEY` | _(unset)_ | MCP/A2A modules | Kunci API untuk panggilan alat MCP internal dan skill A2A. |
| `OMNIROUTE_API_KEY_ID` | _(unset)_ | `open-sse/mcp-server/audit.ts` | ID kunci untuk atribusi log audit MCP. |
| `ROUTER_API_KEY` | _(unset)_ | Legacy | Alias legacy untuk `OMNIROUTE_API_KEY`. |
| `OMNIROUTE_MCP_ENFORCE_SCOPES` | `false` | `open-sse/mcp-server/server.ts` | Terapkan kontrol akses berbasis scope pada panggilan alat MCP. |
| `OMNIROUTE_MCP_SCOPES` | _(all)_ | `open-sse/mcp-server/server.ts` | Scope yang dipisahkan koma: `admin`, `combos`, `health`, `models`, `routing`, `budget`, `metrics`, `pricing`, `memory`, `skills`. |
| `MODEL_SYNC_INTERVAL_HOURS` | `24` | `src/shared/services/modelSyncScheduler.ts` | Interval sinkronisasi katalog model dalam jam. |
| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | `src/server-init.ts` | Interval polling batas rate dan kuota provider. |
| `OMNIROUTE_DISABLE_BACKGROUND_SERVICES` | `false` | `src/instrumentation-node.ts` | Nonaktifkan semua layanan latar belakang (sinkronisasi, harga, pembaruan model). Berguna untuk CI/pengujian. |
| `OMNIROUTE_BOOTSTRAPPED` | `false` | `src/app/(dashboard)/dashboard/page.tsx` | Diatur ke `true` oleh skrip bootstrap setelah pengaturan awal. Mengontrol visibilitas wizard pengaturan. |
| `OMNIROUTE_ALLOW_BODY_PROJECT_OVERRIDE` | `0` | `open-sse/executors/antigravity.ts` | Escape hatch: izinkan body permintaan untuk menimpa field proyek Antigravity. |
### OAuth CLI Bridge (Internal)
### Jembatan CLI OAuth (Internal)
| Variable | Default | Source File | Description |
| ------------------- | ----------- | ------------------------------- | ----------------------------------------- |
| `OMNIROUTE_SERVER` | auto-detect | `src/lib/oauth/config/index.ts` | Server URL for CLI↔OmniRoute auth bridge. |
| `OMNIROUTE_TOKEN` | _(unset)_ | `src/lib/oauth/config/index.ts` | Auth token for CLI bridge. |
| `OMNIROUTE_USER_ID` | `cli` | `src/lib/oauth/config/index.ts` | User ID for CLI bridge sessions. |
| `SERVER_URL` | _(unset)_ | `src/lib/oauth/config/index.ts` | Legacy alias for `OMNIROUTE_SERVER`. |
| `CLI_TOKEN` | _(unset)_ | `src/lib/oauth/config/index.ts` | Legacy alias for `OMNIROUTE_TOKEN`. |
| `CLI_USER_ID` | _(unset)_ | `src/lib/oauth/config/index.ts` | Legacy alias for `OMNIROUTE_USER_ID`. |
| Variable | Default | Source File | Deskripsi |
| ------------------- | ---------------- | ------------------------------- | ------------------------------------------------ |
| `OMNIROUTE_SERVER` | deteksi otomatis | `src/lib/oauth/config/index.ts` | URL server untuk jembatan autentikasi CLI↔OmniRoute. |
| `OMNIROUTE_TOKEN` | _(unset)_ | `src/lib/oauth/config/index.ts` | Token autentikasi untuk jembatan CLI. |
| `OMNIROUTE_USER_ID` | `cli` | `src/lib/oauth/config/index.ts` | ID pengguna untuk sesi jembatan CLI. |
| `SERVER_URL` | _(unset)_ | `src/lib/oauth/config/index.ts` | Alias legacy untuk `OMNIROUTE_SERVER`. |
| `CLI_TOKEN` | _(unset)_ | `src/lib/oauth/config/index.ts` | Alias legacy untuk `OMNIROUTE_TOKEN`. |
| `CLI_USER_ID` | _(unset)_ | `src/lib/oauth/config/index.ts` | Alias legacy untuk `OMNIROUTE_USER_ID`. |
---
## 11. OAuth Provider Credentials
## 11. Kredensial Provider OAuth
Built-in credentials for **localhost development**. For remote deployments, register your own at each provider's developer console.
Kredensial bawaan untuk **pengembangan localhost**. Untuk deployment jarak jauh, daftarkan milik Anda sendiri di konsol pengembang masing-masing provider.
| Variable | Provider | Notes |
| --------------------------------- | ----------------------- | --------------------------------------------------------------------------------- |
| `CLAUDE_OAUTH_CLIENT_ID` | Claude Code (Anthropic) | Public client — no secret needed. |
| `CLAUDE_CODE_REDIRECT_URI` | Claude Code | Override redirect URI. Default: `https://platform.claude.com/oauth/code/callback` |
| `CODEX_OAUTH_CLIENT_ID` | Codex / OpenAI | Public client. |
| `GEMINI_OAUTH_CLIENT_ID` | Gemini (Google) | Requires matching `_SECRET`. |
| `GEMINI_OAUTH_CLIENT_SECRET` | Gemini (Google) | — |
| `GEMINI_CLI_OAUTH_CLIENT_ID` | Gemini CLI | Usually same as Gemini. |
| `GEMINI_CLI_OAUTH_CLIENT_SECRET` | Gemini CLI | — |
| `QWEN_OAUTH_CLIENT_ID` | Qwen (Alibaba) | Public client. |
| `KIMI_CODING_OAUTH_CLIENT_ID` | Kimi Coding (Moonshot) | Public client. |
| `ANTIGRAVITY_OAUTH_CLIENT_ID` | Antigravity (Google) | Requires matching `_SECRET`. |
| `ANTIGRAVITY_OAUTH_CLIENT_SECRET` | Antigravity (Google) | — |
| `GITHUB_OAUTH_CLIENT_ID` | GitHub Copilot | Public client. |
| `QODER_OAUTH_CLIENT_SECRET` | Qoder | — |
| `QODER_OAUTH_AUTHORIZE_URL` | Qoder | Set to enable Qoder OAuth. |
| `QODER_OAUTH_TOKEN_URL` | Qoder | — |
| `QODER_OAUTH_USERINFO_URL` | Qoder | — |
| `QODER_OAUTH_CLIENT_ID` | Qoder | — |
| `QODER_PERSONAL_ACCESS_TOKEN` | Qoder | Direct API key fallback (bypasses OAuth). |
| `QODER_CLI_WORKSPACE` | Qoder | Workspace ID for Qoder CLI. |
| `OMNIROUTE_QODER_WORKSPACE` | Qoder | Alias for `QODER_CLI_WORKSPACE`. |
| Variable | Provider | Catatan |
| --------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------- |
| `CLAUDE_OAUTH_CLIENT_ID` | Claude Code (Anthropic) | Klien publik — tidak perlu secret. |
| `CLAUDE_CODE_REDIRECT_URI` | Claude Code | Timpa redirect URI. Default: `https://platform.claude.com/oauth/code/callback` |
| `CODEX_OAUTH_CLIENT_ID` | Codex / OpenAI | Klien publik. |
| `GEMINI_OAUTH_CLIENT_ID` | Gemini (Google) | Memerlukan `_SECRET` yang sesuai. |
| `GEMINI_OAUTH_CLIENT_SECRET` | Gemini (Google) | — |
| `GEMINI_CLI_OAUTH_CLIENT_ID` | Gemini CLI | Biasanya sama dengan Gemini. |
| `GEMINI_CLI_OAUTH_CLIENT_SECRET` | Gemini CLI | — |
| `QWEN_OAUTH_CLIENT_ID` | Qwen (Alibaba) | Klien publik. |
| `KIMI_CODING_OAUTH_CLIENT_ID` | Kimi Coding (Moonshot) | Klien publik. |
| `ANTIGRAVITY_OAUTH_CLIENT_ID` | Antigravity (Google) | Memerlukan `_SECRET` yang sesuai. |
| `ANTIGRAVITY_OAUTH_CLIENT_SECRET` | Antigravity (Google) | — |
| `GITHUB_OAUTH_CLIENT_ID` | GitHub Copilot | Klien publik. |
| `QODER_OAUTH_CLIENT_SECRET` | Qoder | — |
| `QODER_OAUTH_AUTHORIZE_URL` | Qoder | Atur untuk mengaktifkan OAuth Qoder. |
| `QODER_OAUTH_TOKEN_URL` | Qoder | — |
| `QODER_OAUTH_USERINFO_URL` | Qoder | — |
| `QODER_OAUTH_CLIENT_ID` | Qoder | — |
| `QODER_PERSONAL_ACCESS_TOKEN` | Qoder | Fallback kunci API langsung (melewati OAuth). |
| `QODER_CLI_WORKSPACE` | Qoder | ID workspace untuk CLI Qoder. |
| `OMNIROUTE_QODER_WORKSPACE` | Qoder | Alias untuk `QODER_CLI_WORKSPACE`. |
> [!WARNING]
> **Google OAuth** (Antigravity, Gemini CLI) credentials **only work on localhost**. For remote servers:
> Kredensial **Google OAuth** (Antigravity, Gemini CLI) **hanya berfungsi di localhost**. Untuk server jarak jauh:
>
> 1. Go to [Google Cloud Console → Credentials](https://console.cloud.google.com/apis/credentials)
> 2. Create an OAuth 2.0 Client ID (type: "Web application")
> 3. Add your server URL as Authorized redirect URI
> 4. Replace the credential values in `.env`.
> 1. Buka [Google Cloud Console → Credentials](https://console.cloud.google.com/apis/credentials)
> 2. Buat OAuth 2.0 Client ID (tipe: "Web application")
> 3. Tambahkan URL server Anda sebagai Authorized redirect URI
> 4. Ganti nilai kredensial di `.env`.
---
## 12. Provider User-Agent Overrides
## 12. Override User-Agent Provider
Override the `User-Agent` header sent to each upstream provider. This is dynamically resolved at runtime by the executor base class:
Menimpa header `User-Agent` yang dikirim ke setiap provider upstream. Ini diselesaikan secara dinamis saat runtime oleh kelas dasar executor:
```
process.env[`${PROVIDER_ID}_USER_AGENT`]
```
> **Source:** `open-sse/executors/base.ts` → `buildHeaders()`
> **Sumber:** `open-sse/executors/base.ts` → `buildHeaders()`
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |
| `ANTIGRAVITY_USER_AGENT` | `antigravity/2.0.1 darwin/arm64` | When Antigravity IDE updates |
| `KIRO_USER_AGENT` | `AWS-SDK-JS/3.0.0 kiro-ide/1.0.0` | When Kiro IDE updates |
| `QODER_USER_AGENT` | `Qoder-Cli` | When Qoder CLI updates |
| `QWEN_USER_AGENT` | `QwenCode/0.15.11 (linux; x64)` | When Qwen Code updates |
| `CURSOR_USER_AGENT` | `connect-es/1.6.1` | When Cursor updates |
| `GEMINI_CLI_USER_AGENT` | `google-api-nodejs-client/10.3.0` | When Google API client updates |
| Variable | Nilai Default | Kapan Diperbarui |
| ------------------------ | --------------------------------------------- | ---------------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.145 (external, cli)` | Saat Anthropic merilis versi CLI baru |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | Saat OpenAI memperbarui CLI Codex |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override versi klien Codex secara independen dari string UA penuh |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | Saat GitHub Copilot Chat diperbarui |
| `ANTIGRAVITY_USER_AGENT` | `antigravity/2.0.1 darwin/arm64` | Saat Antigravity IDE diperbarui |
| `KIRO_USER_AGENT` | `AWS-SDK-JS/3.0.0 kiro-ide/1.0.0` | Saat Kiro IDE diperbarui |
| `QODER_USER_AGENT` | `Qoder-Cli` | Saat CLI Qoder diperbarui |
| `QWEN_USER_AGENT` | `QwenCode/0.15.11 (linux; x64)` | Saat Qwen Code diperbarui |
| `CURSOR_USER_AGENT` | `connect-es/1.6.1` | Saat Cursor diperbarui |
| `GEMINI_CLI_USER_AGENT` | `google-api-nodejs-client/10.3.0` | Saat klien API Google diperbarui |
> [!TIP]
> You can add User-Agent overrides for **any** provider using the pattern `{PROVIDER_ID}_USER_AGENT`. The executor dynamically constructs the env var name.
> Anda dapat menambahkan override User-Agent untuk provider **mana pun** menggunakan pola `{PROVIDER_ID}_USER_AGENT`. Executor secara dinamis membangun nama variabel lingkungan.
---
## 13. CLI Fingerprint Compatibility
## 13. Kompatibilitas Fingerprint CLI
When enabled, OmniRoute reorders HTTP headers and JSON body fields to match the exact signature of official CLI tools. This reduces the risk of account flagging while preserving your proxy IP.
Saat diaktifkan, OmniRoute mengatur ulang urutan header HTTP dan field body JSON agar cocok dengan tanda tangan persis dari alat CLI resmi. Hal ini mengurangi risiko pemblokiran akun sambil mempertahankan IP proxy Anda.
**Source:** `open-sse/config/cliFingerprints.ts`, `open-sse/executors/base.ts`
**Sumber:** `open-sse/config/cliFingerprints.ts`, `open-sse/executors/base.ts`
### Per-Provider
| Variable | Effect |
| -------------------------- | --------------------------------------- |
| `CLI_COMPAT_CODEX=1` | Mimics Codex CLI request signature |
| `CLI_COMPAT_CLAUDE=1` | Mimics Claude Code request signature |
| `CLI_COMPAT_GITHUB=1` | Mimics GitHub Copilot request signature |
| `CLI_COMPAT_ANTIGRAVITY=1` | Mimics Antigravity request signature |
| `CLI_COMPAT_KIRO=1` | Mimics Kiro IDE request signature |
| `CLI_COMPAT_CURSOR=1` | Mimics Cursor request signature |
| `CLI_COMPAT_KIMI_CODING=1` | Mimics Kimi Coding request signature |
| `CLI_COMPAT_KILOCODE=1` | Mimics Kilo Code request signature |
| `CLI_COMPAT_CLINE=1` | Mimics Cline request signature |
| `CLI_COMPAT_QWEN=1` | Mimics Qwen Code request signature |
| Variable | Efek |
| -------------------------- | ------------------------------------------------- |
| `CLI_COMPAT_CODEX=1` | Meniru tanda tangan permintaan CLI Codex |
| `CLI_COMPAT_CLAUDE=1` | Meniru tanda tangan permintaan Claude Code |
| `CLI_COMPAT_GITHUB=1` | Meniru tanda tangan permintaan GitHub Copilot |
| `CLI_COMPAT_ANTIGRAVITY=1` | Meniru tanda tangan permintaan Antigravity |
| `CLI_COMPAT_KIRO=1` | Meniru tanda tangan permintaan Kiro IDE |
| `CLI_COMPAT_CURSOR=1` | Meniru tanda tangan permintaan Cursor |
| `CLI_COMPAT_KIMI_CODING=1` | Meniru tanda tangan permintaan Kimi Coding |
| `CLI_COMPAT_KILOCODE=1` | Meniru tanda tangan permintaan Kilo Code |
| `CLI_COMPAT_CLINE=1` | Meniru tanda tangan permintaan Cline |
| `CLI_COMPAT_QWEN=1` | Meniru tanda tangan permintaan Qwen Code |
### Global
| Variable | Effect |
| ------------------ | --------------------------------------------------------------- |
| `CLI_COMPAT_ALL=1` | Enable fingerprint compatibility for **all** providers at once. |
| Variable | Efek |
| ------------------ | ------------------------------------------------------------------------ |
| `CLI_COMPAT_ALL=1` | Aktifkan kompatibilitas fingerprint untuk **semua** provider sekaligus. |
> [!NOTE]
> This feature works alongside the User-Agent overrides (§12). The fingerprint system handles header ordering and body field ordering, while User-Agent overrides handle the specific UA string. Both can be enabled independently.
> Fitur ini bekerja berdampingan dengan override User-Agent (§12). Sistem fingerprint menangani urutan header dan urutan field body, sementara override User-Agent menangani string UA tertentu. Keduanya dapat diaktifkan secara independen.
---
## 14. API Key Providers
## 14. Provider Kunci API
API keys for providers that use direct authentication. **Preferred setup:** Dashboard → Providers → Add API Key.
Kunci API untuk provider yang menggunakan autentikasi langsung. **Pengaturan yang disarankan:** Dashboard → Providers → Add API Key.
Setting via environment variables is an alternative for Docker or headless deployments.
Pengaturan melalui variabel lingkungan adalah alternatif untuk deployment Docker atau tanpa antarmuka grafis.
Recognized pattern: `{PROVIDER_ID}_API_KEY`
Pola yang dikenali: `{PROVIDER_ID}_API_KEY`
| Variable | Provider |
| -------------------- | ------------------- |
@@ -410,15 +410,15 @@ Recognized pattern: `{PROVIDER_ID}_API_KEY`
| `NEBIUS_API_KEY` | Nebius (embeddings) |
> [!TIP]
> Keys set via the Dashboard are stored encrypted in SQLite and take precedence over environment variables.
> Kunci yang diatur melalui Dashboard disimpan terenkripsi di SQLite dan mengambil prioritas di atas variabel lingkungan.
---
## 15. Timeout Settings
## 15. Pengaturan Batas Waktu
All values are in **milliseconds**. Centralized resolution in `src/shared/utils/runtimeTimeouts.ts`.
Semua nilai dalam satuan **milidetik**. Penyelesaian terpusat di `src/shared/utils/runtimeTimeouts.ts`.
### Timeout Hierarchy
### Hierarki Batas Waktu
```
REQUEST_TIMEOUT_MS (global override)
@@ -436,69 +436,69 @@ REQUEST_TIMEOUT_MS (global override)
└── API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS (default: 0 = disabled)
```
| Variable | Default | Description |
| ---------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------- |
| `REQUEST_TIMEOUT_MS` | _(unset)_ | Global shortcut — overrides both `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` defaults. |
| `FETCH_TIMEOUT_MS` | `600000` | Total HTTP request timeout for upstream provider calls. |
| `STREAM_IDLE_TIMEOUT_MS` | `600000` | Max silence between SSE chunks before aborting. Extended-thinking models rarely pause >90s. |
| `FETCH_HEADERS_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | Time to receive response headers. |
| `FETCH_BODY_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | Time to receive the full response body. |
| `FETCH_CONNECT_TIMEOUT_MS` | `30000` | TCP connection establishment timeout. |
| `FETCH_KEEPALIVE_TIMEOUT_MS` | `4000` | Keep-alive socket idle timeout. |
| `TLS_CLIENT_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | TLS fingerprint proxy (wreq-js) timeout. |
| `API_BRIDGE_PROXY_TIMEOUT_MS` | `600000` | Proxy hop timeout for `/v1` bridge requests. |
| `API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS` | `600000` | Overall server request timeout for the bridge. |
| `API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS` | `60000` | Time to send response headers via the bridge. |
| `API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS` | `5000` | Bridge keep-alive idle timeout. |
| `API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS` | `0` | Raw socket timeout (0 = disabled). |
| `SHUTDOWN_TIMEOUT_MS` | `30000` | Grace period on SIGTERM/SIGINT before force-exit. |
| Variable | Default | Deskripsi |
| ---------------------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `REQUEST_TIMEOUT_MS` | _(unset)_ | Pintasan global — menimpa default `FETCH_TIMEOUT_MS` maupun `STREAM_IDLE_TIMEOUT_MS`. |
| `FETCH_TIMEOUT_MS` | `600000` | Total batas waktu permintaan HTTP untuk panggilan provider upstream. |
| `STREAM_IDLE_TIMEOUT_MS` | `600000` | Keheningan maksimum antar chunk SSE sebelum dibatalkan. Model extended-thinking jarang berhenti lebih dari 90 detik. |
| `FETCH_HEADERS_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | Waktu untuk menerima header respons. |
| `FETCH_BODY_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | Waktu untuk menerima body respons penuh. |
| `FETCH_CONNECT_TIMEOUT_MS` | `30000` | Batas waktu pembentukan koneksi TCP. |
| `FETCH_KEEPALIVE_TIMEOUT_MS` | `4000` | Batas waktu idle socket keep-alive. |
| `TLS_CLIENT_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | Batas waktu proxy fingerprint TLS (wreq-js). |
| `API_BRIDGE_PROXY_TIMEOUT_MS` | `600000` | Batas waktu hop proxy untuk permintaan jembatan `/v1`. |
| `API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS` | `600000` | Batas waktu permintaan server keseluruhan untuk jembatan. |
| `API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS` | `60000` | Waktu untuk mengirim header respons melalui jembatan. |
| `API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS` | `5000` | Batas waktu idle keep-alive jembatan. |
| `API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS` | `0` | Batas waktu socket mentah (0 = dinonaktifkan). |
| `SHUTDOWN_TIMEOUT_MS` | `30000` | Periode grace pada SIGTERM/SIGINT sebelum force-exit. |
### Scenarios
### Skenario
| Scenario | Configuration |
| -------------------------------- | ------------------------------------------------------ |
| **Long-running code generation** | `REQUEST_TIMEOUT_MS=900000` (15 min) |
| **Fast-fail for production API** | `API_BRIDGE_PROXY_TIMEOUT_MS=10000` |
| **Extended thinking models** | `STREAM_IDLE_TIMEOUT_MS=300000` (5 min between chunks) |
| Skenario | Konfigurasi |
| ----------------------------------------- | --------------------------------------------------------- |
| **Pembuatan kode berjalan lama** | `REQUEST_TIMEOUT_MS=900000` (15 menit) |
| **Fast-fail untuk API produksi** | `API_BRIDGE_PROXY_TIMEOUT_MS=10000` |
| **Model extended thinking** | `STREAM_IDLE_TIMEOUT_MS=300000` (5 menit antar chunk) |
---
## 16. Logging
The logging system writes to both stdout and rotated log files. All configuration is read by `src/lib/logEnv.ts`.
Sistem logging menulis ke stdout dan file log yang dirotasi. Semua konfigurasi dibaca oleh `src/lib/logEnv.ts`.
| Variable | Default | Description |
| --------------------------- | -------------------------- | ---------------------------------------------------------------------------- |
| `APP_LOG_LEVEL` | `info` | Minimum log level: `debug`, `info`, `warn`, `error`. |
| `APP_LOG_FORMAT` | `text` | Output format: `text` (human-readable) or `json` (structured). |
| `APP_LOG_TO_FILE` | `true` | Write logs to file alongside stdout. |
| `APP_LOG_FILE_PATH` | `logs/application/app.log` | Log file path (relative to project root or `DATA_DIR`). |
| `APP_LOG_MAX_FILE_SIZE` | `50M` | Max file size before rotation. Accepts: `50M`, `1G`, `512K`, or plain bytes. |
| `APP_LOG_RETENTION_DAYS` | `7` | Days to keep rotated application log files. |
| `APP_LOG_MAX_FILES` | `20` | Maximum rotated log file backups. |
| `CALL_LOG_RETENTION_DAYS` | `7` | Days to keep request/call log entries in the database. |
| `CALL_LOG_MAX_ENTRIES` | `10000` | Max call log entries in the in-memory buffer. |
| `CALL_LOGS_TABLE_MAX_ROWS` | `100000` | Max rows in the `call_logs` SQLite table before pruning. |
| `PROXY_LOGS_TABLE_MAX_ROWS` | `100000` | Max rows in the `proxy_logs` SQLite table before pruning. |
| Variable | Default | Deskripsi |
| --------------------------- | -------------------------- | -------------------------------------------------------------------------------------- |
| `APP_LOG_LEVEL` | `info` | Level log minimum: `debug`, `info`, `warn`, `error`. |
| `APP_LOG_FORMAT` | `text` | Format output: `text` (mudah dibaca manusia) atau `json` (terstruktur). |
| `APP_LOG_TO_FILE` | `true` | Tulis log ke file bersama stdout. |
| `APP_LOG_FILE_PATH` | `logs/application/app.log` | Path file log (relatif terhadap root proyek atau `DATA_DIR`). |
| `APP_LOG_MAX_FILE_SIZE` | `50M` | Ukuran file maksimum sebelum rotasi. Menerima: `50M`, `1G`, `512K`, atau byte biasa. |
| `APP_LOG_RETENTION_DAYS` | `7` | Hari untuk menyimpan file log aplikasi yang telah dirotasi. |
| `APP_LOG_MAX_FILES` | `20` | Maksimum cadangan file log yang telah dirotasi. |
| `CALL_LOG_RETENTION_DAYS` | `7` | Hari untuk menyimpan entri log permintaan/panggilan di database. |
| `CALL_LOG_MAX_ENTRIES` | `10000` | Maksimum entri log panggilan dalam buffer in-memory. |
| `CALL_LOGS_TABLE_MAX_ROWS` | `100000` | Maksimum baris dalam tabel SQLite `call_logs` sebelum dipangkas. |
| `PROXY_LOGS_TABLE_MAX_ROWS` | `100000` | Maksimum baris dalam tabel SQLite `proxy_logs` sebelum dipangkas. |
---
## 17. Memory Optimization
## 17. Optimasi Memori
| Variable | Default | Description |
| -------------------------- | ------------------------------- | ---------------------------------------------------------------------- |
| `OMNIROUTE_MEMORY_MB` | `512` | Runtime V8 heap limit. Docker standalone and `omniroute serve` use it to set `--max-old-space-size`. |
| `PROMPT_CACHE_MAX_SIZE` | `50` | Max cached system prompt entries. |
| `PROMPT_CACHE_MAX_BYTES` | `2097152` (2 MB) | Max total prompt cache size. |
| `PROMPT_CACHE_TTL_MS` | `300000` (5 min) | Prompt cache entry TTL. |
| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max cached temperature=0 responses. |
| `SEMANTIC_CACHE_MAX_BYTES` | `4194304` (4 MB) | Max total semantic cache size. |
| `SEMANTIC_CACHE_TTL_MS` | `1800000` (30 min) | Semantic cache entry TTL. |
| `STREAM_HISTORY_MAX` | `50` | Max recent stream events in the Dashboard live view buffer. |
| `CONTEXT_LENGTH_DEFAULT` | `128000` | Global fallback max context length for models without explicit config. |
| `USAGE_TOKEN_BUFFER` | `100` | Extra token headroom reserved when tracking usage quotas. |
| Variable | Default | Deskripsi |
| -------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `OMNIROUTE_MEMORY_MB` | `512` | Batas heap V8 saat runtime. Docker standalone dan `omniroute serve` menggunakannya untuk mengatur `--max-old-space-size`. |
| `PROMPT_CACHE_MAX_SIZE` | `50` | Maksimum entri prompt sistem yang dicache. |
| `PROMPT_CACHE_MAX_BYTES` | `2097152` (2 MB) | Ukuran total cache prompt maksimum. |
| `PROMPT_CACHE_TTL_MS` | `300000` (5 menit) | TTL entri cache prompt. |
| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Maksimum respons temperature=0 yang dicache. |
| `SEMANTIC_CACHE_MAX_BYTES` | `4194304` (4 MB) | Ukuran total cache semantik maksimum. |
| `SEMANTIC_CACHE_TTL_MS` | `1800000` (30 menit) | TTL entri cache semantik. |
| `STREAM_HISTORY_MAX` | `50` | Maksimum event stream terbaru dalam buffer tampilan langsung Dashboard. |
| `CONTEXT_LENGTH_DEFAULT` | `128000` | Panjang konteks maksimum fallback global untuk model tanpa konfigurasi eksplisit. |
| `USAGE_TOKEN_BUFFER` | `100` | Cadangan token ekstra yang disisihkan saat melacak kuota penggunaan. |
### Low-RAM Docker Example
### Contoh Docker RAM Rendah
```bash
OMNIROUTE_MEMORY_MB=128
@@ -511,85 +511,85 @@ STREAM_HISTORY_MAX=10
---
## 18. Pricing Sync
## 18. Sinkronisasi Harga
Automatic model pricing data synchronization from external sources.
Sinkronisasi data harga model secara otomatis dari sumber eksternal.
| Variable | Default | Source File | Description |
| ----------------------- | ------------- | ------------------------ | ----------------------------- |
| `PRICING_SYNC_ENABLED` | `false` | `src/lib/pricingSync.ts` | Opt-in periodic pricing sync. |
| `PRICING_SYNC_INTERVAL` | `86400` (24h) | `src/lib/pricingSync.ts` | Sync interval in seconds. |
| `PRICING_SYNC_SOURCES` | `litellm` | `src/lib/pricingSync.ts` | Comma-separated data sources. |
| Variable | Default | Source File | Deskripsi |
| ----------------------- | ------------- | ------------------------ | ------------------------------------------------- |
| `PRICING_SYNC_ENABLED` | `false` | `src/lib/pricingSync.ts` | Opt-in sinkronisasi harga berkala. |
| `PRICING_SYNC_INTERVAL` | `86400` (24h) | `src/lib/pricingSync.ts` | Interval sinkronisasi dalam detik. |
| `PRICING_SYNC_SOURCES` | `litellm` | `src/lib/pricingSync.ts` | Sumber data yang dipisahkan koma. |
---
## 19. Model Sync (Dev)
## 19. Sinkronisasi Model (Dev)
| Variable | Default | Source File | Description |
| -------------------------- | ------------- | -------------------------- | -------------------------------------------------------- |
| `MODELS_DEV_SYNC_INTERVAL` | `86400` (24h) | `src/lib/modelsDevSync.ts` | Development-time model catalog sync interval in seconds. |
| Variable | Default | Source File | Deskripsi |
| -------------------------- | ------------- | -------------------------- | ----------------------------------------------------------------------- |
| `MODELS_DEV_SYNC_INTERVAL` | `86400` (24h) | `src/lib/modelsDevSync.ts` | Interval sinkronisasi katalog model saat pengembangan dalam detik. |
---
## 20. Provider-Specific Settings
## 20. Pengaturan Spesifik Provider
| Variable | Default | Source File | Description |
| ----------------------------------------- | ------------------ | ------------------------------------------ | ------------------------------------------------------------------------------------- |
| `OPENROUTER_CATALOG_TTL_MS` | `86400000` (24h) | `src/lib/catalog/openrouterCatalog.ts` | OpenRouter model catalog cache TTL. |
| `NANOBANANA_POLL_TIMEOUT_MS` | `120000` | `open-sse/handlers/imageGeneration.ts` | Max wait for NanoBanana image generation jobs. |
| `NANOBANANA_POLL_INTERVAL_MS` | `2500` | `open-sse/handlers/imageGeneration.ts` | NanoBanana job polling frequency. |
| `CLOUDFLARE_ACCOUNT_ID` | _(unset)_ | `open-sse/executors/cloudflare-ai.ts` | Account ID for Cloudflare Workers AI. |
| `CLOUDFLARED_BIN` | auto-detect | `src/lib/cloudflaredTunnel.ts` | Custom path to `cloudflared` binary. |
| `SEARCH_CACHE_TTL_MS` | `300000` (5 min) | `open-sse/services/searchCache.ts` | TTL for search API (Perplexity, Brave, etc.) response caching. |
| `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` | `false` | `src/app/api/providers/route.ts` | Allow multiple simultaneous connections per OpenAI-compatible provider. |
| `ENABLE_CC_COMPATIBLE_PROVIDER` | `false` | `src/shared/utils/featureFlags.ts` | Enable experimental Claude Code compatible provider endpoint. |
| `CLIPROXYAPI_HOST` | `127.0.0.1` | `open-sse/executors/cliproxyapi.ts` | CLIProxyAPI bridge host (legacy integration). |
| `CLIPROXYAPI_PORT` | `5544` | `open-sse/executors/cliproxyapi.ts` | CLIProxyAPI bridge port. |
| `CLIPROXYAPI_CONFIG_DIR` | `~/.cli-proxy-api` | `src/lib/versionManager/processManager.ts` | CLIProxyAPI config directory. |
| `LOCAL_HOSTNAMES` | _(empty)_ | `open-sse/config/providerRegistry.ts` | Comma-separated additional hostnames treated as "local" (Docker service names, etc.). |
| Variable | Default | Source File | Deskripsi |
| ----------------------------------------- | --------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| `OPENROUTER_CATALOG_TTL_MS` | `86400000` (24h) | `src/lib/catalog/openrouterCatalog.ts` | TTL cache katalog model OpenRouter. |
| `NANOBANANA_POLL_TIMEOUT_MS` | `120000` | `open-sse/handlers/imageGeneration.ts` | Waktu tunggu maksimum untuk pekerjaan pembuatan gambar NanoBanana. |
| `NANOBANANA_POLL_INTERVAL_MS` | `2500` | `open-sse/handlers/imageGeneration.ts` | Frekuensi polling pekerjaan NanoBanana. |
| `CLOUDFLARE_ACCOUNT_ID` | _(unset)_ | `open-sse/executors/cloudflare-ai.ts` | ID akun untuk Cloudflare Workers AI. |
| `CLOUDFLARED_BIN` | deteksi otomatis | `src/lib/cloudflaredTunnel.ts` | Path kustom ke biner `cloudflared`. |
| `SEARCH_CACHE_TTL_MS` | `300000` (5 menit) | `open-sse/services/searchCache.ts` | TTL untuk caching respons API pencarian (Perplexity, Brave, dll.). |
| `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` | `false` | `src/app/api/providers/route.ts` | Izinkan beberapa koneksi simultan per provider yang kompatibel dengan OpenAI. |
| `ENABLE_CC_COMPATIBLE_PROVIDER` | `false` | `src/shared/utils/featureFlags.ts` | Aktifkan endpoint provider eksperimental yang kompatibel dengan Claude Code. |
| `CLIPROXYAPI_HOST` | `127.0.0.1` | `open-sse/executors/cliproxyapi.ts` | Host jembatan CLIProxyAPI (integrasi legacy). |
| `CLIPROXYAPI_PORT` | `5544` | `open-sse/executors/cliproxyapi.ts` | Port jembatan CLIProxyAPI. |
| `CLIPROXYAPI_CONFIG_DIR` | `~/.cli-proxy-api` | `src/lib/versionManager/processManager.ts` | Direktori konfigurasi CLIProxyAPI. |
| `LOCAL_HOSTNAMES` | _(empty)_ | `open-sse/config/providerRegistry.ts` | Nama host tambahan yang dipisahkan koma yang diperlakukan sebagai "lokal" (nama layanan Docker, dll.). |
---
## 21. Proxy Health
## 21. Kesehatan Proxy
| Variable | Default | Source File | Description |
| ---------------------------- | ---------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `PROXY_FAST_FAIL_TIMEOUT_MS` | `2000` | `src/lib/proxyHealth.ts` | Fast-fail health check timeout. |
| `PROXY_HEALTH_CACHE_TTL_MS` | `30000` | `src/lib/proxyHealth.ts` | Health check result cache TTL. |
| `RATE_LIMIT_MAX_WAIT_MS` | `120000` (2 min) | `open-sse/services/rateLimitManager.ts` | Max time to wait on a 429 before failing the request. |
| `REQUEST_RETRY` | `2` | `src/sse/services/cooldownAwareRetry.ts` | Number of automatic retries on model-scoped cooldown responses before returning error to client. |
| `MAX_RETRY_INTERVAL_SEC` | `30` | `src/sse/services/cooldownAwareRetry.ts` | Max backoff interval (seconds) between cooldown retries. Capped by this value regardless of upstream `Retry-After`. |
| Variable | Default | Source File | Deskripsi |
| ---------------------------- | ------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `PROXY_FAST_FAIL_TIMEOUT_MS` | `2000` | `src/lib/proxyHealth.ts` | Batas waktu pemeriksaan kesehatan fast-fail. |
| `PROXY_HEALTH_CACHE_TTL_MS` | `30000` | `src/lib/proxyHealth.ts` | TTL cache hasil pemeriksaan kesehatan. |
| `RATE_LIMIT_MAX_WAIT_MS` | `120000` (2 menit) | `open-sse/services/rateLimitManager.ts` | Waktu tunggu maksimum pada respons 429 sebelum menggagalkan permintaan. |
| `REQUEST_RETRY` | `2` | `src/sse/services/cooldownAwareRetry.ts` | Jumlah percobaan ulang otomatis pada respons cooldown berbasis model sebelum mengembalikan error ke klien. |
| `MAX_RETRY_INTERVAL_SEC` | `30` | `src/sse/services/cooldownAwareRetry.ts` | Interval backoff maksimum (detik) antar percobaan ulang cooldown. Dibatasi oleh nilai ini terlepas dari `Retry-After` upstream. |
---
## 22. Debugging
> [!CAUTION]
> These variables produce **verbose output** and may leak sensitive data. **Never enable in production.**
> Variabel-variabel ini menghasilkan **output yang sangat detail** dan dapat membocorkan data sensitif. **Jangan pernah aktifkan di lingkungan produksi.**
| Variable | Default | Source File | Description |
| -------------------------------- | --------- | ----------------------------------------- | -------------------------------------------------------------- |
| `CURSOR_PROTOBUF_DEBUG` | _(unset)_ | `open-sse/utils/cursorProtobuf.ts` | Set `1` to dump Cursor protobuf decode/encode details. |
| `CURSOR_STREAM_DEBUG` | _(unset)_ | `open-sse/executors/cursor.ts` | Set `1` to dump raw Cursor SSE stream data. |
| `DEBUG_RESPONSES_SSE_TO_JSON` | _(unset)_ | `open-sse/handlers/responseTranslator.ts` | Set `true` to log Responses API SSE→JSON translation details. |
| `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` | _(unset)_ | E2E test harness | Set `true` to enable E2E test mode (relaxed auth, test hooks). |
| Variable | Default | Source File | Deskripsi |
| -------------------------------- | --------- | ----------------------------------------- | ---------------------------------------------------------------------------------- |
| `CURSOR_PROTOBUF_DEBUG` | _(unset)_ | `open-sse/utils/cursorProtobuf.ts` | Atur ke `1` untuk membuang detail decode/encode protobuf Cursor. |
| `CURSOR_STREAM_DEBUG` | _(unset)_ | `open-sse/executors/cursor.ts` | Atur ke `1` untuk membuang data stream SSE Cursor mentah. |
| `DEBUG_RESPONSES_SSE_TO_JSON` | _(unset)_ | `open-sse/handlers/responseTranslator.ts` | Atur ke `true` untuk mencatat log detail translasi SSE→JSON Responses API. |
| `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` | _(unset)_ | E2E test harness | Atur ke `true` untuk mengaktifkan mode pengujian E2E (autentikasi santai, test hook). |
---
## 23. GitHub Integration
## 23. Integrasi GitHub
Allow users to report issues directly from the Dashboard.
Memungkinkan pengguna melaporkan masalah langsung dari Dashboard.
| Variable | Default | Source File | Description |
| --------------------- | --------- | --------------------------------------- | ------------------------------------------------------- |
| `GITHUB_ISSUES_REPO` | _(unset)_ | `src/app/api/v1/issues/report/route.ts` | Repository in `owner/repo` format. |
| `GITHUB_ISSUES_TOKEN` | _(unset)_ | `src/app/api/v1/issues/report/route.ts` | GitHub Personal Access Token with `issues:write` scope. |
| Variable | Default | Source File | Deskripsi |
| --------------------- | --------- | --------------------------------------- | -------------------------------------------------------------------- |
| `GITHUB_ISSUES_REPO` | _(unset)_ | `src/app/api/v1/issues/report/route.ts` | Repositori dalam format `owner/repo`. |
| `GITHUB_ISSUES_TOKEN` | _(unset)_ | `src/app/api/v1/issues/report/route.ts` | GitHub Personal Access Token dengan scope `issues:write`. |
---
## Deployment Scenarios
## Skenario Deployment
### Minimal Local Development
### Pengembangan Lokal Minimal
```bash
JWT_SECRET=$(openssl rand -base64 48)
@@ -629,7 +629,7 @@ OMNIROUTE_DISABLE_BACKGROUND_SERVICES=true
APP_LOG_TO_FILE=false
```
### VPS with Reverse Proxy (nginx + Cloudflare)
### VPS dengan Reverse Proxy (nginx + Cloudflare)
```bash
JWT_SECRET=<generated>
@@ -647,23 +647,23 @@ CLI_COMPAT_ALL=1
---
## Audit: Removed / Dead Variables
## Audit: Variabel yang Dihapus / Tidak Aktif
The following variables appeared in previous versions of `.env.example` but have **no runtime references** in the current codebase. They have been removed:
Variabel-variabel berikut muncul di versi sebelumnya dari `.env.example` tetapi **tidak memiliki referensi runtime** di basis kode saat ini. Variabel-variabel ini telah dihapus:
| Variable | Reason |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `STORAGE_DRIVER=sqlite` | Never read by any source file. SQLite is the only supported driver — no selection needed. |
| `INSTANCE_NAME=omniroute` | Present in old docs/env templates but unused at runtime. May return in a future multi-instance feature. |
| `SQLITE_MAX_SIZE_MB=2048` | Not referenced in source code. Database size is not artificially limited. |
| `SQLITE_CLEAN_LEGACY_FILES=true` | Not referenced in source code. Legacy cleanup was likely removed. |
| `CLI_ROO_BIN` | Not registered in `src/shared/services/cliRuntime.ts`. |
| `CLI_KIMI_CODING_BIN` | Not registered in `src/shared/services/cliRuntime.ts` (Kimi Coding uses OAuth, not a CLI binary). |
| `IFLOW_OAUTH_CLIENT_ID` / `IFLOW_OAUTH_CLIENT_SECRET` | Not referenced anywhere in source code. |
| Variable | Alasan |
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `STORAGE_DRIVER=sqlite` | Tidak pernah dibaca oleh file sumber mana pun. SQLite adalah satu-satunya driver yang didukung — tidak diperlukan pemilihan. |
| `INSTANCE_NAME=omniroute` | Ada di template docs/env lama tetapi tidak digunakan saat runtime. Mungkin kembali dalam fitur multi-instansi di masa depan. |
| `SQLITE_MAX_SIZE_MB=2048` | Tidak dirujuk dalam kode sumber. Ukuran database tidak dibatasi secara artifisial. |
| `SQLITE_CLEAN_LEGACY_FILES=true` | Tidak dirujuk dalam kode sumber. Pembersihan legacy kemungkinan telah dihapus. |
| `CLI_ROO_BIN` | Tidak terdaftar di `src/shared/services/cliRuntime.ts`. |
| `CLI_KIMI_CODING_BIN` | Tidak terdaftar di `src/shared/services/cliRuntime.ts` (Kimi Coding menggunakan OAuth, bukan biner CLI). |
| `IFLOW_OAUTH_CLIENT_ID` / `IFLOW_OAUTH_CLIENT_SECRET` | Tidak dirujuk di mana pun dalam kode sumber. |
### Default Value Corrections
### Koreksi Nilai Default
| Variable | Old `.env.example` Value | Actual Code Default | Fixed |
| ------------------------- | ------------------------ | ------------------- | ------------------------------------------------------ |
| `APP_LOG_RETENTION_DAYS` | `90` | `7` | ✅ Removed misleading value; documented `7` as default |
| `CALL_LOG_RETENTION_DAYS` | `90` | `7` | ✅ Removed misleading value; documented `7` as default |
| Variable | Nilai `.env.example` Lama | Default Kode Aktual | Diperbaiki |
| ------------------------- | ------------------------- | ------------------- | ------------------------------------------------------------------ |
| `APP_LOG_RETENTION_DAYS` | `90` | `7` | ✅ Nilai yang menyesatkan dihapus; `7` didokumentasikan sebagai default |
| `CALL_LOG_RETENTION_DAYS` | `90` | `7` | ✅ Nilai yang menyesatkan dihapus; `7` didokumentasikan sebagai default |

View File

@@ -4,40 +4,40 @@
---
> Self-managing model chains with adaptive scoring
> Rantai model yang mengelola diri sendiri dengan penilaian adaptif
## How It Works
## Cara Kerjanya
The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
Auto-Combo Engine secara dinamis memilih penyedia/model terbaik untuk setiap permintaan menggunakan **fungsi penilaian 6 faktor**:
| Factor | Weight | Description |
| :--------- | :----- | :---------------------------------------------- |
| Quota | 0.20 | Remaining capacity [0..1] |
| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
| TaskFit | 0.10 | Model × task type fitness score |
| Stability | 0.10 | Low variance in latency/errors |
| Faktor | Bobot | Deskripsi |
| :--------- | :---- | :----------------------------------------------------- |
| Quota | 0.20 | Kapasitas tersisa [0..1] |
| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
| CostInv | 0.20 | Biaya invers (lebih murah = skor lebih tinggi) |
| LatencyInv | 0.15 | Latensi p95 invers (lebih cepat = lebih tinggi) |
| TaskFit | 0.10 | Skor kesesuaian model × tipe tugas |
| Stability | 0.10 | Variansi rendah dalam latensi/kesalahan |
## Mode Packs
## Paket Mode
| Pack | Focus | Key Weight |
| Paket | Fokus | Bobot Utama |
| :---------------------- | :----------- | :--------------- |
| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
| 💰 **Cost Saver** | Economy | costInv: 0.40 |
| 🎯 **Quality First** | Best model | taskFit: 0.40 |
| 📡 **Offline Friendly** | Availability | quota: 0.40 |
| 🚀 **Ship Fast** | Kecepatan | latencyInv: 0.35 |
| 💰 **Cost Saver** | Ekonomi | costInv: 0.40 |
| 🎯 **Quality First** | Model terbaik | taskFit: 0.40 |
| 📡 **Offline Friendly** | Ketersediaan | quota: 0.40 |
## Self-Healing
## Pemulihan Mandiri
- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
- **Incident mode**: >50% OPEN → disable exploration, maximize stability
- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
- **Pengecualian sementara**: Skor < 0.2 → dikecualikan selama 5 menit (backoff progresif, maks 30 menit)
- **Kesadaran circuit breaker**: OPEN → dikecualikan otomatis; HALF_OPEN → permintaan probe
- **Mode insiden**: >50% OPEN → nonaktifkan eksplorasi, maksimalkan stabilitas
- **Pemulihan cooldown**: Setelah pengecualian, permintaan pertama adalah "probe" dengan timeout yang dikurangi
## Bandit Exploration
## Eksplorasi Bandit
5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
5% permintaan (dapat dikonfigurasi) diarahkan ke penyedia acak untuk eksplorasi. Dinonaktifkan dalam mode insiden.
## API
@@ -51,17 +51,17 @@ curl -X POST http://localhost:20128/api/combos/auto \
curl http://localhost:20128/api/combos/auto
```
## Task Fitness
## Kesesuaian Tugas
30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder`high coding score).
30+ model dinilai di 6 tipe tugas (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Mendukung pola wildcard (mis., `*-coder`skor coding tinggi).
## Files
## Berkas
| File | Purpose |
| :------------------------------------------- | :------------------------------------ |
| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
| `src/app/api/combos/auto/route.ts` | REST API |
| Berkas | Tujuan |
| :------------------------------------------- | :-------------------------------------------- |
| `open-sse/services/autoCombo/scoring.ts` | Fungsi penilaian & normalisasi pool |
| `open-sse/services/autoCombo/taskFitness.ts` | Pencarian kesesuaian model × tugas |
| `open-sse/services/autoCombo/engine.ts` | Logika pemilihan, bandit, batas anggaran |
| `open-sse/services/autoCombo/selfHealing.ts` | Pengecualian, probe, mode insiden |
| `open-sse/services/autoCombo/modePacks.ts` | 4 profil bobot |
| `src/app/api/combos/auto/route.ts` | REST API |

View File

@@ -4,191 +4,191 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 177 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (37 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex-cloud, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute adalah AI Gateway gratis dan open-source yang berfungsi sebagai proxy API universal untuk LLM multi-penyedia. OmniRoute menyediakan routing cerdas, fallback otomatis, load balancing, dan translasi format untuk 177 penyedia AI — semuanya melalui satu endpoint yang kompatibel dengan OpenAI. Dilengkapi dengan MCP Server bawaan (37 alat), protokol A2A v0.3, sistem Memory/Skills, Cloud Agents (codex-cloud, devin, jules), kerangka Guardrails, dan aplikasi desktop Electron.
## Overview
## Ikhtisar
OmniRoute solves the problem of managing multiple AI provider subscriptions, quotas, and rate limits. It sits between your AI-powered tools (IDE agents, CLI tools) and AI providers, routing requests intelligently through a 4-tier fallback system: Subscription → API Key → Cheap → Free.
OmniRoute menyelesaikan masalah pengelolaan beberapa langganan penyedia AI, kuota, dan batas kecepatan. OmniRoute berada di antara alat bertenaga AI Anda (agen IDE, alat CLI) dan penyedia AI, merutekan permintaan secara cerdas melalui sistem fallback 4-tingkat: Subscription → API Key → Cheap → Free.
**Key value:** One endpoint (`http://localhost:20128/v1`), unlimited models, zero downtime, minimal cost.
**Nilai utama:** Satu endpoint (`http://localhost:20128/v1`), model tak terbatas, tanpa downtime, biaya minimal.
**Current version:** 3.8.8
**Versi saat ini:** 3.8.8
## Tech Stack
## Tumpukan Teknologi
- **Runtime:** Node.js `>=20.20.2 <21 || >=22.22.2 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
- **Framework:** Next.js 16 (App Router) with TypeScript 5.9
- **Database:** SQLite via better-sqlite3 (local, zero-config, 55 migrations)
- **State management:** Zustand (client), SQLite (server persistence)
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
- **Schemas:** Zod v4 for all API / MCP input validation
- **Background jobs:** Custom token health check scheduler, 24h model auto-sync
- **Streaming:** Server-Sent Events (SSE) for real-time proxy responses
- **Proxy engine:** Custom pipeline with format translation, circuit breaker, rate limiting, auto-combo engine
- **i18n:** next-intl with 40+ languages
- **Desktop:** Electron (cross-platform: Windows, macOS, Linux)
- **Package:** Published on npm (`omniroute`) and Docker Hub (`diegosouzapw/omniroute`)
- **Framework:** Next.js 16 (App Router) dengan TypeScript 5.9
- **Database:** SQLite via better-sqlite3 (lokal, tanpa konfigurasi, 55 migrasi)
- **Manajemen state:** Zustand (klien), SQLite (persistensi server)
- **UI:** React 19, Tailwind CSS 4, Recharts untuk analitik, @lobehub/icons untuk 130+ ikon SVG penyedia
- **Auth:** OAuth 2.0 (PKCE) untuk penyedia, bcrypt untuk autentikasi pengguna lokal
- **Skema:** Zod v4 untuk semua validasi input API / MCP
- **Pekerjaan latar belakang:** Penjadwal pemeriksaan kesehatan token kustom, auto-sync model 24 jam
- **Streaming:** Server-Sent Events (SSE) untuk respons proxy secara real-time
- **Mesin proxy:** Pipeline kustom dengan translasi format, circuit breaker, pembatasan kecepatan, mesin auto-combo
- **i18n:** next-intl dengan 40+ bahasa
- **Desktop:** Electron (lintas platform: Windows, macOS, Linux)
- **Paket:** Diterbitkan di npm (`omniroute`) dan Docker Hub (`diegosouzapw/omniroute`)
## Project Structure
## Struktur Proyek
```
/
├── src/ # Main application source
│ ├── app/ # Next.js App Router pages and API routes
│ │ ├── (dashboard)/ # Dashboard UI pages
├── src/ # Sumber utama aplikasi
│ ├── app/ # Halaman Next.js App Router dan rute API
│ │ ├── (dashboard)/ # Halaman UI dashboard
│ │ │ └── dashboard/
│ │ │ ├── agents/ # ACP Agents dashboard (CLI agent detection + custom agents)
│ │ │ ├── analytics/ # Usage analytics and charts
│ │ │ ├── api-manager/ # API key management
│ │ │ ├── audit/ # Audit logs
│ │ │ ├── auto-combo/ # Auto-combo engine dashboard
│ │ │ ├── cache/ # Cache dashboard (semantic cache stats)
│ │ │ ├── cli-tools/ # CLI tool configuration (Claude Code, Codex, Gemini CLI, etc.)
│ │ │ ├── combos/ # Model combo management (14 strategies + 4 templates)
│ │ │ ├── costs/ # Cost tracking per provider/model
│ │ │ ├── endpoint/ # Unified: Endpoint Proxy, MCP, A2A, API Endpoints tabs
│ │ │ ├── health/ # System health (uptime, circuit breakers, latency)
│ │ │ ├── limits/ # Rate limits dashboard
│ │ │ ├── logs/ # Request, Proxy, Audit, Console logs (tabbed)
│ │ │ ├── media/ # Image/video/music generation + transcription
│ │ │ ├── memory/ # Memory system dashboard
│ │ │ ├── onboarding/ # Onboarding wizard
│ │ │ ├── playground/ # Model playground (Monaco editor, streaming)
│ │ │ ├── providers/ # Provider management (OAuth + API key + free)
│ │ │ ├── search-tools/ # Search tools configuration
│ │ │ ├── settings/ # Settings tabs (General, Appearance, Security, Routing, Resilience, Advanced)
│ │ │ ├── skills/ # Skills system dashboard
│ │ │ ├── translator/ # Format translator + debug tools
│ │ │ └── usage/ # Usage history
│ │ ├── api/ # REST API endpoints (51 route directories)
│ │ │ ├── v1/ # OpenAI-compatible API (chat, completions, models, embeddings,
│ │ │ ├── agents/ # Dashboard ACP Agents (deteksi agen CLI + agen kustom)
│ │ │ ├── analytics/ # Analitik penggunaan dan grafik
│ │ │ ├── api-manager/ # Manajemen kunci API
│ │ │ ├── audit/ # Log audit
│ │ │ ├── auto-combo/ # Dashboard mesin auto-combo
│ │ │ ├── cache/ # Dashboard cache (statistik cache semantik)
│ │ │ ├── cli-tools/ # Konfigurasi alat CLI (Claude Code, Codex, Gemini CLI, dll.)
│ │ │ ├── combos/ # Manajemen combo model (14 strategi + 4 template)
│ │ │ ├── costs/ # Pelacakan biaya per penyedia/model
│ │ │ ├── endpoint/ # Terpadu: tab Endpoint Proxy, MCP, A2A, API Endpoints
│ │ │ ├── health/ # Kesehatan sistem (uptime, circuit breaker, latensi)
│ │ │ ├── limits/ # Dashboard batas kecepatan
│ │ │ ├── logs/ # Log Permintaan, Proxy, Audit, Konsol (bertab)
│ │ │ ├── media/ # Pembuatan gambar/video/musik + transkripsi
│ │ │ ├── memory/ # Dashboard sistem memori
│ │ │ ├── onboarding/ # Wizard orientasi
│ │ │ ├── playground/ # Taman bermain model (editor Monaco, streaming)
│ │ │ ├── providers/ # Manajemen penyedia (OAuth + kunci API + gratis)
│ │ │ ├── search-tools/ # Konfigurasi alat pencarian
│ │ │ ├── settings/ # Tab pengaturan (Umum, Tampilan, Keamanan, Routing, Resilience, Lanjutan)
│ │ │ ├── skills/ # Dashboard sistem skills
│ │ │ ├── translator/ # Penerjemah format + alat debug
│ │ │ └── usage/ # Riwayat penggunaan
│ │ ├── api/ # Endpoint REST API (51 direktori rute)
│ │ │ ├── v1/ # API kompatibel OpenAI (chat, completions, models, embeddings,
│ │ │ │ # images, audio, videos, music, moderations, rerank, search,
│ │ │ │ # responses, messages, registered-keys, quotas, accounts)
│ │ │ ├── v1beta/ # Gemini-compatible API
│ │ │ ├── a2a/ # A2A agent management API
│ │ │ ├── acp/ # ACP agent management API
│ │ │ ├── oauth/ # OAuth flows per provider
│ │ │ ├── providers/ # Provider CRUD and batch testing
│ │ │ ├── models/ # Dashboard model listing and aliases
│ │ │ ├── combos/ # Combo CRUD (multi-model fallback chains)
│ │ │ ├── memory/ # Memory system API
│ │ │ ├── skills/ # Skills system API
│ │ │ ├── evals/ # Eval runner API
│ │ │ ├── mcp/ # MCP HTTP transport API
│ │ │ ├── search/ # Search provider API
│ │ │ ├── webhooks/ # Webhook management
│ │ │ ├── tunnels/ # Cloudflare tunnel management
│ │ │ └── ... # Other endpoints (usage, logs, health, settings, pricing, etc.)
│ │ ├── landing/ # Landing page
│ │ ├── login/ # Login page
│ │ ├── forgot-password/ # Password recovery
│ │ ├── status/ # Status page
│ │ └── docs/ # In-app documentation
│ ├── domain/ # Domain types and policy engine
│ │ ├── policyEngine.ts # Central policy engine
│ │ ├── comboResolver.ts # Combo resolution logic
│ │ ├── costRules.ts # Cost calculation rules
│ │ ├── degradation.ts # Graceful degradation
│ │ ├── fallbackPolicy.ts # Fallback behavior
│ │ ├── lockoutPolicy.ts # Account lockout logic
│ │ ├── modelAvailability.ts # Model availability checks
│ │ ├── providerExpiration.ts # Provider credential expiration
│ │ ├── quotaCache.ts # Quota caching layer
│ │ ├── configAudit.ts # Configuration auditing
│ │ └── responses.ts # Domain response types
│ ├── i18n/ # Internationalization
│ │ └── messages/ # 40+ language JSON files
│ ├── lib/ # Core libraries
│ │ ├── a2a/ # Agent-to-Agent v0.3 protocol server
│ │ │ ├── skills/ # A2A skills (quotaManagement, smartRouting)
│ │ │ ├── taskManager.ts # Task lifecycle with TTL cleanup
│ │ │ └── streaming.ts # SSE streaming for A2A
│ │ ├── acp/ # Agent Communication Protocol registry and manager
│ │ ├── compliance/ # Compliance policy engine
│ │ ├── db/ # SQLite database layer (21 modules + migrations)
│ │ │ ├── core.ts # Database initialization, connection, schema
│ │ │ ├── providers.ts # Provider connection CRUD
│ │ │ ├── models.ts # Model catalog management
│ │ │ ├── combos.ts # Combo configuration
│ │ │ ├── apiKeys.ts # API key management
│ │ │ ├── settings.ts # Settings persistence
│ │ │ ├── backup.ts # Database backup/restore
│ │ │ ├── proxies.ts # Proxy registry
│ │ │ ├── prompts.ts # Prompt templates
│ │ │ ├── webhooks.ts # Webhook subscriptions
│ │ │ ├── detailedLogs.ts # Detailed request logging
│ │ │ ├── domainState.ts # Domain state persistence
│ │ │ ├── registeredKeys.ts # Registered API keys with quotas
│ │ │ ├── quotaSnapshots.ts # Quota snapshot history
│ │ │ ├── modelComboMappings.ts # Model-to-combo mappings
│ │ │ ├── cliToolState.ts # CLI tool state tracking
│ │ │ ├── encryption.ts # Data encryption
│ │ │ ├── readCache.ts # Read-through cache layer
│ │ │ ├── secrets.ts # Secrets management
│ │ │ ├── stateReset.ts # State reset utilities
│ │ │ ├── migrationRunner.ts # Schema migration runner
│ │ │ └── migrations/ # 16 SQL migration files
│ │ ├── evals/ # Eval runner and scheduler
│ │ ├── memory/ # Persistent conversational memory
│ │ │ ├── extraction.ts # Memory extraction from conversations
│ │ │ ├── injection.ts # Memory injection into context
│ │ │ ├── retrieval.ts # Memory retrieval/search
│ │ │ ├── store.ts # Memory persistence layer
│ │ │ └── summarization.ts # Memory summarization
│ │ ├── oauth/ # OAuth providers, services, and utilities
│ │ │ ├── constants/ # Default OAuth credentials (overridable via env)
│ │ │ ├── providers/ # Provider-specific OAuth configs
│ │ │ ├── services/ # Provider-specific token exchange logic
│ │ │ └── utils/ # PKCE, callback server, token helpers
│ │ ├── plugins/ # Plugin system
│ │ ├── skills/ # Extensible skill framework
│ │ │ ├── registry.ts # Skill registration
│ │ │ ├── executor.ts # Skill execution engine
│ │ │ ├── sandbox.ts # Skill sandbox environment
│ │ │ ├── builtin/ # Built-in skills
│ │ │ ├── interception.ts # Skill request interception
│ │ │ └── injection.ts # Skill context injection
│ │ ├── usage/ # Usage tracking system
│ │ │ ├── callLogs.ts # Call log persistence
│ │ │ ├── costCalculator.ts # Cost calculation engine
│ │ │ └── usageHistory.ts # Usage history queries
│ │ ├── cloudSync.ts # Cloud sync via Cloudflare Workers
│ │ ├── cloudflaredTunnel.ts # Cloudflare tunnel management
│ │ ├── pricingSync.ts # LiteLLM pricing data sync
│ │ ├── semanticCache.ts # Semantic caching layer
│ │ ├── tokenHealthCheck.ts # Background OAuth token refresh scheduler
│ │ ├── webhookDispatcher.ts # Webhook event dispatcher
│ │ └── localDb.ts # Unified re-export layer for all DB modules
│ ├── middleware/ # Request middleware
│ │ └── promptInjectionGuard.ts # Prompt injection detection
│ ├── mitm/ # MITM proxy capability
│ │ ├── cert/ # Certificate management
│ │ ├── dns/ # DNS handling
│ │ ├── targets/ # Target routing
│ │ └── manager.ts # MITM proxy manager
│ ├── shared/ # Shared utilities, components, and constants
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
│ │ ├── constants/ # Provider definitions (160+), model lists, pricing, routing strategies, MCP scopes
│ │ ├── contracts/ # Shared API contracts
│ │ │ ├── v1beta/ # API kompatibel Gemini
│ │ │ ├── a2a/ # API manajemen agen A2A
│ │ │ ├── acp/ # API manajemen agen ACP
│ │ │ ├── oauth/ # Alur OAuth per penyedia
│ │ │ ├── providers/ # CRUD penyedia dan pengujian batch
│ │ │ ├── models/ # Daftar model dashboard dan alias
│ │ │ ├── combos/ # CRUD combo (rantai fallback multi-model)
│ │ │ ├── memory/ # API sistem memori
│ │ │ ├── skills/ # API sistem skills
│ │ │ ├── evals/ # API runner eval
│ │ │ ├── mcp/ # API transport HTTP MCP
│ │ │ ├── search/ # API penyedia pencarian
│ │ │ ├── webhooks/ # Manajemen webhook
│ │ │ ├── tunnels/ # Manajemen tunnel Cloudflare
│ │ │ └── ... # Endpoint lainnya (usage, logs, health, settings, pricing, dll.)
│ │ ├── landing/ # Halaman landing
│ │ ├── login/ # Halaman login
│ │ ├── forgot-password/ # Pemulihan kata sandi
│ │ ├── status/ # Halaman status
│ │ └── docs/ # Dokumentasi dalam aplikasi
│ ├── domain/ # Tipe domain dan mesin kebijakan
│ │ ├── policyEngine.ts # Mesin kebijakan pusat
│ │ ├── comboResolver.ts # Logika resolusi combo
│ │ ├── costRules.ts # Aturan perhitungan biaya
│ │ ├── degradation.ts # Degradasi bertahap
│ │ ├── fallbackPolicy.ts # Perilaku fallback
│ │ ├── lockoutPolicy.ts # Logika penguncian akun
│ │ ├── modelAvailability.ts # Pemeriksaan ketersediaan model
│ │ ├── providerExpiration.ts # Kedaluwarsa kredensial penyedia
│ │ ├── quotaCache.ts # Lapisan caching kuota
│ │ ├── configAudit.ts # Audit konfigurasi
│ │ └── responses.ts # Tipe respons domain
│ ├── i18n/ # Internasionalisasi
│ │ └── messages/ # 40+ file JSON bahasa
│ ├── lib/ # Pustaka inti
│ │ ├── a2a/ # Server protokol Agent-to-Agent v0.3
│ │ │ ├── skills/ # Skills A2A (quotaManagement, smartRouting)
│ │ │ ├── taskManager.ts # Siklus hidup tugas dengan pembersihan TTL
│ │ │ └── streaming.ts # SSE streaming untuk A2A
│ │ ├── acp/ # Registri dan manajer Agent Communication Protocol
│ │ ├── compliance/ # Mesin kebijakan kepatuhan
│ │ ├── db/ # Lapisan database SQLite (21 modul + migrasi)
│ │ │ ├── core.ts # Inisialisasi database, koneksi, skema
│ │ │ ├── providers.ts # CRUD koneksi penyedia
│ │ │ ├── models.ts # Manajemen katalog model
│ │ │ ├── combos.ts # Konfigurasi combo
│ │ │ ├── apiKeys.ts # Manajemen kunci API
│ │ │ ├── settings.ts # Persistensi pengaturan
│ │ │ ├── backup.ts # Backup/restore database
│ │ │ ├── proxies.ts # Registri proxy
│ │ │ ├── prompts.ts # Template prompt
│ │ │ ├── webhooks.ts # Langganan webhook
│ │ │ ├── detailedLogs.ts # Pencatatan permintaan terperinci
│ │ │ ├── domainState.ts # Persistensi state domain
│ │ │ ├── registeredKeys.ts # Kunci API terdaftar dengan kuota
│ │ │ ├── quotaSnapshots.ts # Riwayat snapshot kuota
│ │ │ ├── modelComboMappings.ts # Pemetaan model-ke-combo
│ │ │ ├── cliToolState.ts # Pelacakan state alat CLI
│ │ │ ├── encryption.ts # Enkripsi data
│ │ │ ├── readCache.ts # Lapisan cache read-through
│ │ │ ├── secrets.ts # Manajemen rahasia
│ │ │ ├── stateReset.ts # Utilitas reset state
│ │ │ ├── migrationRunner.ts # Runner migrasi skema
│ │ │ └── migrations/ # 16 file migrasi SQL
│ │ ├── evals/ # Runner dan penjadwal eval
│ │ ├── memory/ # Memori percakapan persisten
│ │ │ ├── extraction.ts # Ekstraksi memori dari percakapan
│ │ │ ├── injection.ts # Injeksi memori ke dalam konteks
│ │ │ ├── retrieval.ts # Pengambilan/pencarian memori
│ │ │ ├── store.ts # Lapisan persistensi memori
│ │ │ └── summarization.ts # Ringkasan memori
│ │ ├── oauth/ # Penyedia, layanan, dan utilitas OAuth
│ │ │ ├── constants/ # Kredensial OAuth default (dapat diganti via env)
│ │ │ ├── providers/ # Konfigurasi OAuth spesifik penyedia
│ │ │ ├── services/ # Logika pertukaran token spesifik penyedia
│ │ │ └── utils/ # PKCE, server callback, pembantu token
│ │ ├── plugins/ # Sistem plugin
│ │ ├── skills/ # Kerangka skill yang dapat dikembangkan
│ │ │ ├── registry.ts # Registrasi skill
│ │ │ ├── executor.ts # Mesin eksekusi skill
│ │ │ ├── sandbox.ts # Lingkungan sandbox skill
│ │ │ ├── builtin/ # Skill bawaan
│ │ │ ├── interception.ts # Intersepsi permintaan skill
│ │ │ └── injection.ts # Injeksi konteks skill
│ │ ├── usage/ # Sistem pelacakan penggunaan
│ │ │ ├── callLogs.ts # Persistensi log panggilan
│ │ │ ├── costCalculator.ts # Mesin perhitungan biaya
│ │ │ └── usageHistory.ts # Kueri riwayat penggunaan
│ │ ├── cloudSync.ts # Sinkronisasi cloud via Cloudflare Workers
│ │ ├── cloudflaredTunnel.ts # Manajemen tunnel Cloudflare
│ │ ├── pricingSync.ts # Sinkronisasi data harga LiteLLM
│ │ ├── semanticCache.ts # Lapisan caching semantik
│ │ ├── tokenHealthCheck.ts # Penjadwal refresh token OAuth latar belakang
│ │ ├── webhookDispatcher.ts # Dispatcher event webhook
│ │ └── localDb.ts # Lapisan re-ekspor terpadu untuk semua modul DB
│ ├── middleware/ # Middleware permintaan
│ │ └── promptInjectionGuard.ts # Deteksi injeksi prompt
│ ├── mitm/ # Kemampuan proxy MITM
│ │ ├── cert/ # Manajemen sertifikat
│ │ ├── dns/ # Penanganan DNS
│ │ ├── targets/ # Routing target
│ │ └── manager.ts # Manajer proxy MITM
│ ├── shared/ # Utilitas, komponen, dan konstanta bersama
│ │ ├── components/ # Komponen UI yang dapat digunakan ulang (Card, Badge, Button, Modal, Sidebar, ProviderIcon, dll.)
│ │ ├── constants/ # Definisi penyedia (160+), daftar model, harga, strategi routing, cakupan MCP
│ │ ├── contracts/ # Kontrak API bersama
│ │ ├── hooks/ # React hooks
│ │ ├── middleware/ # Shared middleware utilities
│ │ ├── schemas/ # Shared Zod schemas
│ │ ├── services/ # Shared services
│ │ ├── types/ # Shared TypeScript types
│ │ ├── validation/ # Zod schemas (settings, providers, routes)
│ │ └── utils/ # Helpers (auth, CORS, error codes, machine ID)
│ ├── sse/ # SSE proxy pipeline
│ │ ├── services/ # Auth resolution, format translation, response handling
│ │ └── middleware/ # Rate limiting, circuit breaker, caching, idempotency
│ ├── store/ # Zustand client-side stores (theme, providers, etc.)
│ └── types/ # TypeScript type definitions
├── open-sse/ # Standalone SSE server (npm workspace)
│ ├── config/ # Model registries (providerRegistry, embedding, image, audio, video,
│ │ # music, rerank, moderation, search, CLI fingerprints, Ollama models)
│ ├── executors/ # Provider-specific request executors (31 executors)
│ │ ├── base.ts # Base executor with shared logic
│ │ ├── default.ts # Default OpenAI-compatible executor
│ │ ├── middleware/ # Utilitas middleware bersama
│ │ ├── schemas/ # Skema Zod bersama
│ │ ├── services/ # Layanan bersama
│ │ ├── types/ # Tipe TypeScript bersama
│ │ ├── validation/ # Skema Zod (settings, providers, routes)
│ │ └── utils/ # Pembantu (auth, CORS, kode error, ID mesin)
│ ├── sse/ # Pipeline proxy SSE
│ │ ├── services/ # Resolusi auth, translasi format, penanganan respons
│ │ └── middleware/ # Pembatasan kecepatan, circuit breaker, caching, idempotency
│ ├── store/ # Store sisi klien Zustand (tema, penyedia, dll.)
│ └── types/ # Definisi tipe TypeScript
├── open-sse/ # Server SSE mandiri (workspace npm)
│ ├── config/ # Registri model (providerRegistry, embedding, image, audio, video,
│ │ # music, rerank, moderation, search, sidik jari CLI, model Ollama)
│ ├── executors/ # Executor permintaan spesifik penyedia (31 executor)
│ │ ├── base.ts # Executor dasar dengan logika bersama
│ │ ├── default.ts # Executor kompatibel OpenAI default
│ │ ├── cursor.ts # Cursor IDE (protobuf + checksum)
│ │ ├── codex.ts # OpenAI Codex CLI
│ │ ├── antigravity.ts # Antigravity IDE
@@ -201,315 +201,315 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
│ │ ├── opencode.ts # OpenCode Zen/Go
│ │ ├── pollinations.ts # Pollinations AI
│ │ └── puter.ts # Puter AI
│ ├── handlers/ # Request handlers per API type (11 handlers)
│ │ ├── chatCore.ts # Main chat completions handler
│ │ ├── responsesHandler.ts # OpenAI Responses API handler
│ │ ├── embeddings.ts # Embedding generation
│ │ ├── imageGeneration.ts # Image generation (GPT-Image, FLUX, SD, etc.)
│ │ ├── videoGeneration.ts # Video generation
│ │ ├── musicGeneration.ts # Music generation
│ ├── handlers/ # Handler permintaan per tipe API (11 handler)
│ │ ├── chatCore.ts # Handler utama chat completions
│ │ ├── responsesHandler.ts # Handler OpenAI Responses API
│ │ ├── embeddings.ts # Pembuatan embedding
│ │ ├── imageGeneration.ts # Pembuatan gambar (GPT-Image, FLUX, SD, dll.)
│ │ ├── videoGeneration.ts # Pembuatan video
│ │ ├── musicGeneration.ts # Pembuatan musik
│ │ ├── audioSpeech.ts # Text-to-speech
│ │ ├── audioTranscription.ts # Speech-to-text (Whisper, Deepgram, AssemblyAI)
│ │ ├── moderations.ts # Content moderation
│ │ ├── rerank.ts # Reranking API
│ │ └── search.ts # Web search API
│ ├── mcp-server/ # Built-in MCP server (29 tools, 3 transports: stdio/SSE/streamable-HTTP)
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
│ │ ├── scopeEnforcement.ts # Scope-based access control (10 scopes)
│ │ ├── audit.ts # Tool call audit logging
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
│ │ └── httpTransport.ts # HTTP transport handler
│ ├── services/ # 36+ service modules
│ │ ├── combo.ts # Core routing engine
│ │ ├── usage.ts # Usage tracking
│ │ ├── tokenRefresh.ts # OAuth token refresh
│ │ ├── rateLimitManager.ts # Rate limit management
│ │ ├── accountFallback.ts # Multi-account fallback
│ │ ├── sessionManager.ts # Session management
│ │ ├── wildcardRouter.ts # Wildcard model routing
│ │ ├── autoCombo/ # Auto-combo engine (6-factor scoring, bandit exploration)
│ │ ├── intentClassifier.ts # Request intent classification
│ │ ├── taskAwareRouter.ts # Task-aware routing
│ │ ├── thinkingBudget.ts # Thinking budget management
│ │ ├── contextManager.ts # Context window management
│ │ ├── modelDeprecation.ts # Model deprecation handling
│ │ ├── modelFamilyFallback.ts # Intra-family model fallback
│ │ ├── emergencyFallback.ts # Emergency fallback
│ │ ├── workflowFSM.ts # Workflow state machine
│ │ ├── backgroundTaskDetector.ts # Background task detection
│ │ ├── ipFilter.ts # IP-based access control
│ │ ├── signatureCache.ts # CLI signature caching
│ │ ├── volumeDetector.ts # Request volume detection
│ │ ├── contextHandoff.ts # Context relay handoff generation and injection
│ │ ├── codexQuotaFetcher.ts # Codex quota fetching for context-relay
│ │ └── ... # Additional services (14 more modules)
│ ├── transformer/ # Responses API transformer
│ │ ├── moderations.ts # Moderasi konten
│ │ ├── rerank.ts # API reranking
│ │ └── search.ts # API pencarian web
│ ├── mcp-server/ # Server MCP bawaan (29 alat, 3 transport: stdio/SSE/streamable-HTTP)
│ │ ├── server.ts # Inti server MCP (registrasi alat, penegakan cakupan)
│ │ ├── tools/ # Implementasi alat (advancedTools, memoryTools, skillTools)
│ │ ├── schemas/ # Skema input Zod (tools, audit, a2a)
│ │ ├── scopeEnforcement.ts # Kontrol akses berbasis cakupan (10 cakupan)
│ │ ├── audit.ts # Pencatatan audit pemanggilan alat
│ │ ├── runtimeHeartbeat.ts # Heartbeat runtime MCP
│ │ └── httpTransport.ts # Handler transport HTTP
│ ├── services/ # 36+ modul layanan
│ │ ├── combo.ts # Mesin routing inti
│ │ ├── usage.ts # Pelacakan penggunaan
│ │ ├── tokenRefresh.ts # Refresh token OAuth
│ │ ├── rateLimitManager.ts # Manajemen batas kecepatan
│ │ ├── accountFallback.ts # Fallback multi-akun
│ │ ├── sessionManager.ts # Manajemen sesi
│ │ ├── wildcardRouter.ts # Routing model wildcard
│ │ ├── autoCombo/ # Mesin auto-combo (penilaian 6-faktor, eksplorasi bandit)
│ │ ├── intentClassifier.ts # Klasifikasi maksud permintaan
│ │ ├── taskAwareRouter.ts # Routing berbasis tugas
│ │ ├── thinkingBudget.ts # Manajemen anggaran berpikir
│ │ ├── contextManager.ts # Manajemen jendela konteks
│ │ ├── modelDeprecation.ts # Penanganan model yang sudah tidak digunakan
│ │ ├── modelFamilyFallback.ts # Fallback model dalam keluarga yang sama
│ │ ├── emergencyFallback.ts # Fallback darurat
│ │ ├── workflowFSM.ts # Mesin state alur kerja
│ │ ├── backgroundTaskDetector.ts # Deteksi tugas latar belakang
│ │ ├── ipFilter.ts # Kontrol akses berbasis IP
│ │ ├── signatureCache.ts # Caching tanda tangan CLI
│ │ ├── volumeDetector.ts # Deteksi volume permintaan
│ │ ├── contextHandoff.ts # Pembuatan dan injeksi handoff context relay
│ │ ├── codexQuotaFetcher.ts # Pengambilan kuota Codex untuk context-relay
│ │ └── ... # Layanan tambahan (14 modul lagi)
│ ├── transformer/ # Transformer Responses API
│ │ └── responsesTransformer.ts
│ ├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama ↔ DeepSeek)
│ │ ├── request/ # Request translators per provider
│ │ ├── response/ # Response translators per provider
│ │ ├── helpers/ # Translation helpers
│ │ └── image/ # Image format translation
│ └── utils/ # 22 utility modules (stream, TLS, proxy, logging, etc.)
├── electron/ # Electron desktop app (cross-platform)
│ ├── main.js # Electron main process
│ ├── preload.js # Preload script (IPC bridge)
│ └── assets/ # App icons and assets
├── tests/ # Test suites
│ ├── unit/ # 122 unit test files
│ ├── integration/ # Integration tests
│ ├── e2e/ # Playwright E2E tests
│ ├── security/ # Security tests
│ ├── translator/ # Translator-specific tests
│ └── load/ # Load tests
├── docs/ # Documentation
│ ├── i18n/ # 30-language translated docs
│ ├── ARCHITECTURE.md # Full architecture documentation
│ ├── API_REFERENCE.md # API reference
│ ├── USER_GUIDE.md # User guide
│ ├── CODEBASE_DOCUMENTATION.md # Codebase overview
│ ├── CLI-TOOLS.md # CLI tools integration guide
│ ├── A2A-SERVER.md # A2A agent protocol documentation
│ ├── AUTO-COMBO.md # Auto-combo engine (6-factor scoring)
│ ├── MCP-SERVER.md # MCP server (29 tools)
│ ├── TROUBLESHOOTING.md # Troubleshooting guide
│ ├── VM_DEPLOYMENT_GUIDE.md # VPS deployment guide
│ ├── openapi.yaml # OpenAPI specification
│ └── screenshots/ # Dashboard screenshots
├── bin/ # CLI entry points (omniroute, reset-password)
├── scripts/ # Build and utility scripts
└── .env.example # Environment variable template
│ ├── translator/ # Penerjemah format (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama ↔ DeepSeek)
│ │ ├── request/ # Penerjemah permintaan per penyedia
│ │ ├── response/ # Penerjemah respons per penyedia
│ │ ├── helpers/ # Pembantu translasi
│ │ └── image/ # Translasi format gambar
│ └── utils/ # 22 modul utilitas (stream, TLS, proxy, logging, dll.)
├── electron/ # Aplikasi desktop Electron (lintas platform)
│ ├── main.js # Proses utama Electron
│ ├── preload.js # Skrip preload (jembatan IPC)
│ └── assets/ # Ikon dan aset aplikasi
├── tests/ # Suite pengujian
│ ├── unit/ # 122 file uji unit
│ ├── integration/ # Uji integrasi
│ ├── e2e/ # Uji E2E Playwright
│ ├── security/ # Uji keamanan
│ ├── translator/ # Uji khusus penerjemah
│ └── load/ # Uji beban
├── docs/ # Dokumentasi
│ ├── i18n/ # Dokumentasi terjemahan 30 bahasa
│ ├── ARCHITECTURE.md # Dokumentasi arsitektur lengkap
│ ├── API_REFERENCE.md # Referensi API
│ ├── USER_GUIDE.md # Panduan pengguna
│ ├── CODEBASE_DOCUMENTATION.md # Ikhtisar basis kode
│ ├── CLI-TOOLS.md # Panduan integrasi alat CLI
│ ├── A2A-SERVER.md # Dokumentasi protokol agen A2A
│ ├── AUTO-COMBO.md # Mesin auto-combo (penilaian 6-faktor)
│ ├── MCP-SERVER.md # Server MCP (29 alat)
│ ├── TROUBLESHOOTING.md # Panduan pemecahan masalah
│ ├── VM_DEPLOYMENT_GUIDE.md # Panduan penerapan VPS
│ ├── openapi.yaml # Spesifikasi OpenAPI
│ └── screenshots/ # Tangkapan layar dashboard
├── bin/ # Titik masuk CLI (omniroute, reset-password)
├── scripts/ # Skrip build dan utilitas
└── .env.example # Template variabel lingkungan
```
## Key Features (v3.8.8)
## Fitur Utama (v3.8.8)
### Core Proxy
- **177 AI providers** with automatic format translation
- **4 provider categories**: Free (5), OAuth (14), API Key (123+), Self-Hosted (8+), Custom (OpenAI/Anthropic-compatible)
- **14 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, strict-random, auto, lkgp, context-optimized, context-relay, **reset-aware** (v3.8)
- **4-tier fallback**: Subscription → API Key → Cheap → Free
- **Context Relay strategy**: Session handoff summaries on account rotation for continuity
- **Auto-combo engine**: Self-healing routing optimization with **9-factor scoring** (health/quota/costInv/latencyInv/taskFit/specificityMatch/stability/tierPriority/tierAffinity), bandit exploration, progressive cooldown
- **Semantic caching** with cache hit/miss headers
- **Idempotency** with configurable dedup window
- **3-layer resilience**: Provider Circuit Breaker / Connection Cooldown / Model Lockout
- **Provider Icons**: 130+ provider logos via `@lobehub/icons` (SVG) with PNG fallback
- **Model Auto-Sync**: 24h scheduler refreshes model lists for 16 providers
- **Registered Keys API**: Auto-provision API keys via `POST /api/v1/registered-keys` with quota enforcement
- **Memory System**: Persistent conversational memory with extraction, injection, retrieval, and summarization
- **Skills System**: Extensible skill framework with registry, executor, sandbox, built-in and custom skills
- **Cloud Agents**: Codex Cloud, Devin, Jules — autonomous coding agents with task lifecycle management
- **Guardrails Framework**: Hot-reloadable registry with vision-bridge, pii-masker, prompt-injection (priority-ordered)
- **MITM Proxy**: Certificate management, DNS handling, and target routing
- **Cloudflare Tunnels**: Managed tunnel creation for remote access
- **Coverage gate**: 75% statements/lines/functions, 70% branches (measured ~82%)
### Proxy Inti
- **177 penyedia AI** dengan translasi format otomatis
- **4 kategori penyedia**: Gratis (5), OAuth (14), Kunci API (123+), Self-Hosted (8+), Kustom (kompatibel OpenAI/Anthropic)
- **14 strategi routing**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, strict-random, auto, lkgp, context-optimized, context-relay, **reset-aware** (v3.8)
- **Fallback 4-tingkat**: Subscription → API Key → Cheap → Free
- **Strategi Context Relay**: Ringkasan handoff sesi saat rotasi akun untuk kesinambungan
- **Mesin auto-combo**: Optimasi routing self-healing dengan **penilaian 9-faktor** (health/quota/costInv/latencyInv/taskFit/specificityMatch/stability/tierPriority/tierAffinity), eksplorasi bandit, pendinginan progresif
- **Caching semantik** dengan header hit/miss cache
- **Idempotency** dengan jendela dedup yang dapat dikonfigurasi
- **Resilience 3-lapisan**: Provider Circuit Breaker / Connection Cooldown / Model Lockout
- **Ikon Penyedia**: 130+ logo penyedia via `@lobehub/icons` (SVG) dengan fallback PNG
- **Auto-Sync Model**: Penjadwal 24 jam memperbarui daftar model untuk 16 penyedia
- **API Kunci Terdaftar**: Provisioning otomatis kunci API via `POST /api/v1/registered-keys` dengan penegakan kuota
- **Sistem Memori**: Memori percakapan persisten dengan ekstraksi, injeksi, pengambilan, dan ringkasan
- **Sistem Skills**: Kerangka skill yang dapat dikembangkan dengan registri, executor, sandbox, skill bawaan dan kustom
- **Cloud Agents**: Codex Cloud, Devin, Jules — agen pengkodean otonom dengan manajemen siklus hidup tugas
- **Kerangka Guardrails**: Registri hot-reloadable dengan vision-bridge, pii-masker, prompt-injection (berurutan berdasarkan prioritas)
- **Proxy MITM**: Manajemen sertifikat, penanganan DNS, dan routing target
- **Tunnel Cloudflare**: Pembuatan tunnel terkelola untuk akses jarak jauh
- **Gerbang cakupan**: 75% statements/lines/functions, 70% branches (terukur ~82%)
### Security
- **Data Loss Prevention**: SQLite migration safety bounds abort startup on dangerous massive schema overrides. Pre-migration `VACUUM INTO` backups isolate rollback snapshots.
- **CodeQL security**: Fixed 10+ CodeQL alerts (polynomial-redos, insecure-randomness, shell-injection, SSRF, incomplete URLs)
- **Web Crypto session IDs**: `generateSessionId` uses `crypto.getRandomValues()` instead of `Math.random()`
- **Route validation**: All API routes validated with Zod v4 schemas + `validateBody()`
- **omniModel tag sanitization**: Internal `<omniModel>` tags never leak to clients in SSE streams
- **TLS Fingerprint Spoofing** — Browser-like TLS fingerprint to reduce bot detection
- **CLI Fingerprint Matching** — Per-provider request signature matching
- **Prompt injection guard** — Request middleware detection
- **Provider constants validated at module load** via Zod (`src/shared/validation/providerSchema.ts`)
- **PII sanitizer** — Sensitive data scrubbing in logs
### Keamanan
- **Pencegahan Kehilangan Data**: Batas keamanan migrasi SQLite menghentikan startup pada penggantian skema besar yang berbahaya. Backup `VACUUM INTO` pra-migrasi mengisolasi snapshot rollback.
- **Keamanan CodeQL**: Memperbaiki 10+ peringatan CodeQL (polynomial-redos, insecure-randomness, shell-injection, SSRF, URL tidak lengkap)
- **ID sesi Web Crypto**: `generateSessionId` menggunakan `crypto.getRandomValues()` alih-alih `Math.random()`
- **Validasi rute**: Semua rute API divalidasi dengan skema Zod v4 + `validateBody()`
- **Sanitasi tag omniModel**: Tag internal `<omniModel>` tidak pernah bocor ke klien dalam aliran SSE
- **Pemalsuan Sidik Jari TLS** — Sidik jari TLS seperti browser untuk mengurangi deteksi bot
- **Pencocokan Sidik Jari CLI** — Pencocokan tanda tangan permintaan per penyedia
- **Penjaga injeksi prompt** — Deteksi middleware permintaan
- **Konstanta penyedia divalidasi saat pemuatan modul** via Zod (`src/shared/validation/providerSchema.ts`)
- **Sanitizer PII** — Pembersihan data sensitif dalam log
### Dashboard Pages (23 sections)
- **Providers** — OAuth, API key, and free provider management with ProviderIcon SVG icons
- **Combos** — Multi-model combo builder with 4 templates (Free Stack, High Availability, Cost Saver, Balanced) + 14 strategies
- **Auto-Combo** — Auto-combo engine dashboard with scoring metrics
- **Analytics** — Token consumption, cost, heatmaps, distributions
- **Health** — Uptime, memory, latency percentiles, circuit breakers
- **Logs** — Request, Proxy, Audit, Console (tabbed)
- **Audit** — Audit trail and compliance logging
- **Costs** — Cost tracking per provider/model
- **Limits** — Rate limit monitoring
- **Cache** — Semantic cache statistics and management
- **CLI Tools** — One-click configuration for 10+ AI CLI tools
- **CLI Agents** — Grid of 14+ built-in agents with ProviderIcon and install detection + custom agent registration
- **Playground** — Test any model with Monaco editor, streaming responses
- **Media** — Image/video/music generation (GPT-Image, FLUX, etc.) + audio transcription (up to 2GB files)
- **Search Tools** — Search provider configuration and testing
- **Memory** — Memory system management and visualization
- **Skills** — Skills framework management and execution
- **Translator** — Format debugging: playground, chat tester, test bench, live monitor
- **Settings** — General, Appearance (7 color themes), Security (TLS/CLI fingerprint, IP filter), Routing, Resilience, Advanced
- **Endpoint** — Unified: Endpoint Proxy, MCP Server, A2A Server, API Endpoints (tabbed)
- **Onboarding** — Setup wizard for new users
- **Usage** — Usage history and analytics
- **API Manager** — API key management with scoped permissions
### Halaman Dashboard (23 bagian)
- **Providers** — Manajemen penyedia OAuth, kunci API, dan gratis dengan ikon SVG ProviderIcon
- **Combos** — Pembuat combo multi-model dengan 4 template (Free Stack, High Availability, Cost Saver, Balanced) + 14 strategi
- **Auto-Combo** — Dashboard mesin auto-combo dengan metrik penilaian
- **Analytics** — Konsumsi token, biaya, peta panas, distribusi
- **Health** — Uptime, memori, persentil latensi, circuit breaker
- **Logs** — Permintaan, Proxy, Audit, Konsol (bertab)
- **Audit** — Jejak audit dan pencatatan kepatuhan
- **Costs** — Pelacakan biaya per penyedia/model
- **Limits** — Pemantauan batas kecepatan
- **Cache** — Statistik dan manajemen cache semantik
- **CLI Tools** — Konfigurasi satu klik untuk 10+ alat CLI AI
- **CLI Agents** — Kisi 14+ agen bawaan dengan ProviderIcon dan deteksi instalasi + registrasi agen kustom
- **Playground** — Uji model apa pun dengan editor Monaco, respons streaming
- **Media** — Pembuatan gambar/video/musik (GPT-Image, FLUX, dll.) + transkripsi audio (hingga file 2GB)
- **Search Tools** — Konfigurasi dan pengujian penyedia pencarian
- **Memory** — Manajemen dan visualisasi sistem memori
- **Skills** — Manajemen dan eksekusi kerangka skills
- **Translator** — Debug format: playground, penguji chat, bangku uji, monitor langsung
- **Settings** — Umum, Tampilan (7 tema warna), Keamanan (sidik jari TLS/CLI, filter IP), Routing, Resilience, Lanjutan
- **Endpoint** — Terpadu: Endpoint Proxy, MCP Server, A2A Server, API Endpoints (bertab)
- **Onboarding** — Wizard penyiapan untuk pengguna baru
- **Usage** — Riwayat penggunaan dan analitik
- **API Manager** — Manajemen kunci API dengan izin berbasis cakupan
### Protocol Support
- **OpenAI-compatible** — `/v1/chat/completions`, `/v1/models`, `/v1/embeddings`, `/v1/images/generations`, `/v1/audio/transcriptions`, `/v1/audio/speech`, `/v1/moderations`, `/v1/rerank`, `/v1/videos/generations`, `/v1/music/generations`
### Dukungan Protokol
- **Kompatibel OpenAI** — `/v1/chat/completions`, `/v1/models`, `/v1/embeddings`, `/v1/images/generations`, `/v1/audio/transcriptions`, `/v1/audio/speech`, `/v1/moderations`, `/v1/rerank`, `/v1/videos/generations`, `/v1/music/generations`
- **Anthropic** — `/v1/messages`, `/v1/messages/count_tokens`
- **OpenAI Responses** — `/v1/responses`
- **Gemini** — `/v1beta/models`, `/v1beta/models/{...path}`
- **Ollama** — `/v1/api/chat`, `/api/tags`
- **Search** — `/v1/search` (Perplexity, Serper, Brave, Exa, Tavily)
- **MCP** — 37-tool MCP server with scope-based auth (3 transports: stdio, SSE, streamable HTTP)
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 5 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report)
- **ACP** — Agent Communication Protocol registry and manager
- **MCP** — Server MCP 37 alat dengan auth berbasis cakupan (3 transport: stdio, SSE, streamable HTTP)
- **A2A** — Protokol Agent-to-Agent v0.3 (JSON-RPC 2.0, 5 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report)
- **ACP** — Registri dan manajer Agent Communication Protocol
### MCP Server (37 Tools)
| Category | Tools |
### Server MCP (37 Alat)
| Kategori | Alat |
|------------|-------|
| Core (30) | `get_health`, `list_combos`, `get_combo_metrics`, `switch_combo`, `check_quota`, `route_request`, `cost_report`, `list_models_catalog`, `web_search`, `simulate_route`, `set_budget_guard`, `set_routing_strategy`, `set_resilience_profile`, `test_combo`, `get_provider_metrics`, `best_combo_for_task`, `explain_route`, `get_session_snapshot`, `db_health_check`, `sync_pricing`, `cache_stats`, `cache_flush`, and advanced routing/diagnostics tools (see `docs/frameworks/MCP-SERVER.md` for full inventory) |
| Memory (3) | `memory_search`, `memory_add`, `memory_clear` |
| Inti (30) | `get_health`, `list_combos`, `get_combo_metrics`, `switch_combo`, `check_quota`, `route_request`, `cost_report`, `list_models_catalog`, `web_search`, `simulate_route`, `set_budget_guard`, `set_routing_strategy`, `set_resilience_profile`, `test_combo`, `get_provider_metrics`, `best_combo_for_task`, `explain_route`, `get_session_snapshot`, `db_health_check`, `sync_pricing`, `cache_stats`, `cache_flush`, dan alat routing/diagnostik lanjutan (lihat `docs/frameworks/MCP-SERVER.md` untuk inventaris lengkap) |
| Memori (3) | `memory_search`, `memory_add`, `memory_clear` |
| Skills (4) | `skills_list`, `skills_enable`, `skills_execute`, `skills_executions` |
**MCP Auth Scopes (~13):** `read:health`, `read:combos`, `write:combos`, `read:quota`, `read:usage`, `read:models`, `execute:completions`, `execute:search`, `write:budget`, `write:resilience`, plus memory/skills scopes — full list in `docs/frameworks/MCP-SERVER.md`.
**Cakupan Auth MCP (~13):** `read:health`, `read:combos`, `write:combos`, `read:quota`, `read:usage`, `read:models`, `execute:completions`, `execute:search`, `write:budget`, `write:resilience`, ditambah cakupan memori/skills — daftar lengkap di `docs/frameworks/MCP-SERVER.md`.
### Provider Categories
### Kategori Penyedia
**Free Providers (5):** Qoder AI, Qwen Code (deprecated), Gemini CLI, Kiro AI, Windsurf
**Penyedia Gratis (5):** Qoder AI, Qwen Code (tidak digunakan lagi), Gemini CLI, Kiro AI, Windsurf
**OAuth Providers (14):** Claude Code, Antigravity, OpenAI Codex, GitHub Copilot, Cursor IDE, Kimi Coding, Kilo Code, Cline, Qwen, Kiro, Qoder, Gemini, Windsurf, GitLab Duo
**Penyedia OAuth (14):** Claude Code, Antigravity, OpenAI Codex, GitHub Copilot, Cursor IDE, Kimi Coding, Kilo Code, Cline, Qwen, Kiro, Qoder, Gemini, Windsurf, GitLab Duo
**API Key Providers (48+):** OpenAI, Anthropic, Gemini (Google AI Studio), DeepSeek, Groq, xAI (Grok), Mistral, Perplexity, Together AI, Fireworks AI, Cerebras, Cohere, NVIDIA NIM, Nebius AI, SiliconFlow, Hyperbolic, HuggingFace, OpenRouter, Vertex AI, Cloudflare Workers AI, Scaleway AI, AI/ML API, Pollinations AI, Puter AI, LongCat AI, Alibaba, Alibaba (China), Kimi, Kimi Coding (API Key), Minimax, Minimax (China), Blackbox AI, Synthetic, Kilo Gateway, Z.AI, GLM Coding, Deepgram, AssemblyAI, ElevenLabs, Cartesia, PlayHT, Inworld, NanoBanana, SD WebUI, ComfyUI, Ollama Cloud, Perplexity Search, Serper Search, Brave Search, Exa Search, Tavily Search, OpenCode Zen, OpenCode Go, Alibaba Coding Plan
**Penyedia Kunci API (48+):** OpenAI, Anthropic, Gemini (Google AI Studio), DeepSeek, Groq, xAI (Grok), Mistral, Perplexity, Together AI, Fireworks AI, Cerebras, Cohere, NVIDIA NIM, Nebius AI, SiliconFlow, Hyperbolic, HuggingFace, OpenRouter, Vertex AI, Cloudflare Workers AI, Scaleway AI, AI/ML API, Pollinations AI, Puter AI, LongCat AI, Alibaba, Alibaba (China), Kimi, Kimi Coding (API Key), Minimax, Minimax (China), Blackbox AI, Synthetic, Kilo Gateway, Z.AI, GLM Coding, Deepgram, AssemblyAI, ElevenLabs, Cartesia, PlayHT, Inworld, NanoBanana, SD WebUI, ComfyUI, Ollama Cloud, Perplexity Search, Serper Search, Brave Search, Exa Search, Tavily Search, OpenCode Zen, OpenCode Go, Alibaba Coding Plan
**Custom Providers:** OpenAI-compatible (`openai-compatible-*`) and Anthropic-compatible (`anthropic-compatible-*`) with custom base URLs
**Penyedia Kustom:** Kompatibel OpenAI (`openai-compatible-*`) dan kompatibel Anthropic (`anthropic-compatible-*`) dengan URL dasar kustom
### Internationalization
- 40+ languages for UI (all dashboard pages)
- 40 translated documentation sets in docs/i18n/
- Language switcher in documentation
### Internasionalisasi
- 40+ bahasa untuk UI (semua halaman dashboard)
- 40 set dokumentasi terjemahan di docs/i18n/
- Pemilih bahasa dalam dokumentasi
## Key Architectural Decisions
## Keputusan Arsitektur Utama
1. **OpenAI-compatible API surface:** All incoming requests follow the OpenAI API format. This makes OmniRoute a drop-in replacement for any tool that supports custom OpenAI endpoints.
1. **Permukaan API kompatibel OpenAI:** Semua permintaan masuk mengikuti format OpenAI API. Ini menjadikan OmniRoute sebagai pengganti langsung untuk alat apa pun yang mendukung endpoint OpenAI kustom.
2. **Provider abstraction via format translators:** Each AI provider has a translator in `open-sse/translator/` that converts between OpenAI format and the provider's native format transparently.
2. **Abstraksi penyedia via penerjemah format:** Setiap penyedia AI memiliki penerjemah di `open-sse/translator/` yang mengkonversi antara format OpenAI dan format asli penyedia secara transparan.
3. **Connection-based provider model:** Providers are stored as "connections" in SQLite. Each connection has an `id`, `provider`, `authType` (oauth/apikey/free), `isActive` flag, and credentials. Multiple connections per provider for multi-account rotation.
3. **Model penyedia berbasis koneksi:** Penyedia disimpan sebagai "koneksi" di SQLite. Setiap koneksi memiliki `id`, `provider`, `authType` (oauth/apikey/free), flag `isActive`, dan kredensial. Beberapa koneksi per penyedia untuk rotasi multi-akun.
4. **Combo system for fallback:** Users create "combos" — ordered lists of `provider/model` pairs. The proxy tries each in order until one succeeds. Supports 14 strategies including auto-combo with self-healing and context-relay for session continuity.
4. **Sistem combo untuk fallback:** Pengguna membuat "combo" — daftar terurut pasangan `provider/model`. Proxy mencoba setiap pasangan secara berurutan hingga salah satu berhasil. Mendukung 14 strategi termasuk auto-combo dengan self-healing dan context-relay untuk kesinambungan sesi.
5. **SSE proxy pipeline:** The proxy pipeline is middleware-based: request → auth resolution → rate limiting → circuit breaker → format translation → upstream call → response translation → SSE streaming back to client.
5. **Pipeline proxy SSE:** Pipeline proxy berbasis middleware: permintaan → resolusi auth → pembatasan kecepatan → circuit breaker → translasi format → panggilan upstream → translasi respons → SSE streaming kembali ke klien.
6. **SQLite for persistence:** All state (providers, combos, logs, settings, API keys, memory, skills) stored in a single SQLite database via 21 domain-specific modules. All DB operations go through `src/lib/db/` modules, never raw SQL in routes.
6. **SQLite untuk persistensi:** Semua state (penyedia, combo, log, pengaturan, kunci API, memori, skills) disimpan dalam satu database SQLite via 21 modul domain-spesifik. Semua operasi DB melewati modul `src/lib/db/`, bukan SQL mentah di rute.
7. **OAuth with PKCE:** OAuth flows use PKCE for security. Token refresh handled by background job (`tokenHealthCheck.ts`).
7. **OAuth dengan PKCE:** Alur OAuth menggunakan PKCE untuk keamanan. Refresh token ditangani oleh pekerjaan latar belakang (`tokenHealthCheck.ts`).
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
8. **Komponen ProviderIcon:** Sistem ikon terpadu menggunakan `@lobehub/icons` (130+ SVG) dengan fallback PNG dan rantai fallback ikon generik. Digunakan di halaman penyedia, dashboard, dan agen.
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 21 `src/lib/db/` modules with 16 SQL migrations.
9. **Arsitektur DB:** `localDb.ts` hanya merupakan lapisan re-ekspor — logika nyata ada di 21 modul `src/lib/db/` dengan 16 migrasi SQL.
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
10. **Header upstream:** Header kustom digabungkan di executor setelah auth default; nama header yang sama menggantikan nilai executor. Nama header yang dilarang ada di `src/shared/constants/upstreamHeaders.ts`.
11. **Memory/Skills cross-cutting systems:** Memory and Skills affect the MCP tools, request pipeline, and A2A skills. Memory provides persistent context across sessions; Skills provide extensible tool execution with sandbox isolation.
11. **Sistem lintas-bidang Memory/Skills:** Memory dan Skills mempengaruhi alat MCP, pipeline permintaan, dan skills A2A. Memory menyediakan konteks persisten lintas sesi; Skills menyediakan eksekusi alat yang dapat dikembangkan dengan isolasi sandbox.
12. **Domain policy engine:** `src/domain/` contains policy engine modules (policyEngine, comboResolver, costRules, degradation, fallbackPolicy, lockoutPolicy, modelAvailability, providerExpiration, quotaCache, configAudit) that govern routing decisions independently from the pipeline.
12. **Mesin kebijakan domain:** `src/domain/` berisi modul mesin kebijakan (policyEngine, comboResolver, costRules, degradation, fallbackPolicy, lockoutPolicy, modelAvailability, providerExpiration, quotaCache, configAudit) yang mengatur keputusan routing secara independen dari pipeline.
13. **Provider constants validated at load:** All provider definitions validated via Zod schemas at module load time (`src/shared/validation/providerSchema.ts`). Invalid providers fail fast.
13. **Konstanta penyedia divalidasi saat pemuatan:** Semua definisi penyedia divalidasi via skema Zod saat waktu pemuatan modul (`src/shared/validation/providerSchema.ts`). Penyedia yang tidak valid gagal dengan cepat.
## Main Flows
## Alur Utama
### Proxy Request Flow
1. Client sends OpenAI-format request to `/v1/chat/completions`
2. API key validation
3. Model resolution: direct model or combo lookup
4. For combos: iterate through models with selected strategy
5. Auth resolution: get credentials for the target provider
6. Format translation: OpenAI → provider native format
7. CLI fingerprint matching (if enabled for provider)
8. Upstream request with circuit breaker and rate limiting
9. Response translation: provider → OpenAI format
10. omniModel tag sanitization (strip internal tags)
11. SSE streaming back to client
12. Memory extraction (if memory system enabled)
13. Usage logging and cost calculation
### Alur Permintaan Proxy
1. Klien mengirim permintaan format OpenAI ke `/v1/chat/completions`
2. Validasi kunci API
3. Resolusi model: pencarian model langsung atau combo
4. Untuk combo: iterasi melalui model dengan strategi yang dipilih
5. Resolusi auth: mendapatkan kredensial untuk penyedia target
6. Translasi format: OpenAI → format asli penyedia
7. Pencocokan sidik jari CLI (jika diaktifkan untuk penyedia)
8. Permintaan upstream dengan circuit breaker dan pembatasan kecepatan
9. Translasi respons: penyedia → format OpenAI
10. Sanitasi tag omniModel (hapus tag internal)
11. SSE streaming kembali ke klien
12. Ekstraksi memori (jika sistem memori diaktifkan)
13. Pencatatan penggunaan dan perhitungan biaya
### OAuth Flow
1. Dashboard initiates `/api/oauth/[provider]/authorize`
2. User completes OAuth login in browser
3. Callback hits `/api/oauth/[provider]/exchange`
4. Tokens stored as a provider connection in SQLite
5. Background job refreshes tokens before expiry
### Alur OAuth
1. Dashboard memulai `/api/oauth/[provider]/authorize`
2. Pengguna menyelesaikan login OAuth di browser
3. Callback menyentuh `/api/oauth/[provider]/exchange`
4. Token disimpan sebagai koneksi penyedia di SQLite
5. Pekerjaan latar belakang memperbarui token sebelum kedaluwarsa
## Important Notes for LLMs
## Catatan Penting untuk LLM
1. **Two model endpoints exist:** `/api/models` (dashboard, all models) and `/v1/models` (OpenAI-compatible, active only).
1. **Dua endpoint model tersedia:** `/api/models` (dashboard, semua model) dan `/v1/models` (kompatibel OpenAI, hanya aktif).
2. **Provider IDs vs aliases:** Providers have both an ID (`claude`, `github`) and a short alias (`cc`, `gh`). Models are referenced as `alias/model-name` (e.g., `cc/claude-opus-4-6`).
2. **ID penyedia vs alias:** Penyedia memiliki ID (`claude`, `github`) dan alias pendek (`cc`, `gh`). Model direferensikan sebagai `alias/model-name` (mis., `cc/claude-opus-4-6`).
3. **The `open-sse/` directory is a separate npm workspace** with its own config, handlers, executors, translators, and services.
3. **Direktori `open-sse/` adalah workspace npm terpisah** dengan konfigurasi, handler, executor, penerjemah, dan layanannya sendiri.
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
4. **Variabel lingkungan:** Semua konfigurasi ada di `.env` (dari `.env.example`). Variabel kunci: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
5. **Database layer:** Operations go through `src/lib/db/` modules (45+ domain-specific files, 55 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
5. **Lapisan database:** Operasi melewati modul `src/lib/db/` (45+ file domain-spesifik, 55 migrasi). `localDb.ts` hanya re-ekspor — tambahkan fungsi baru ke modul `db/*.ts` yang sesuai.
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: 75% statements/lines/functions, 70% branches.
6. **Pengujian** menggunakan runner bawaan Node.js + Vitest. Jalankan `npm test`. Vitest untuk MCP/autoCombo (`npm run test:vitest`). Playwright untuk E2E (`npm run test:e2e`). Gerbang cakupan: 75% statements/lines/functions, 70% branches.
7. **MCP and A2A pages are embedded as tabs inside `/dashboard/endpoint`**, not standalone routes.
7. **Halaman MCP dan A2A disematkan sebagai tab di dalam `/dashboard/endpoint`**, bukan rute mandiri.
8. **ACP agents** are in `src/lib/acp/registry.ts` with detection cache. Custom agents stored via settings DB.
8. **Agen ACP** ada di `src/lib/acp/registry.ts` dengan cache deteksi. Agen kustom disimpan via DB pengaturan.
9. **Auto-combo engine** in `open-sse/services/autoCombo/` — **9-factor scoring** (health 0.22, quota 0.17, costInv 0.17, latencyInv 0.13, taskFit 0.08, specificityMatch 0.08, stability 0.05, tierPriority 0.05, tierAffinity 0.05), 4 mode packs, bandit exploration, progressive cooldown.
9. **Mesin auto-combo** di `open-sse/services/autoCombo/` — **penilaian 9-faktor** (health 0.22, quota 0.17, costInv 0.17, latencyInv 0.13, taskFit 0.08, specificityMatch 0.08, stability 0.05, tierPriority 0.05, tierAffinity 0.05), 4 paket mode, eksplorasi bandit, pendinginan progresif.
10. **Docker:** Dockerfile has two targets: `runner-base` and `runner-cli`. `docker-compose.yml` for dev (3 profiles), `docker-compose.prod.yml` for production (port 20130).
10. **Docker:** Dockerfile memiliki dua target: `runner-base` dan `runner-cli`. `docker-compose.yml` untuk dev (3 profil), `docker-compose.prod.yml` untuk produksi (port 20130).
11. **Electron desktop app** in `electron/` with main.js and preload.js. Build with `npm run electron:build` (supports Windows, macOS, Linux).
11. **Aplikasi desktop Electron** di `electron/` dengan main.js dan preload.js. Build dengan `npm run electron:build` (mendukung Windows, macOS, Linux).
12. **Pricing data** syncs from LiteLLM via `src/lib/pricingSync.ts`. Use `sync_pricing` MCP tool or API endpoint.
12. **Data harga** disinkronkan dari LiteLLM via `src/lib/pricingSync.ts`. Gunakan alat MCP `sync_pricing` atau endpoint API.
13. **Memory system** in `src/lib/memory/` provides extraction, injection, retrieval, summarization, and persistent store. Exposed via MCP memory tools and `/api/memory/ API.
13. **Sistem memori** di `src/lib/memory/` menyediakan ekstraksi, injeksi, pengambilan, ringkasan, dan penyimpanan persisten. Diekspos via alat memori MCP dan API `/api/memory/`.
14. **Skills system** in `src/lib/skills/` provides registry, executor, sandbox isolation, built-in skills, custom skill support, request interception, and context injection. Exposed via MCP skill tools and `/api/skills/` API.
14. **Sistem skills** di `src/lib/skills/` menyediakan registri, executor, isolasi sandbox, skill bawaan, dukungan skill kustom, intersepsi permintaan, dan injeksi konteks. Diekspos via alat skill MCP dan API `/api/skills/`.
15. **Zod v4** is used for all validation. Import from `zod` package. Provider schemas validated at module load time.
15. **Zod v4** digunakan untuk semua validasi. Impor dari paket `zod`. Skema penyedia divalidasi saat waktu pemuatan modul.
16. **Context Relay** strategy (`context-relay`) is split across two layers: `combo.ts` decides if a handoff should be generated after a successful turn; `chat.ts` injects the handoff only after account resolution. Handoff data lives in `context_handoffs` SQLite table. Config: `handoffThreshold`, `handoffModel`, `handoffProviders`.
16. **Strategi Context Relay** (`context-relay`) dibagi ke dua lapisan: `combo.ts` memutuskan apakah handoff harus dibuat setelah giliran yang berhasil; `chat.ts` menyuntikkan handoff hanya setelah resolusi akun. Data handoff tersimpan di tabel SQLite `context_handoffs`. Konfigurasi: `handoffThreshold`, `handoffModel`, `handoffProviders`.
17. **Proxy enforcement** is now comprehensive: token health checks resolve proxy per connection, provider validation wraps in `runWithProxyContext`, and proxy dispatchers use `undici.fetch()` instead of the Node built-in `fetch()` to avoid dispatcher incompatibilities on Node 22.
17. **Penegakan proxy** kini komprehensif: pemeriksaan kesehatan token menyelesaikan proxy per koneksi, validasi penyedia dibungkus dalam `runWithProxyContext`, dan dispatcher proxy menggunakan `undici.fetch()` alih-alih `fetch()` bawaan Node untuk menghindari ketidakcocokan dispatcher di Node 22.
18. **Node.js 24+ compatibility**: The login page (`/api/settings/require-login`) detects the Node.js version and sends `nodeVersion`/`nodeCompatible` fields. The login UI renders a warning banner when `nodeCompatible` is false.
18. **Kompatibilitas Node.js 24+**: Halaman login (`/api/settings/require-login`) mendeteksi versi Node.js dan mengirim field `nodeVersion`/`nodeCompatible`. UI login merender banner peringatan ketika `nodeCompatible` bernilai false.
19. **Cloud Agents** in `src/lib/cloudAgent/` — three external autonomous coding agents (Codex Cloud, Devin, Jules) with task lifecycle endpoints under `/api/v1/agents/tasks/`. Require management auth, not client auth.
19. **Cloud Agents** di `src/lib/cloudAgent/` — tiga agen pengkodean otonom eksternal (Codex Cloud, Devin, Jules) dengan endpoint siklus hidup tugas di bawah `/api/v1/agents/tasks/`. Memerlukan auth manajemen, bukan auth klien.
20. **Guardrails framework** in `src/lib/guardrails/` — hot-reloadable registry. Built-ins (priority-ordered): `vision-bridge` (5) → `pii-masker` (10) → `prompt-injection` (20). Fail-open model: exceptions never block traffic. Per-request opt-out via `x-omniroute-disabled-guardrails` header.
20. **Kerangka Guardrails** di `src/lib/guardrails/` — registri hot-reloadable. Bawaan (berurutan berdasarkan prioritas): `vision-bridge` (5) → `pii-masker` (10) → `prompt-injection` (20). Model fail-open: pengecualian tidak pernah memblokir lalu lintas. Penonaktifan per-permintaan via header `x-omniroute-disabled-guardrails`.
21. **Authz pipeline** (`src/server/authz/`): every request is classified as `PUBLIC`, `CLIENT_API`, or `MANAGEMENT`, then run through policy + enforce stages. See `docs/architecture/AUTHZ_GUIDE.md`.
21. **Pipeline Authz** (`src/server/authz/`): setiap permintaan diklasifikasikan sebagai `PUBLIC`, `CLIENT_API`, atau `MANAGEMENT`, kemudian dijalankan melalui tahap kebijakan + penerapan. Lihat `docs/architecture/AUTHZ_GUIDE.md`.
22. **Three resilience layers** are distinct (do not conflate them):
- **Provider Circuit Breaker** (`src/shared/utils/circuitBreaker.ts`) — whole-provider scope.
- **Connection Cooldown** (`src/sse/services/auth.ts::markAccountUnavailable`) — one key/account scope.
- **Model Lockout** (`open-sse/services/accountFallback.ts`) — provider + connection + model scope.
22. **Tiga lapisan resilience** berbeda (jangan mencampuradukkan):
- **Provider Circuit Breaker** (`src/shared/utils/circuitBreaker.ts`) — cakupan seluruh penyedia.
- **Connection Cooldown** (`src/sse/services/auth.ts::markAccountUnavailable`) — cakupan satu kunci/akun.
- **Model Lockout** (`open-sse/services/accountFallback.ts`) — cakupan penyedia + koneksi + model.
## v3.8.0 Highlights
## Sorotan v3.8.0
- **Cloud Agents** (Codex Cloud, Devin, Jules) with task lifecycle management and management-auth enforcement
- **Guardrails framework**: hot-reloadable registry with vision-bridge, pii-masker, prompt-injection
- **9-factor Auto-Combo scoring** (was 6-factor in earlier versions)
- **`reset-aware` routing strategy** (14th strategy) — picks the account whose quota will reset soonest
- **A2A protocol expanded to 5 skills**: smart-routing, quota-management, provider-discovery, cost-analysis, health-report
- **MCP server expanded to 37 tools** (30 base + 3 memory + 4 skills) across ~13 scopes
- **OAuth providers expanded to 14**: added Qwen, Kiro, Qoder, Gemini, Windsurf, GitLab Duo
- **Coverage gate raised to 75/75/75/70** (was 60% across the board) — measured ~82%
- **Reasoning replay** (`docs/routing/REASONING_REPLAY.md`) — capture and inspect provider reasoning streams
- **Compliance + Evals + Webhooks** documentation introduced
- **Stealth guide** (`docs/security/STEALTH_GUIDE.md`) — TLS / CLI fingerprint configuration
- **Tunnels guide** (`docs/ops/TUNNELS_GUIDE.md`) — Cloudflare tunnel management
- **Electron guide** (`docs/guides/ELECTRON_GUIDE.md`) — desktop app build + signing
- **Cloud Agents** (Codex Cloud, Devin, Jules) dengan manajemen siklus hidup tugas dan penegakan auth manajemen
- **Kerangka Guardrails**: registri hot-reloadable dengan vision-bridge, pii-masker, prompt-injection
- **Penilaian Auto-Combo 9-faktor** (sebelumnya 6-faktor pada versi sebelumnya)
- **Strategi routing `reset-aware`** (strategi ke-14) — memilih akun yang kuotanya akan segera direset
- **Protokol A2A diperluas ke 5 skills**: smart-routing, quota-management, provider-discovery, cost-analysis, health-report
- **Server MCP diperluas ke 37 alat** (30 dasar + 3 memori + 4 skills) di ~13 cakupan
- **Penyedia OAuth diperluas ke 14**: menambahkan Qwen, Kiro, Qoder, Gemini, Windsurf, GitLab Duo
- **Gerbang cakupan dinaikkan ke 75/75/75/70** (sebelumnya 60% di semua bagian) — terukur ~82%
- **Replay penalaran** (`docs/routing/REASONING_REPLAY.md`) — tangkap dan periksa aliran penalaran penyedia
- **Dokumentasi Compliance + Evals + Webhooks** diperkenalkan
- **Panduan stealth** (`docs/security/STEALTH_GUIDE.md`) — konfigurasi sidik jari TLS / CLI
- **Panduan tunnel** (`docs/ops/TUNNELS_GUIDE.md`) — manajemen tunnel Cloudflare
- **Panduan Electron** (`docs/guides/ELECTRON_GUIDE.md`) — build + penandatanganan aplikasi desktop
## Links
## Tautan
- Repository: https://github.com/diegosouzapw/OmniRoute
- Website: https://omniroute.online
- Repositori: https://github.com/diegosouzapw/OmniRoute
- Situs web: https://omniroute.online
- npm: https://www.npmjs.com/package/omniroute
- Docker Hub: https://hub.docker.com/r/diegosouzapw/omniroute
- Documentation: See `/docs/` directory
- Dokumentasi: Lihat direktori `/docs/`
### Documentation Index
### Indeks Dokumentasi
- **Architecture & Reference**: `docs/architecture/ARCHITECTURE.md`, `docs/architecture/CODEBASE_DOCUMENTATION.md`, `docs/architecture/REPOSITORY_MAP.md`, `docs/reference/API_REFERENCE.md`, `docs/reference/PROVIDER_REFERENCE.md`, `docs/reference/openapi.yaml`
- **Operator guides**: `docs/guides/USER_GUIDE.md`, `docs/reference/CLI-TOOLS.md`, `docs/guides/TROUBLESHOOTING.md`, `docs/ops/COVERAGE_PLAN.md`
- **Protocols**: `docs/frameworks/MCP-SERVER.md`, `docs/frameworks/A2A-SERVER.md`, `docs/frameworks/AGENT_PROTOCOLS_GUIDE.md`, `docs/frameworks/CLOUD_AGENT.md`
- **Arsitektur & Referensi**: `docs/architecture/ARCHITECTURE.md`, `docs/architecture/CODEBASE_DOCUMENTATION.md`, `docs/architecture/REPOSITORY_MAP.md`, `docs/reference/API_REFERENCE.md`, `docs/reference/PROVIDER_REFERENCE.md`, `docs/reference/openapi.yaml`
- **Panduan operator**: `docs/guides/USER_GUIDE.md`, `docs/reference/CLI-TOOLS.md`, `docs/guides/TROUBLESHOOTING.md`, `docs/ops/COVERAGE_PLAN.md`
- **Protokol**: `docs/frameworks/MCP-SERVER.md`, `docs/frameworks/A2A-SERVER.md`, `docs/frameworks/AGENT_PROTOCOLS_GUIDE.md`, `docs/frameworks/CLOUD_AGENT.md`
- **Routing & resilience**: `docs/routing/AUTO-COMBO.md`, `docs/architecture/RESILIENCE_GUIDE.md`
- **Security**: `docs/architecture/AUTHZ_GUIDE.md`, `docs/security/GUARDRAILS.md`, `docs/security/COMPLIANCE.md`, `docs/security/STEALTH_GUIDE.md`
- **Extensibility**: `docs/frameworks/SKILLS.md`, `docs/frameworks/MEMORY.md`, `docs/frameworks/EVALS.md`, `docs/frameworks/WEBHOOKS.md`, `docs/routing/REASONING_REPLAY.md`
- **Keamanan**: `docs/architecture/AUTHZ_GUIDE.md`, `docs/security/GUARDRAILS.md`, `docs/security/COMPLIANCE.md`, `docs/security/STEALTH_GUIDE.md`
- **Ekstensibilitas**: `docs/frameworks/SKILLS.md`, `docs/frameworks/MEMORY.md`, `docs/frameworks/EVALS.md`, `docs/frameworks/WEBHOOKS.md`, `docs/routing/REASONING_REPLAY.md`
- **Platform**: `docs/guides/ELECTRON_GUIDE.md`, `docs/ops/TUNNELS_GUIDE.md`
- **AI agents**: `CLAUDE.md`, `AGENTS.md`, `GEMINI.md`
- **Agen AI**: `CLAUDE.md`, `AGENTS.md`, `GEMINI.md`