# API Reference (Bahasa Melayu) 🌐 **Languages:** 🇺🇸 [English](../../../../reference/API_REFERENCE.md) · 🇪🇹 [am](../../../am/docs/reference/API_REFERENCE.md) · 🇸🇦 [ar](../../../ar/docs/reference/API_REFERENCE.md) · 🇦🇿 [az](../../../az/docs/reference/API_REFERENCE.md) · 🇧🇬 [bg](../../../bg/docs/reference/API_REFERENCE.md) · 🇧🇩 [bn](../../../bn/docs/reference/API_REFERENCE.md) · 🇧🇦 [bs](../../../bs/docs/reference/API_REFERENCE.md) · 🇨🇿 [cs](../../../cs/docs/reference/API_REFERENCE.md) · 🇩🇰 [da](../../../da/docs/reference/API_REFERENCE.md) · 🇩🇪 [de](../../../de/docs/reference/API_REFERENCE.md) · 🇬🇷 [el](../../../el/docs/reference/API_REFERENCE.md) · 🇪🇸 [es](../../../es/docs/reference/API_REFERENCE.md) · 🇪🇪 [et](../../../et/docs/reference/API_REFERENCE.md) · 🇮🇷 [fa](../../../fa/docs/reference/API_REFERENCE.md) · 🇫🇮 [fi](../../../fi/docs/reference/API_REFERENCE.md) · 🇫🇷 [fr](../../../fr/docs/reference/API_REFERENCE.md) · 🇮🇪 [ga](../../../ga/docs/reference/API_REFERENCE.md) · 🇮🇳 [gu](../../../gu/docs/reference/API_REFERENCE.md) · 🇳🇬 [ha](../../../ha/docs/reference/API_REFERENCE.md) · 🇮🇱 [he](../../../he/docs/reference/API_REFERENCE.md) · 🇮🇳 [hi](../../../hi/docs/reference/API_REFERENCE.md) · 🇭🇷 [hr](../../../hr/docs/reference/API_REFERENCE.md) · 🇭🇺 [hu](../../../hu/docs/reference/API_REFERENCE.md) · 🇦🇲 [hy](../../../hy/docs/reference/API_REFERENCE.md) · 🇮🇩 [id](../../../id/docs/reference/API_REFERENCE.md) · 🇳🇬 [ig](../../../ig/docs/reference/API_REFERENCE.md) · 🇮🇹 [it](../../../it/docs/reference/API_REFERENCE.md) · 🇯🇵 [ja](../../../ja/docs/reference/API_REFERENCE.md) · 🇬🇪 [ka](../../../ka/docs/reference/API_REFERENCE.md) · 🇰🇭 [km](../../../km/docs/reference/API_REFERENCE.md) · 🇮🇳 [kn](../../../kn/docs/reference/API_REFERENCE.md) · 🇰🇷 [ko](../../../ko/docs/reference/API_REFERENCE.md) · 🇱🇹 [lt](../../../lt/docs/reference/API_REFERENCE.md) · 🇱🇻 [lv](../../../lv/docs/reference/API_REFERENCE.md) · 🇮🇳 [ml](../../../ml/docs/reference/API_REFERENCE.md) · 🇮🇳 [mr](../../../mr/docs/reference/API_REFERENCE.md) · 🇲🇹 [mt](../../../mt/docs/reference/API_REFERENCE.md) · 🇲🇲 [my](../../../my/docs/reference/API_REFERENCE.md) · 🇳🇵 [ne](../../../ne/docs/reference/API_REFERENCE.md) · 🇳🇱 [nl](../../../nl/docs/reference/API_REFERENCE.md) · 🇳🇴 [no](../../../no/docs/reference/API_REFERENCE.md) · 🇮🇳 [or](../../../or/docs/reference/API_REFERENCE.md) · 🇮🇳 [pa](../../../pa/docs/reference/API_REFERENCE.md) · 🇵🇭 [phi](../../../phi/docs/reference/API_REFERENCE.md) · 🇵🇱 [pl](../../../pl/docs/reference/API_REFERENCE.md) · 🇵🇹 [pt](../../../pt/docs/reference/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/reference/API_REFERENCE.md) · 🇷🇴 [ro](../../../ro/docs/reference/API_REFERENCE.md) · 🇷🇺 [ru](../../../ru/docs/reference/API_REFERENCE.md) · 🇱🇰 [si](../../../si/docs/reference/API_REFERENCE.md) · 🇸🇰 [sk](../../../sk/docs/reference/API_REFERENCE.md) · 🇸🇮 [sl](../../../sl/docs/reference/API_REFERENCE.md) · 🇷🇸 [sr](../../../sr/docs/reference/API_REFERENCE.md) · 🇸🇪 [sv](../../../sv/docs/reference/API_REFERENCE.md) · 🇰🇪 [sw](../../../sw/docs/reference/API_REFERENCE.md) · 🇮🇳 [ta](../../../ta/docs/reference/API_REFERENCE.md) · 🇮🇳 [te](../../../te/docs/reference/API_REFERENCE.md) · 🇹🇭 [th](../../../th/docs/reference/API_REFERENCE.md) · 🇹🇷 [tr](../../../tr/docs/reference/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/reference/API_REFERENCE.md) · 🇵🇰 [ur](../../../ur/docs/reference/API_REFERENCE.md) · 🇺🇿 [uz](../../../uz/docs/reference/API_REFERENCE.md) · 🇻🇳 [vi](../../../vi/docs/reference/API_REFERENCE.md) · 🇳🇬 [yo](../../../yo/docs/reference/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/reference/API_REFERENCE.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/reference/API_REFERENCE.md) --- 🌐 **Bahasa:** 🇺🇸 [English](./API_REFERENCE.md) | 🇪🇹 [አማርኛ](../i18n/am/docs/reference/API_REFERENCE.md) | 🇸🇦 [العربية](../i18n/ar/docs/reference/API_REFERENCE.md) | 🇦🇿 [Azərbaycan dili](../i18n/az/docs/reference/API_REFERENCE.md) | 🇧🇬 [Български](../i18n/bg/docs/reference/API_REFERENCE.md) | 🇧🇩 [বাংলা](../i18n/bn/docs/reference/API_REFERENCE.md) | 🇧🇦 [Bosanski](../i18n/bs/docs/reference/API_REFERENCE.md) | 🇨🇿 [Čeština](../i18n/cs/docs/reference/API_REFERENCE.md) | 🇩🇰 [Dansk](../i18n/da/docs/reference/API_REFERENCE.md) | 🇩🇪 [Deutsch](../i18n/de/docs/reference/API_REFERENCE.md) | 🇬🇷 [Ελληνικά](../i18n/el/docs/reference/API_REFERENCE.md) | 🇪🇸 [Español](../i18n/es/docs/reference/API_REFERENCE.md) | 🇪🇪 [Eesti](../i18n/et/docs/reference/API_REFERENCE.md) | 🇮🇷 [فارسی](../i18n/fa/docs/reference/API_REFERENCE.md) | 🇫🇮 [Suomi](../i18n/fi/docs/reference/API_REFERENCE.md) | 🇫🇷 [Français](../i18n/fr/docs/reference/API_REFERENCE.md) | 🇮🇪 [Gaeilge](../i18n/ga/docs/reference/API_REFERENCE.md) | 🇮🇳 [ગુજરાતી](../i18n/gu/docs/reference/API_REFERENCE.md) | 🇳🇬 [Hausa](../i18n/ha/docs/reference/API_REFERENCE.md) | 🇮🇱 [עברית](../i18n/he/docs/reference/API_REFERENCE.md) | 🇮🇳 [हिन्दी](../i18n/hi/docs/reference/API_REFERENCE.md) | 🇭🇷 [Hrvatski](../i18n/hr/docs/reference/API_REFERENCE.md) | 🇭🇺 [Magyar](../i18n/hu/docs/reference/API_REFERENCE.md) | 🇦🇲 [Հայերեն](../i18n/hy/docs/reference/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](../i18n/id/docs/reference/API_REFERENCE.md) | 🇳🇬 [Igbo](../i18n/ig/docs/reference/API_REFERENCE.md) | 🇮🇹 [Italiano](../i18n/it/docs/reference/API_REFERENCE.md) | 🇯🇵 [日本語](../i18n/ja/docs/reference/API_REFERENCE.md) | 🇬🇪 [ქართული](../i18n/ka/docs/reference/API_REFERENCE.md) | 🇰🇭 [ខ្មែរ](../i18n/km/docs/reference/API_REFERENCE.md) | 🇮🇳 [ಕನ್ನಡ](../i18n/kn/docs/reference/API_REFERENCE.md) | 🇰🇷 [한국어](../i18n/ko/docs/reference/API_REFERENCE.md) | 🇱🇹 [Lietuvių](../i18n/lt/docs/reference/API_REFERENCE.md) | 🇱🇻 [Latviešu](../i18n/lv/docs/reference/API_REFERENCE.md) | 🇮🇳 [മലയാളം](../i18n/ml/docs/reference/API_REFERENCE.md) | 🇮🇳 [मराठी](../i18n/mr/docs/reference/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](../i18n/ms/docs/reference/API_REFERENCE.md) | 🇲🇹 [Malti](../i18n/mt/docs/reference/API_REFERENCE.md) | 🇲🇲 [မြန်မာ](../i18n/my/docs/reference/API_REFERENCE.md) | 🇳🇵 [नेपाली](../i18n/ne/docs/reference/API_REFERENCE.md) | 🇳🇱 [Nederlands](../i18n/nl/docs/reference/API_REFERENCE.md) | 🇳🇴 [Norsk](../i18n/no/docs/reference/API_REFERENCE.md) | 🇮🇳 [ଓଡ଼ିଆ](../i18n/or/docs/reference/API_REFERENCE.md) | 🇮🇳 [ਪੰਜਾਬੀ](../i18n/pa/docs/reference/API_REFERENCE.md) | 🇵🇭 [Filipino](../i18n/phi/docs/reference/API_REFERENCE.md) | 🇵🇱 [Polski](../i18n/pl/docs/reference/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](../i18n/pt/docs/reference/API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](../i18n/pt-BR/docs/reference/API_REFERENCE.md) | 🇷🇴 [Română](../i18n/ro/docs/reference/API_REFERENCE.md) | 🇷🇺 [Русский](../i18n/ru/docs/reference/API_REFERENCE.md) | 🇱🇰 [සිංහල](../i18n/si/docs/reference/API_REFERENCE.md) | 🇸🇰 [Slovenčina](../i18n/sk/docs/reference/API_REFERENCE.md) | 🇸🇮 [Slovenščina](../i18n/sl/docs/reference/API_REFERENCE.md) | 🇷🇸 [Српски](../i18n/sr/docs/reference/API_REFERENCE.md) | 🇸🇪 [Svenska](../i18n/sv/docs/reference/API_REFERENCE.md) | 🇰🇪 [Kiswahili](../i18n/sw/docs/reference/API_REFERENCE.md) | 🇮🇳 [தமிழ்](../i18n/ta/docs/reference/API_REFERENCE.md) | 🇮🇳 [తెలుగు](../i18n/te/docs/reference/API_REFERENCE.md) | 🇹🇭 [ไทย](../i18n/th/docs/reference/API_REFERENCE.md) | 🇹🇷 [Türkçe](../i18n/tr/docs/reference/API_REFERENCE.md) | 🇺🇦 [Українська](../i18n/uk-UA/docs/reference/API_REFERENCE.md) | 🇵🇰 [اردو](../i18n/ur/docs/reference/API_REFERENCE.md) | 🇺🇿 [Oʻzbekcha](../i18n/uz/docs/reference/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](../i18n/vi/docs/reference/API_REFERENCE.md) | 🇳🇬 [Yorùbá](../i18n/yo/docs/reference/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](../i18n/zh-CN/docs/reference/API_REFERENCE.md) | 🇹🇼 [中文 (繁體)](../i18n/zh-TW/docs/reference/API_REFERENCE.md) Rujukan teras untuk API OmniRoute. Ia merangkumi permukaan awam `/v1` dan titik akhir pengurusan yang paling banyak digunakan; [`docs/openapi.yaml`](../openapi.yaml) yang boleh dibaca mesin serta pepohon laluan di bawah `src/app/api/` ialah sumber yang lengkap. Untuk protokol yang serasi dengan OpenAI dan matriks keupayaan penyedia yang lebih khusus, lihat [`OPENAI_COMPATIBILITY.md`](./OPENAI_COMPATIBILITY.md). Setiap deployment menyediakan salinan spesifikasinya sendiri di `/openapi.yaml`, yang dijana daripada `docs/openapi.yaml` semasa binaan. Spesifikasi ini membawa versi binaan serta URL pelayan relatif (`./`), supaya permintaan kekal pada hos yang menyediakan dokumen tersebut. Alat yang mengimport fail yang dimuat turun tidak mempunyai hos sedemikian dan memerlukan URL asas ditetapkan secara manual. --- ## Kandungan - [Pelengkapan Sembang](#chat-completions) - [Pajakan Sesi Terurus Eksklusif](#exclusive-managed-session-leases) - [Pembenaman](#embeddings) - [Penjanaan Imej](#image-generation) - [OCR Dokumen](#document-ocr) - [Senaraikan Model](#list-models) - [Manifes Pemalam Pembekal](#provider-plugin-manifest) - [Titik Akhir Keserasian](#compatibility-endpoints) - [API Fail](#files-api) - [API Kelompok](#batches-api) - [API Carian](#search-api) - [Penstriman WebSocket](#websocket-streaming) - [Kuota & Pelaporan Isu](#quotas--issues-reporting) - [Cache Semantik](#semantic-cache) - [Keserasian Pengurusan CLIProxyAPI](#cliproxyapi-management-compatibility) - [Papan Pemuka & Pengurusan](#dashboard--management) - [Pengurusan Gabungan](#combo-management) - [Webhook](#webhooks) - [Kunci Berdaftar (Pengurusan Automatik)](#registered-keys-auto-management) - [Protokol Ejen](#agents-protocol) - [Proksi Pengurusan](#management-proxies) - [Ketahanan (dilanjutkan)](#resilience-extended) - [Kemahiran](#skills) - [Memori](#memory) - [Pelayan MCP](#mcp-server) - [Pelayan A2A](#a2a-server) - [Cloud, Evals & Assess](#cloud-evals--assess) - [Pemprosesan Permintaan](#request-processing) - [Pengesahan](#authentication) --- ## Pelengkapan Sembang ```bash POST /v1/chat/completions Authorization: Bearer your-api-key Content-Type: application/json { "model": "cc/claude-opus-4-6", "messages": [ {"role": "user", "content": "Write a function to..."} ], "stream": true } ``` ### Pengepala Tersuai | Header | Arah | Penerangan | | ------------------------ | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `X-OmniRoute-No-Cache` | Permintaan | Tetapkan kepada `true` untuk memintas cache | | `x-omniroute-no-memory` | Permintaan | Tetapkan kepada `true` untuk melangkau suntikan memori + kemahiran bagi permintaan ini (mencerminkan no-cache; mengelakkan overhed token/kos setiap panggilan) | | `X-OmniRoute-Progress` | Permintaan | Tetapkan kepada `true` untuk peristiwa kemajuan | | `X-Session-Id` | Permintaan | Kunci sesi lekat untuk afiniti sesi luaran | | `x_session_id` | Permintaan | Varian garis bawah juga diterima (HTTP langsung) | | `X-OmniRoute-Session-Id` | Permintaan | Tag sesi/perbualan yang dibekalkan pemanggil (juga disalurkan kepada memori). Apabila hadir, disimpan secara verbatim ke `call_logs.session_tag` untuk atribusi kos mengikut sesi (#8249) — tidak pernah dijana apabila tiada | | `Idempotency-Key` | Permintaan | Kunci deduplikasi (tetingkap 5s) | | `X-Request-Id` | Permintaan | Kunci deduplikasi alternatif | | `x-omniroute-connection` | Permintaan | Ikat permintaan model tunggal kepada satu sambungan penyedia (akaun) mengikut idnya — lihat [Pengikatan akaun bagi setiap permintaan](#account-pinning-per-request) | | `X-OmniRoute-Cache` | Respons | `HIT` atau `MISS` (bukan penstriman) | | `X-OmniRoute-Idempotent` | Respons | `true` jika dideduplikasi | | `X-OmniRoute-Progress` | Respons | `enabled` jika penjejakan kemajuan diaktifkan | | `X-OmniRoute-Session-Id` | Respons | ID sesi berkesan yang digunakan oleh OmniRoute | | `X-OmniRoute-Request-Id` | Respons | ID korelasi permintaan (apabila diketahui) | | `X-OmniRoute-Version` | Respons | Versi binaan OmniRoute (sentiasa hadir) | | `X-OmniRoute-Cost-Saved` | Respons | USD yang dijimatkan oleh cache pada `HIT` (hanya cache hit) | | `X-OmniRoute-Decision` | Respons | Jejak penghalaan: `strategy=; provider=; latency_ms=` (`` ialah strategi gabungan, atau `single` untuk permintaan bukan gabungan) — sentiasa hadir pada respons penyelesaian | > Nota Nginx: jika anda bergantung pada pengepala garis bawah (contohnya `x_session_id`), dayakan `underscores_in_headers on;`. #### Pengikatan akaun bagi setiap permintaan Apabila penyedia mempunyai beberapa sambungan (akaun atau kunci), OmniRoute biasanya memilih salah satu melalui strategi pemilihan akaunnya. Sebaliknya, permintaan boleh mengikat satu sambungan tertentu dengan pengepala `x-omniroute-connection`: ```bash curl http://localhost:20128/v1/chat/completions \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -H "x-omniroute-connection: " \ -d '{"model": "codex/gpt-5.5", "messages": [{"role": "user", "content": "hi"}]}' ``` - **Tempat untuk mencari id.** Buka halaman penyedia dalam papan pemuka (**Dashboard → Providers → **) dan klik cip id `xxxxxxxx…` pada baris sambungan — ia menyalin id sambungan penuh. - **Permintaan yang menghormatinya.** Permintaan model tunggal (`provider/model`) pada `/v1/chat/completions`, `/v1/messages` dan `/v1/responses`. Gabungan mengabaikan pengepala ini: tetapkan akaun bagi setiap langkah gabungan melalui sambungan langkah itu sendiri. - **Pin adalah ketetapan, bukan keutamaan.** Sambungan yang dipinkan digunakan secara eksklusif. Jika berlaku kegagalan dalam permintaan, ia merekodkan tempoh penyejukan akaun tetapi **tidak** beralih kepada akaun lain daripada penyedia yang sama. - **Tempoh penyejukan dan kuota melepaskan pin.** Selagi sambungan yang dipinkan dalam tempoh penyejukan, kehabisan kuota atau disekat oleh dasar kuota, permintaan seterusnya akan beralih kepada sambungan lain penyedia, sama seperti trafik tanpa pin. - **Id yang tidak diketahui atau dilumpuhkan akan gagal.** Id yang tiada dalam kumpulan aktif penyedia (dipadamkan, dinyahaktifkan atau milik penyedia lain) tidak meninggalkan akaun yang layak, maka permintaan gagal dan bukannya dihalakan secara senyap ke tempat lain. Claude Code menghantar pengepala tersuai melalui `ANTHROPIC_CUSTOM_HEADERS`. Letakkannya dalam blok `env` bagi `~/.claude/settings.json`, atau dalam `.claude/settings.json` peringkat projek untuk menetapkan akaun yang berbeza bagi setiap projek: ```jsonc { "env": { "ANTHROPIC_BASE_URL": "http://:20128", "ANTHROPIC_AUTH_TOKEN": "", "ANTHROPIC_CUSTOM_HEADERS": "x-omniroute-connection: ", }, } ``` Sumber: `src/sse/handlers/chat.ts` (pembacaan pengepala), `src/sse/services/auth.ts` dan `src/sse/services/sessionAffinityPin.ts` (pelepasan pin dan semakan sambungan yang tiada dalam kumpulan). > **Pengepala telemetri kos:** respons berjaya tanpa penstriman turut membawa set telemetri kos `X-OmniRoute-*` — `X-OmniRoute-Response-Cost` (USD, tetap 10 tempat perpuluhan; `0.0000000000` untuk percuma/tanpa harga), `X-OmniRoute-Tokens-In` / `X-OmniRoute-Tokens-Out`, `X-OmniRoute-Model`, `X-OmniRoute-Provider`, `X-OmniRoute-Latency-Ms`, `X-OmniRoute-Cache-Hit` dan `X-OmniRoute-Fallback-Attempts` (hanya apabila > 0), serta `X-OmniRoute-Request-Id` dan `X-OmniRoute-Version`. Semua ini dijana oleh penyempurnaan chat, `/v1/responses`, `/v1/messages`, **dan titik akhir media** — `/v1/embeddings`, `/v1/images/generations`, `/v1/audio/speech`, `/v1/audio/transcriptions`, `/v1/rerank`, `/v1/videos/generations`, `/v1/music/generations` dan `/v1/moderations` (sentiasa dengan kos `0`). Kos media dikira mengikut modaliti (setiap imej, setiap saat, setiap aksara, setiap unit carian) apabila harga tersedia, jika tidak `0` (gagal terbuka). > **Semantik kos capaian cache:** pada HIT cache semantik (`X-OmniRoute-Cache-Hit: true`), tiada panggilan huluan dibuat, maka `X-OmniRoute-Response-Cost` ialah `0.0000000000` (kos **tambahan** untuk menyediakan capaian tersebut). Kos asal/yang sepatutnya berlaku dilaporkan secara berasingan dalam `X-OmniRoute-Cost-Saved`. Pengguna pengebilan hendaklah menjumlahkan `X-OmniRoute-Response-Cost` (capaian cache tidak berkos); analitik cache boleh mengagregatkan `X-OmniRoute-Cost-Saved`. ## Pajakan Sesi Terurus Eksklusif Pajakan sesi terurus eksklusif ialah kontrak penghalaan yang bersifat pilihan dan neutral terhadap klien: satu pemilik aktif memegang satu sambungan OmniRoute yang layak. Ia tidak memajak model, memerlukan OAuth, mengenal pasti klien tertentu, atau memerlukan pembekal tertentu. Kunci API yang mengesahkan mestilah mempunyai skop `lease:exclusive` dan senarai `allowedConnections` yang jelas serta tidak kosong. Sempadan mutasi pangkalan data menguatkuasakan kedua-dua medan ini secara bersama semasa penciptaan kunci dan kemas kini separa. ```http POST /api/v1/session-leases Authorization: Bearer Content-Type: application/json X-OmniRoute-Lease-Owner: vlo_<43-base64url-characters> {"action":"acquire","model":"glm/glm-4.6"} ``` Respons pemerolehan, pembaharuan dan pelepasan yang berjaya mendedahkan cap masa, `state`, dan `generation` positif yang tepat, tetapi tidak pernah mendedahkan sambungan atau kelayakan yang dipilih. Pembaharuan dan pelepasan membekalkan generation dalam badan JSON: ```json { "action": "renew", "generation": 1 } ``` ```json { "action": "release", "generation": 1, "reason": "OWNER_EXIT" } ``` Pemilik pajakan aktif boleh meminta metadata paparan yang selamat dari segi privasi secara jelas untuk binding semasanya: ```json { "action": "status", "generation": 1 } ``` ```json { "state": "ACTIVE", "generation": 1, "acquiredAt": "2026-08-28T12:00:00.000Z", "renewedAt": "2026-08-28T12:00:30.000Z", "expiresAt": "2026-08-28T12:02:30.000Z", "connection": { "displayName": "Primary Codex", "provider": "codex" } } ``` Tindakan status pilihan ini dipagari oleh pemilik legap, kunci API terurus yang disahkan, dan generasi aktif yang tepat dalam satu transaksi pangkalan data. `displayName` hanyalah nama sambungan yang dikonfigurasikan dan telah dipangkas; nilainya ialah `null` apabila tiada nama dikonfigurasikan yang selamat tersedia. OmniRoute tidak pernah menggantikan nama tersebut dengan e-mel atau identiti akaun yang dijana. Nilai pembekal ialah label paparan yang tidak sensitif dan tidak pernah menjadi pengecam pembekal serasi yang dijana. Kelayakan, token, kuki, id sambungan atau kunci API mentah, cincangan pemilik, rahsia pemagaran, dan data penghalaan dalaman tidak disertakan. Carian dengan kunci yang salah, pemilik yang salah, generasi lapuk, pajakan yang tiada, tamat tempoh, telah dilepaskan, atau telah dibatalkan semuanya mengembalikan ralat `409 LEASE_FENCE_STALE` yang sama tanpa metadata sambungan. Klien yang menerima respons menunggu kapasiti tidak mempunyai binding aktif untuk diperiksa. Apabila penghalaan mengalihkan pajakan aktif, generasi yang sama kekal sah dan status secara atom mengembalikan binding baharu, tidak pernah binding lama. Klien sedia ada kekal tidak berubah kerana respons pemerolehan, pembaharuan, pelepasan dan menunggu mengekalkan bentuk sebelumnya. Kontrak pelayan ini tidak mengubah `/status` OpenAI Codex standard. Codex standard pada masa ini melaporkan pembekal model serta keadaan pengesahan/akaun terbina dalamnya, tetapi tidak memaparkan metadata akaun pembekal tersuai sewenang-wenangnya; integrasi klien kemudian mestilah memanggil tindakan ini dan menentukan cara untuk memaparkan `connection.displayName`. Setiap permintaan inferens terurus kemudiannya membekalkan kedua-dua pengepala kawalan: ```http X-OmniRoute-Lease-Owner: vlo_<43-base64url-characters> X-OmniRoute-Lease-Generation: 1 ``` Pemilik, generasi, sambungan aktif dan kunci API yang disahkan yang tepat dipagari serta-merta sebelum setiap percubaan huluan yang disokong. Mengulangi pemilik dan generasi dengan kunci lain akan gagal walaupun kunci tersebut membenarkan sambungan yang sama. Pemilik mentah tidak disimpan, dilog, dikekalkan dalam syot kilat permintaan, atau dihantar ke huluan. Pertikaian sementara mengembalikan HTTP `429` dengan `Retry-After` dan: ```json { "state": "WAITING_FOR_CAPACITY", "error": { "type": "lease_error", "code": "LEASE_CAPACITY_UNAVAILABLE" }, "reason": "NO_FREE_ELIGIBLE_CONNECTION", "retryAfter": 30 } ``` Respons ini hanya bermaksud bahawa set yang layak biasa tidak kosong dan setiap calon yang tersedia sedang dipegang oleh pajakan aktif asing. Model/pembekal yang tidak disokong, ketidakpadanan dasar, tempoh bertenang, kuota, kesihatan dan kegagalan kelayakan biasa yang lain mengekalkan respons OmniRoute sedia ada. ### `x-omniroute-compression` Penggantian setiap permintaan untuk pelan pemampatan. Keutamaan tertinggi — mengatasi penggantian gabungan penghalaan, profil aktif, pencetus automatik dan Default panel. Nilai: | Nilai | Kesan | | ------------- | ------------------------------------------------------------------------------------------------------------- | | `off` | Tiada pemampatan untuk permintaan ini. | | `default` | Profil Default yang diperoleh daripada panel (mengabaikan profil aktif). Enjin lossy dibiarkan mati. | | `safe` | Dedup dan pelipatan ruang putih sahaja. | | `allow-lossy` | Kekalkan pelan operator untuk permintaan ini, termasuk ringkasan dan penulisan semula gaya. | | `engine:` | Satu enjin apabila didayakan, contohnya `engine:rtk`. Pilihan masuk setiap permintaan untuk enjin tersebut. | | `` | Gabungan bernama, dipadankan mengikut nama (tidak membezakan huruf besar-kecil) dahulu, kemudian mengikut id. | Nota: - Nilai yang tidak diketahui diabaikan (permintaan tidak pernah ditolak); penyelesaian diteruskan mengikut keutamaan operator biasa. - Jika beberapa gabungan berkongsi nama, berikan **id** gabungan untuk padanan yang deterministik. - Gabungan yang namanya ialah `off` atau `default` tidak boleh dipilih mengikut nama (kata kunci tersebut ditafsirkan terlebih dahulu); rujuk gabungan sedemikian menggunakan idnya. - Suis pemampatan induk ialah get tegar: apabila pemampatan dilumpuhkan secara global, pengepala ini tidak boleh mendayakannya. Pelan yang digunakan dipantulkan kembali dalam pengepala respons: ``` X-OmniRoute-Compression: ; source= ``` yang mana `` ialah salah satu daripada `request-header`, `routing-override`, `active-profile`, `auto-trigger`, `default`, atau `off`. --- ## Embedding ```bash POST /v1/embeddings Authorization: Bearer your-api-key Content-Type: application/json { "model": "nebius/Qwen/Qwen3-Embedding-8B", "input": "The food was delicious" } ``` Penyedia yang tersedia: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA, **OpenRouter**, Jina AI. ID katalog ialah `provider/model` (contoh: `jina-ai/jina-embeddings-v5-omni-small`). ID model Jina tanpa awalan yang muncul dalam pendaftaran (contohnya `jina-embeddings-v5-text-small`, `jina-reranker-v3.5`) turut diselesaikan. Embed/rerank/classify/segment Jina menggunakan kelayakan `jina-ai` papan pemuka terlebih dahulu; `JINA_AI_API_KEY` hanya menjadi sandaran apabila tiada kunci papan pemuka. Kad `jina-reader` hanya untuk Reader / `r.jina.ai` (`POST /v1/web/fetch`) dan tidak pernah menyediakan embedding atau rerank. Model pendaftaran yang mengiklankan sokongan multimodal turut menerima sehingga 32 item berstruktur yang neutral kepada penyedia. Jenis item media ialah `text`, `image`, `audio`, `video`, dan `document`. `source` media tersebut ialah sama ada `{"type":"url","url":"https://..."}` atau `{"type":"base64","data":"...","media_type":"..."}`. Jina v5 Omni (`jina-ai/jina-embeddings-v5-omni-small`, `jina-ai/jina-embeddings-v5-omni-nano`, dan alias keluarga `jina-ai/jina-embeddings-v5-omni` → omni-small) turut menerima dokumen EmbeddingsV5Request asli Jina dan **meneruskannya tanpa perubahan** ke `https://api.jina.ai/v1/embeddings`: ```json { "model": "jina-ai/jina-embeddings-v5-omni-small", "task": "retrieval.query", "normalized": true, "input": [ { "text": "a red bicycle" }, { "image": "https://example.com/bike.png" }, { "content": [{ "text": "caption" }, { "image": "data:image/png;base64,..." }] } ] } ``` Nilai asli `{ image | audio | video | pdf }` boleh berupa URL HTTPS awam, URI `data:`, atau base64 mentah. OmniRoute tidak menukar objek tersebut kepada rentetan atau mengambil URL imej asli — Jina mengambil media awam itu sendiri. Medan Jina tambahan (`task`, `normalized`, `truncate`, `embedding_type`) akan diteruskan. SKU Jina teks sahaja masih menolak dokumen bukan teks. Had keselamatan dan pengangkutan: - URL media jauh mestilah HTTPS awam. Item kanonik `{type,source:url}` diambil di sisi pelayan (pengesahan semula ubah hala, tamat masa, had saiz, DNS awam, pemautan sambungan) dan disisipkan sebelum panggilan kepada penyedia. Item asli Jina `{image:"https://..."}` diteruskan seperti adanya selepas pemeriksaan HTTPS awam yang sama; Jina mengambil URL tersebut. - Media base64 sebaris dihadkan kepada 8 MiB selepas dinyahkod bagi setiap item dan 16 MiB selepas dinyahkod merentas permintaan. Terjemahan penyedia (item kanonik tidak pernah diteruskan tanpa perubahan): - Model multimodal Jina: setiap item peringkat teratas menjadi satu objek berkunci modaliti (`text` / `image` / `audio` / `video` / `pdf`) menggunakan URI data untuk media sebaris; satu vektor bagi setiap item peringkat teratas. - Keluarga Gemini Embedding 2: satu tatasusunan peringkat teratas menjadi satu permintaan asli `models/{model}:embedContent` dengan `content.parts` (`text` atau `inline_data`). - llama.cpp (`llama-cpp/`, mana-mana model yang dimuatkan oleh pelayan tempatan): item kanonik `text` menjadi rentetan biasa, manakala `image` / `audio` / `video` masing-masing menjadi satu objek `{"content": [part]}`, menggunakan bahagian kandungan sembang llama-server (`image_url`, `input_audio` dengan format `wav` / `mp3` / `flac`, `input_video`) dengan data sebaris; satu vektor bagi setiap item peringkat teratas. Pelayan mesti dijalankan dengan `--embedding --mmproj …`; tanpa projektor, pelayan itu sendiri menolak media. `document` tidak disokong. - Model tidak diketahui/dinamik tanpa metadata modaliti yang jelas akan menolak input berstruktur dengan HTTP 400. ```json { "model": "jina-ai/jina-embeddings-v5-omni-small", "input": [ { "type": "text", "text": "A red bicycle" }, { "type": "image", "source": { "type": "url", "url": "https://example.com/bicycle.png" } } ], "dimensions": 512, "encoding_format": "float" } ``` Gabungan model/modaliti yang tidak disokong akan mengembalikan HTTP 400 dan bukannya memaksa penukaran item. Medan sambungan bukan input pada permintaan rentetan/token legasi terus diteruskan tanpa perubahan. ```bash # Senaraikan semua model embedding GET /v1/embeddings ``` --- ## Penjanaan Imej ```bash POST /v1/images/generations Authorization: Bearer your-api-key Content-Type: application/json { "model": "openai/gpt-image-2", "prompt": "A beautiful sunset over mountains", "size": "1024x1024" } ``` Penyedia yang tersedia termasuk OpenAI (GPT Imej 2), xAI (Grok Image), Together AI (FLUX), Fireworks AI, Nebius (FLUX), Hiperbolik, NanoBanana,**OpenRouter** ,**ZenMux** , SD WebUI (tempatan), ComfyUI (tempatan). `n` mengembalikan imej `n` dalam `data[]`. Penyedia yang API hulunya mengembalikan satu imej setiap panggilan (Black Forest Labs, Stability AI, Leonardo, Ideogram, Haiper, Hyperbolic, Magnific/Freepik, NVIDIA NIM, Cloudflare Workers AI) mendapat `n` panggilan huluan berasingan, paling banyak 4 dalam penerbangan. `seed` tetap diimbangi oleh indeks panggilan (`seed`, `seed + 1`, …), jadi imej berbeza tetapi kekal boleh dihasilkan semula. `n` dihadkan pada 10. Permintaan gagal secara keseluruhan jika sebarang panggilan gagal. Senarai format kipas keluar ialah `SINGLE_IMAGE_FANOUT_FORMATS` dalam `open-sse/handlers/imageGeneration/fanOut.ts`. ZenMux menggunakan semula sambungan kunci API sedia ada dan menerima awalan `zenmux/` atau `zm/` : - `zenmux/openai/gpt-image-2` menggunakan ZenMuxOpenAI Imej API. Pilihan termasuk `size`, `quality`, `n`, `output_format`, `output_compression`, `background` dan `response_format`. - Penerbit lain, seperti `zm/meta/muse-image-1.0`, menggunakan titik akhir ZenMux Vertex AI `:predict`. `n` memetakan ke `sampleCount`, `aspect_ratio` ke `aspectRatio`, dan `image_size` (`1K`, `2K`, `4K`) ke `sampleImageSize`. `size` piksel hanya membekalkan nisbah bidang, bukan dimensi piksel yang dijamin. Nisbah, resolusi dan kiraan yang disokong berbeza mengikut model. - `zm/inclusionai/ming-image-0.1-design` memilih dimensinya sendiri. Tinggalkan `size`, `aspect_ratio`, dan `image_size`; nilai eksplisit mengembalikan HTTP 400. PNG, JPEG dan WebP boleh diminta dengan `output_format`. Penyepaduan ini menyokong penjanaan teks ke imej, bukan pengeditan imej rujukan. Keluaran bucu dinormalkan kepada `data[].b64_json`; `response_format: "url"` mengembalikan HTTPS URL hulu atau URL data base64 apabila hanya bait imej tersedia. output Empty/filtered mengembalikan ralat dan bukannya kejayaan kosong. Akses model bergantung pada akaun ZenMux. Lihat [ZenMux's Vertex API](https://docs.zenmux.ai/api/vertexai/generate-images) dan [OpenAI Imej API](https://docs.zenmux.ai/api/openai/generate-an-image). Sambungan log masuk Microsoft 365 Copilot menyediakan `copilot-m365-web/m365-copilot-image` melalui alat imej terbina dalam Copilot: satu pusingan Copilot setiap imej (`n` 1–4), `size` stereng orientasi sahaja dan imej dikembalikan sebaris (`b64_json`, atau URL data untuk `response_format: "url"`). Lihat [Microsoft 365 Copilot](../providers/COPILOT-M365.md#image-generation). ```bash # List all image models GET /v1/images/generations ``` --- ## OCR Dokumen ```bash POST /v1/ocr Authorization: Bearer your-api-key Content-Type: application/json { "model": "mistral/mistral-ocr-latest", "document": { "type": "document_url", "document_url": "https://example.com/invoice.pdf" } } ``` `model` memilih penyedia OCR melalui awalan `provider/model`; id model tanpa awalan (contohnya `mistral-ocr-latest`) diselesaikan kepada penyedia berdaftarnya, manakala `model` yang tidak dinyatakan secara lalai menggunakan Mistral (`mistral-ocr-latest`). Penyedia berdaftar (`open-sse/config/ocrRegistry.ts`): | ID penyedia | ID model | Nilai `model` | Nota | | ----------------------------- | -------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | `mistral` | `mistral-ocr-latest` | `mistral/mistral-ocr-latest` (atau `mistral-ocr-latest` tanpa awalan) | Segerak — respons dikembalikan terus daripada satu panggilan huluan. | | `azure-document-intelligence` | `prebuilt-read` | `azure-document-intelligence/prebuilt-read` | Huluan tak segerak (`analyze` + tinjau) — lihat di bawah. | | `vertex-deepseek-ocr` | `deepseek-ocr-maas` | `vertex-deepseek-ocr/deepseek-ocr-maas` | Segerak, melalui titik akhir rakan kongsi `openapi/chat/completions` Vertex AI — lihat di bawah untuk pengesahan/URL. | Ketiga-tiga penyedia memberikan respons dalam badan berbentuk Mistral yang sama: ```json { "pages": [{ "index": 0, "markdown": "# Extracted text..." }], "model": "mistral-ocr-latest", "usage_info": { "pages_processed": 1 } } ``` ### Aliran tinjauan Azure Document Intelligence API `analyze` Azure Document Intelligence adalah tak segerak: permintaan awal mengembalikan pengepala `Operation-Location` dan bukannya badan, dan hasilnya mesti ditinjau. Pengendali (`open-sse/handlers/ocr.ts`) meninjau URL tersebut setiap saat sehingga 30 percubaan, berhenti dengan segera (tidak meneruskan tinjauan) apabila respons tinjauan bukan `ok` atau statusnya `"failed"`, dan mengembalikan `504` jika operasi masih berjalan selepas bajet percubaan habis. Respons Azure akhir dinormalkan kepada bentuk `pages`/`markdown` yang sama seperti yang digunakan oleh Mistral sebelum dikembalikan kepada pemanggil, jadi kod klien tidak perlu mengendalikan penyedia secara khusus. ### Pengesahan dan penyelesaian titik akhir Vertex AI DeepSeek OCR `vertex-deepseek-ocr` menggunakan semula pengesahan Vertex AI yang sama yang telah disokong oleh OmniRoute untuk trafik chat/imej (`open-sse/executors/vertex.ts`): kunci API sambungan sama ada merupakan kelayakan JSON Akaun Perkhidmatan (ditukar kepada token akses OAuth berjangka pendek melalui aliran JWT-bearer) atau token akses OAuth yang telah dikeluarkan dan digunakan seadanya. URL titik akhir huluan ialah titik akhir rakan kongsi generik `openapi/chat/completions` Vertex, yang dibina daripada projek dan rantau sambungan — `providerSpecificData.project`/`providerSpecificData.region` yang dinyatakan secara jelas sentiasa diutamakan; jika tidak, projek diperoleh daripada `project_id` JSON Akaun Perkhidmatan dan rantau lalai ialah `us-central1`. Kedua-dua penyelesaian berlaku dalam `open-sse/handlers/ocr.ts` (`resolveVertexOcrAccessToken`, `resolveVertexOcrBaseUrl`), yang digunakan oleh `src/app/api/v1/ocr/route.ts` sebelum dihantar kepada `handleOcr`. --- ## Senaraikan Model ```bash GET /v1/models Authorization: Bearer your-api-key → Mengembalikan semua model sembang, embedding dan imej + gabungan dalam format OpenAI ``` ### Harga model (`pricing`) Sesuatu entri membawa objek `pricing` apabila OmniRoute mengetahui harga model tersebut. Harga datang daripada jadual harga yang digunakan oleh perakaunan kos: lalai terbina dalam, harga yang disegerakkan dan penggantian yang ditetapkan melalui `/api/pricing`. Ini ialah harga senarai, jadi penyedia langganan juga memaparkan harga setiap token. ```json "pricing": { "prompt": "0.000005", "completion": "0.000025", "input_cache_read": "0.0000005", "input_cache_write": "0.00000625", "input": 5, "output": 25, "cached": 0.5, "cache_creation": 6.25 } ``` | Medan | Unit | Nota | | --------------------------------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | `prompt`, `completion`, `input_cache_read`, `input_cache_write` | USD setiap token, rentetan perpuluhan | Serasi dengan OpenRouter, tidak pernah dalam notasi eksponen. Dua medan cache hanya muncul apabila terdapat harga cache. | | `input`, `output`, `cached`, `cache_creation` | USD setiap 1M token, nombor | Medan daripada versi katalog terdahulu, dikekalkan untuk klien sedia ada. `reasoning` dan `long_context` juga muncul apabila baris harga mempunyainya. | - **Gabungan** membawa harga sasaran pertama yang kelihatan. Gabungan `auto/*` terbina dalam memilih sasaran semasa permintaan, jadi ia tidak mempunyai `pricing`. - **Model percuma** memaparkan `"0"` (dan `0`) apabila harganya sifar. Model tanpa baris harga juga memaparkan `"0"` apabila katalog menandakannya sebagai percuma (`free: true`) atau katalog model percuma terbina dalam menyenaraikannya. - **Harga tidak diketahui:** entri tersebut tidak mempunyai kunci `pricing`. - **Penyedia yang diukur berdasarkan kredit** (seperti Kiro) mengebil setiap permintaan dan bukannya setiap token. Entri mereka mengekalkan medan berangka setiap-1M yang dimilikinya sebelum ini dan tidak membawa medan rentetan setiap token. - **Varian** (id usaha penaakulan, alias tanpa pemikiran, cerminan penemuan dan get laluan) menyalin harga model yang dirutekannya. - Medan tersebut hanya membawa kadar asas. Tingkat konteks panjang (medan berangka `long_context`) dan pengganda tingkat perkhidmatan (contohnya Codex pantas atau fleksibel) tidak mengubah `prompt` atau `completion`. - Objek tersebut sama untuk setiap gaya pengesahan, termasuk permintaan bergaya Anthropic dengan `x-api-key` dan `anthropic-version` (respons kekal `{ "object": "list", "data": [...] }`). Pelaksanaan: `src/app/api/v1/models/catalogPricing.ts`. ### Awalan id model (`?prefix=`) Kebanyakan model diiklankan dengan **awalan penyedia**. Awalan yang anda terima dikawal oleh flag ciri `MODELS_CATALOG_PREFIX_MODE`, dan boleh diubah **bagi setiap permintaan** dengan parameter pertanyaan — berguna untuk klien yang mahukan senarai bersih tanpa mengubah tetapan seluruh pelayan untuk orang lain: ```bash GET /v1/models?prefix=alias # satu id bagi setiap model — awalan alias ringkas GET /v1/models?prefix=dual # kedua-dua bentuk (lalai pelayan) GET /v1/models?prefix=canonical # hanya awalan id penyedia penuh ``` | Mod | Menghasilkan | Nota | | ----------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `dual` | `cc/claude-sonnet-4-6` **dan** `claude/claude-sonnet-4-6` | **Lalai.** Kedua-dua id merutekan ke model yang sama; dikekalkan supaya konfigurasi klien yang menetapkan salah satu bentuk secara keras terus berfungsi. Katalog kira-kira berganda. | | `alias` | `cc/claude-sonnet-4-6` | Satu entri bagi setiap model. Penyedia tanpa alias yang berbeza masih menghasilkan entri mereka, jadi tiada apa-apa yang hilang. | | `canonical` | `claude/claude-sonnet-4-6` | Satu entri bagi setiap model di bawah awalan id penyedia penuh. Penyedia tanpa alias yang berbeza (contohnya `antigravity/…`, `agy/…`) turut menghasilkan id tunggal mereka di sini, jadi tiada apa-apa yang hilang. | Cerminan mod `dual` juga boleh dikenal pasti tanpa parameter pertanyaan: ia membawa medan `parent` yang menunjuk kepada id utama. Klien yang memaparkan pemilih model hendaklah meminta `?prefix=alias` — inilah yang dilakukan oleh [sambungan OmniCopilot VS Code](../guides/VSCODE-COPILOT.md). ### Penapis penemuan (`?capability=`, `?min_context=`, `?kind=`, `?q=`) `GET /v1/models` menerima penapis penemuan pilihan. Tanpa mana-mana penapis ini, respons tidak berubah. Penapis ini mengecilkan katalog yang sudah boleh dilihat oleh pemanggil (kebenaran kunci API digunakan terlebih dahulu), dan dijalankan sebelum penomboran `limit` / `after` gaya OpenAI: ```bash GET /v1/models?capability=vision&capability=tool_calling # setiap keupayaan yang disenaraikan mesti benar GET /v1/models?capability=vision,reasoning&min_context=200000 GET /v1/models?kind=embedding # `type` katalog; baris tanpanya ialah `chat` GET /v1/models?q=sonnet&limit=10 # padanan tidak peka huruf besar-kecil pada id atau nama ``` | Parameter | Nilai | | ------------- | --------------------------------------------------------------------------------------------------- | | `capability` | `attachment`, `reasoning`, `structured_output`, `temperature`, `thinking`, `tool_calling`, `vision` | | `min_context` | integer bukan negatif, dibandingkan dengan `context_length` | | `kind` | `chat`, `audio`, `embedding`, `image`, `moderation`, `music`, `rerank`, `video` | | `q` | 1–200 aksara | Nilai yang tidak diketahui, atau `min_context` yang bukan integer bukan negatif (contohnya `1.5`), mengembalikan HTTP `400` dan mesej menyenaraikan nilai yang sah. Pelaksanaan: `src/app/api/v1/models/catalogFilters.ts`. ### Senarai pendek model (`POST /v1/models/query`) `POST /v1/models/query` mengembalikan senarai pendek deterministik daripada katalog yang sama, dengan pengesahan dan keterlihatan setiap kunci yang sama seperti `GET /v1/models`: ```bash POST /v1/models/query Authorization: Bearer your-api-key Content-Type: application/json { "capabilities": ["vision", "tool_calling"], "min_context": 128000, "max_output": 16000, "kind": "chat", "q": "gpt", "owned_by": "openai", "exclude": ["openai/gpt-4o"], "limit": 5 } → { "object": "list", "data": [ ...models ] } ``` Setiap medan adalah pilihan. `capabilities` dan `exclude` menerima tatasusunan atau rentetan dipisahkan koma; `max_output` dibandingkan dengan `max_output_tokens`. Hasilnya diisih mengikut `owned_by`, kemudian `id`. `limit` lalai kepada `20` dan nilai melebihi `100` dihadkan kepada `100`. JSON yang tidak sah, medan yang tidak diketahui atau nilai yang tidak sah mengembalikan HTTP `400`. ### Model sembang yang disembunyikan secara individu Model yang ditandakan **Tersembunyi** pada halaman penyedianya dikecualikan daripada katalog dan ditolak dengan HTTP `404` / `model_not_found` apabila diminta secara eksplisit. Semakan ini menggunakan penyedia dan model yang telah diselesaikan, termasuk alias penyedia, awalan nod penyedia yang serasi dan lalai sambungan. Gabungan melangkau sasaran tersembunyi dan boleh menggunakan adik-beradik yang kelihatan; apabila tiada sasaran boleh laku yang tinggal, ia mengembalikan kod ralat yang sama. Menyahsembunyikan berkuat kuasa pada permintaan seterusnya. Penggantian keterlihatan untuk imej sahaja tidak menyembunyikan model sembang dengan ID yang sama. Tetapan model individu ini berasingan daripada [senarai benarkan/tolak pendedahan model](../routing/MODEL_EXPOSURE_LIST.md), yang menapis pengiklanan katalog dan calon penghalaan automatik sambil mengekalkan penghantaran eksplisit. Kebenaran model untuk kunci API terus digunakan secara bebas. Mod awalan katalog lalai kekal `dual`. ### Varian model tanpa thinking Untuk model Claude yang menyokong thinking, `/v1/models` turut mengiklankan varian **tanpa thinking** yang ID-nya diawali dengan `claude-3-omniroute-no-thinking/`: ``` claude-3-omniroute-no-thinking// ``` Memilih ID ini (contohnya dalam konfigurasi Claude Code yang sentiasa melampirkan blok `thinking`) akan menyelesaikan semula kepada `/` sebenar dengan penaakulan dilumpuhkan — `thinking:{type:"disabled"}` pada laluan `/v1/messages`, atau medan `reasoning`/`reasoning_effort` digugurkan pada laluan `/v1/chat/completions`. Varian ini hanya disenaraikan untuk model keluarga Claude yang menyokong thinking **dan** mematuhi `disabled` (contohnya model adaptif sahaja yang menolak `disabled` dikecualikan). Operator boleh memaksa varian ini hidup atau mati bagi setiap model melalui `ModelSpec.noThinkingAlias`. --- ## Manifes Pemalam Pembekal ```bash GET /api/v1/provider-plugin-manifest ``` Mengembalikan manifes pemalam pembekal yang selamat untuk JSON, yang digunakan oleh Bifrost, CLIProxyAPI dan penghala sidecar akan datang. Respons dijana daripada pendaftaran pembekal TypeScript dan sengaja tidak menyertakan rahsia klien OAuth, penyelesaian persekitaran masa jalan, fungsi pelaksana, pengepala permintaan dan data akaun. Gunakan titik akhir ini apabila sidecar berjalan di luar proses dan tidak boleh mengimport `open-sse/config/providerPluginManifestRegistry.ts` secara langsung. --- ## Penjanaan audio ElevenLabs Konfigurasikan sambungan pembekal `elevenlabs` dalam OmniRoute dengan kunci API ElevenLabs anda. Klien mengesahkan dirinya dengan kunci **OmniRoute** (`Authorization: Bearer $OMNIROUTE_API_KEY`); get laluan membekalkan kunci pembekal yang disimpan sebagai `xi-api-key`. Jangan sekali-kali menghantar kunci ElevenLabs sebagai token pembawa get laluan. | Kaedah | Laluan | Respons | Kategori titik akhir kunci API | | ------ | --------------------------- | ----------------------------------------- | ------------------------------ | | POST | `/v1/sound-generation` | Bait audio natif | `elevenlabs` | | POST | `/v1/music` | Bait audio natif | `music` | | POST | `/v1/music/stream` | Bait audio penstriman | `music` | | POST | `/v1/music/detailed` | Audio multipart natif dan pelan komposisi | `music` | | POST | `/v1/music/detailed/stream` | Metadata SSE natif dan cebisan audio | `music` | | POST | `/v1/music/plan` | Pelan komposisi JSON | `music` | Titik akhir ini melengkapi laluan `/v1/audio/speech`, `/v1/audio/transcriptions`, `/v1/voices`, `/v1/text-to-speech/{voiceId}` dan `/v1/speech-to-text` yang sedia ada. Medan JSON natif dan parameter pertanyaan seperti `output_format` dan `enable_logging` dikekalkan. Respons `/v1/music/detailed` mengekalkan sempadan multipartnya; huraikannya sebagai multipart. `/v1/music/detailed/stream` mengembalikan `text/event-stream` dengan metadata komposisi dan cebisan audio berkod base64 dalam peristiwa SSE. Kesemua enam laluan menyokong prapenerbangan CORS. ```bash export OMNIROUTE_BASE_URL="http://localhost:20128" export OMNIROUTE_API_KEY="your-omniroute-api-key" # Kesan bunyi pendek. Tempoh: 0.5 hingga 30 saat. curl --fail-with-body "$OMNIROUTE_BASE_URL/v1/sound-generation?output_format=mp3_44100_128" \ -H "Authorization: Bearer $OMNIROUTE_API_KEY" \ -H "Content-Type: application/json" \ -d '{"text":"A single soft bell chime","duration_seconds":1,"model_id":"eleven_text_to_sound_v2"}' \ --output effect.mp3 # Tempoh muzik dinyatakan dalam milisaat: 3000 hingga 600000. curl --fail-with-body "$OMNIROUTE_BASE_URL/v1/music?output_format=mp3_44100_128" \ -H "Authorization: Bearer $OMNIROUTE_API_KEY" \ -H "Content-Type: application/json" \ -d '{"prompt":"Gentle instrumental piano","music_length_ms":10000,"force_instrumental":true,"model_id":"music_v1"}' \ --output music.mp3 ``` Gunakan `/v1/music/stream` dengan badan JSON yang sama untuk penghantaran audio secara berperingkat. Komposisi menerima tepat satu daripada `prompt` atau `composition_plan`; `/v1/music/plan` memerlukan `prompt` dan secara pilihan menerima `source_composition_plan`. Skema natif mengekalkan medan pembekal tambahan supaya versi pelan komposisi dan pilihan penalaan halus sampai kepada ElevenLabs. Titik akhir bersatu `/v1/music/generations` juga menerima `elevenlabs/music_v1`, `elevenlabs/music_v2` dan `elevenlabs/music_v2_5`. Dengan sambungan ElevenLabs yang aktif, model ini didedahkan oleh katalog muzik. Titik akhir ini mengembalikan `{"created":...,"data":[{"b64_json":"...","format":"mp3"}]}`. Medan `duration` adalah dalam saat dan dipetakan kepada `music_length_ms`; `music_length_ms` yang dinyatakan secara jelas diutamakan. `instrumental` dipetakan kepada `force_instrumental`, dengan medan natif diutamakan. Gunakan titik akhir penstriman natif untuk penstriman dan titik akhir komposisi natif untuk permintaan yang dipacu hanya oleh pelan komposisi. ```bash curl --fail-with-body "$OMNIROUTE_BASE_URL/v1/music/generations" \ -H "Authorization: Bearer $OMNIROUTE_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"elevenlabs/music_v1","prompt":"Gentle instrumental piano","duration":10,"instrumental":true}' ``` Sekatan titik akhir, model, belanjawan dan sambungan dikenakan sebelum panggilan huluan. Laluan natif mengembalikan kod status huluan dan isi ralat tanpa perubahan, termasuk `402` untuk sekatan pelan dan `429` untuk had kuota. Pengepala `character-cost`, `song-id`, `request-id` dan `retry-after` dikekalkan apabila tersedia. Baki kredit percuma tidak menjamin akses kepada setiap model muzik, format output atau ciri API: ElevenLabs menentukan kelayakan bagi setiap permintaan. Titik akhir bersatu mengekalkan kod status ralat dalam sampul ralat ternormal OmniRoute. Kontrak huluan: [kesan bunyi](https://elevenlabs.io/docs/api-reference/text-to-sound-effects/convert), [komposisi muzik](https://elevenlabs.io/docs/api-reference/music/compose) dan [butiran muzik penstriman](https://elevenlabs.io/docs/api-reference/music/compose-detailed-stream). --- ## Titik Akhir Keserasian | Kaedah | Laluan | Format | | ------ | ----------------------------------------- | ------------------------------------ | | POST | `/v1/chat/completions` | OpenAI | | POST | `/v1/messages` | Anthropic | | POST | `/v1/responses` | OpenAI Responses | | POST | `/v1/embeddings` | OpenAI | | POST | `/v1/images/generations` | OpenAI Images | | POST | `/v1/images/edits` | OpenAI Images (suntingan/inpaint) | | POST | `/v1/videos/generations` | Penjanaan video gaya OpenAI | | POST | `/v1/music/generations` | Penjanaan muzik gaya OpenAI | | POST | `/v1/audio/transcriptions` | OpenAI Audio (STT) | | POST | `/v1/audio/speech` | OpenAI TTS (mengembalikan isi audio) | | POST | `/v1/rerank` | Rerank gaya Cohere/Voyage | | POST | `/v1/classify` | Pengelasan Jina (`api.jina.ai`) | | POST | `/v1/segment` | Segmenter Jina (`segment.jina.ai`) | | POST | `/v1/moderations` | OpenAI Moderations | | GET | `/v1/models` | OpenAI | | POST | `/v1/models/query` | Senarai pendek model yang ditapis | | POST | `/v1/messages/count_tokens` | Anthropic | | GET | `/v1beta/models` | Gemini | | POST | `/v1beta/models/{...path}` | Gemini generateContent | | POST | `/v1/api/chat` | Ollama | | GET | `/api/v1/vscode/{token}/` | Alias katalog OpenAI | | GET | `/api/v1/vscode/{token}/models` | Alias model OpenAI | | POST | `/api/v1/vscode/{token}/chat/completions` | Alias bertoken OpenAI | | POST | `/api/v1/vscode/{token}/responses` | Alias bertoken OpenAI Responses | | POST | `/api/v1/vscode/{token}/api/chat` | Alias bertoken Ollama | | GET | `/api/v1/vscode/{token}/api/tags` | Alias bertoken tag Ollama | Semua laluan POST mengikut bentuk yang sama: `Bearer your-api-key` + isi JSON yang disahkan oleh Zod (`v1RerankSchema`, `v1ModerationSchema`, `v1AudioSpeechSchema`, dan lain-lain, lihat `src/shared/validation/schemas.ts`). Kod 4xx dikembalikan apabila skema gagal. Bagi klien yang tidak dapat melampirkan `Authorization: Bearer ...`, OmniRoute juga menerima kunci API dalam URL melalui sama ada keserasian rentetan pertanyaan (`?token=...`, `?apiKey=...`, `?api_key=...`, `?key=...`) atau titik akhir khusus `/api/v1/vscode/{token}/...` yang didokumenkan di bawah. ```bash # Rerank (penyedia pendaftaran awan, atau nod penyedia yang serasi dengan OpenAI sebagai "/") POST /v1/rerank { "model": "jina-ai/jina-reranker-v3.5", "query": "...", "documents": ["..."] } # Pengelasan Jina (kredensial Foundation API) POST /v1/classify { "model": "jina-embeddings-v5-text-small", "input": ["..."], "labels": ["a", "b"] } # Segmenter Jina POST /v1/segment { "content": "...", "return_chunks": true } # Carian Jina (s.jina.ai; alias penyedia: jina-search, jina-ai, jina) POST /v1/search { "query": "...", "provider": "jina-search" } # Moderations POST /v1/moderations { "model": "omni-moderation-latest", "input": "..." } # TTS — mengembalikan isi audio/mpeg (atau format yang diminta) POST /v1/audio/speech { "model": "openai/tts-1", "input": "Hello", "voice": "alloy" } # TTS Soniox memerlukan bahasa dan suara: `language` lalai kepada "en"; `voice` yang tiada # atau nama suara stok OpenAI (alloy, nova, …) akan menjadi "Adrian" POST /v1/audio/speech { "model": "soniox/tts-rt-v1", "input": "Xin chào", "voice": "Adrian", "language": "vi" } # Suntingan imej (multipart) POST /v1/images/edits -F image=@input.png -F prompt="..." -F mask=@mask.png # Penjanaan video / muzik (ID model berawalan penyedia) POST /v1/videos/generations { "model": "runway/gen-3", "prompt": "..." } POST /v1/music/generations { "model": "kie/suno-v4.0", "prompt": "..." } ``` > **Nod penyedia rerank:** `POST /v1/rerank` juga menghala ke nod penyedia yang serasi dengan OpenAI > (oMLX, vLLM, Infinity, TEI di belakang get laluan, …) yang dialamatkan sebagai `/`. Nod > gelung balik (`localhost`, `127.0.0.1`, `172.16.0.0/12`) sentiasa layak, begitu juga nama hos yang > disenaraikan oleh operator dalam `OMNIROUTE_LOCAL_PROVIDER_NODE_HOSTS` (contohnya nama perkhidmatan > Docker/Compose seperti `http://reranker:8080/v1`; nod ini dipanggil secara terus, tidak melalui > `HTTP(S)_PROXY` atau proksi yang dipasangkan pada sambungan). Nod pada mana-mana > hos lain — mesin LAN atau rakan Tailscale — hanya layak apabila operator mendayakan > bendera ciri `RERANK_REMOTE_PROVIDER_NODES` **dan** URL asas nod melepasi dasar URL keluar penyedia > (`OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS` / `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS`). > Langkah rerank enjin memori memanggil laluan ini melalui > gelung balik, jadi peraturan yang sama mengawal `rerankProviderModel` dalam tetapan Memori. > > **Bentuk pelayan tempatan:** nod dipanggil pada `/v1/rerank` dan, apabila 404, pada `/rerank` > (Infinity, TEI). Isi huluan membawa kedua-dua ejaan Cohere/OpenAI (`documents`, > `return_documents`) dan ejaan TEI (`texts`, `return_text`), dan respons huluan > dinormalkan kepada sampul Cohere: `[{index, score, text}]` kosong milik TEI, `{results: [{index, score}]}` > daripada get laluan nipis, serta `{data: [...]}` gaya Voyage semuanya dikembalikan kepada klien sebagai > `{results: [{index, relevance_score, document?}]}`, diisih mengikut skor dan dihadkan kepada `top_n`. > **Penemuan nod penyedia:** model pada nod penyedia yang serasi dengan OpenAI muncul dalam `GET /v1/models` > di bawah awalan nod. Baris yang tidak mempunyai metadata titik akhir (tipikal untuk penyenaraian `/v1/models` tempatan) > mewarisi `apiType` nod, jadi model nod `embeddings` mempunyai `type: "embedding"` dan > model nod `rerank` mempunyai `type: "rerank"` dan bukannya lalai kepada chat; `supportedEndpoints` eksplisit > pada baris yang disegerakkan atau ditambah secara manual tetap mempunyai keutamaan. ### Laluan Penyedia Khusus ```bash POST /v1/providers/{provider}/chat/completions POST /v1/providers/{provider}/embeddings POST /v1/providers/{provider}/images/generations ``` Awalan penyedia ditambah secara automatik jika tiada. Model yang tidak sepadan mengembalikan `400`. --- ## API Fail Titik akhir fail serasi OpenAI untuk input/output kelompok dan muat naik fail mengikut tujuan. | Kaedah | Laluan | Perihalan | | ------ | ------------------------ | ------------------------------------------------------------------------------------------------------------------- | | POST | `/v1/files` | Muat naik fail (multipart: `file`, `purpose`, `expires_after[anchor]`, `expires_after[seconds]`) — maksimum 512 MiB | | GET | `/v1/files` | Senaraikan fail untuk kunci API yang disahkan | | GET | `/v1/files/[id]` | Dapatkan metadata fail | | DELETE | `/v1/files/[id]` | Padam fail | | GET | `/v1/files/[id]/content` | Strim isi badan fail mentah kembali | **Pengesahan:** Kunci API Bearer — fail dilingkungi mengikut kunci API melalui `getApiKeyRequestScope`. Satu kunci hanya boleh melihat, memuat turun dan memadam failnya sendiri; sesi papan pemuka tanpa kunci membaca keseluruhan tika; fail tanpa pemilik (muat naik tanpa nama atau melalui sesi papan pemuka) dinafikan kepada setiap pemanggil bukan sesi. `GET /v1/files` menolak pemanggil tanpa nama — serta kunci yang diberikan tetapi tidak dapat diselesaikan — dengan `401` walaupun `REQUIRE_API_KEY=false`, dan bukannya menyenaraikan fail semua penyewa (GHSA-m3hp-hq9g-fpmv, GHSA-2jm2-mpx8-6523). --- ## API Kelompok Pemprosesan kelompok yang serasi OpenAI. | Kaedah | Laluan | Perihalan | | ------ | ------------------------- | ------------------------------------------------------------------------------------------------------------- | | POST | `/v1/batches` | Cipta kelompok — badan disahkan oleh `v1BatchCreateSchema` (`input_file_id`, `endpoint`, `completion_window`) | | GET | `/v1/batches` | Senaraikan kelompok | | GET | `/v1/batches/[id]` | Dapatkan status kelompok + `request_counts` | | DELETE | `/v1/batches/[id]` | Padam kelompok yang telah selesai/gagal | | POST | `/v1/batches/[id]/cancel` | Batalkan kelompok yang sedang diproses | **Pengesahan:** Kunci API Bearer. Kelompok dilingkungi mengikut kunci API di bawah peraturan tiga hala yang sama seperti fail: hanya kunci sendiri, sesi papan pemuka meliputi keseluruhan tika, rekod tanpa pemilik dinafikan kepada setiap pemanggil bukan sesi (pengambilan, pemadaman, pembatalan dan semakan `input_file_id` semasa penciptaan). `GET /v1/batches` menolak pemanggil tanpa nama dengan `401` walaupun `REQUIRE_API_KEY=false`. --- ## Cari API abstraksi penyedia Web/search (Tavily, Brave, Exa, Serper, dll.). | Kaedah | Laluan | Penerangan | | ------ | ---------------------- | --------------------------------------------------------------------------------------------------- | | GET | `/v1/search` | Senaraikan keupayaan + pembekal carian yang dikonfigurasikan | | POST | `/v1/search` | Jalankan pertanyaan carian — body yang disahkan oleh `v1SearchSchema`, menyokong caching/coalescing | | GET | `/v1/search/analytics` | Statistik hit/latency/cache setiap pembekal | **Pengesahan:** Kunci API pembawa (`extractApiKey` + `isValidApiKey`). Dasar carian dikuatkuasakan melalui `enforceApiKeyPolicy`. **Auto-select:** without `provider`, the cheapest provider with a configured connection runs first and the next cheapest is the failover. Free last-resort providers (`duckduckgo-free`) are used only when nothing else is configured. A self-hosted SearXNG counts as configured once its connection stores a real `baseUrl` (not the catalog default `http://localhost:8888/search`): it then ranks as a $0 provider ahead of keyed ones, with the cheapest keyed provider as failover, including when SearXNG answers 400, 401, 403 or 404. A `baseUrl` that is not a valid `http(s)` URL or that points at a cloud-metadata address does not count. A SearXNG connection that stores a token ranks this way only over `https://` or loopback `http://`. Over remote plain `http://` it is never a failover and stays a last resort, used only when no other provider is configured or when requested by name, so it does send the token in cleartext in those two cases. ### Exa dan Tavily `provider_options` Exa dan Tavily membaca medan khusus pembekal daripada beg ruang nama: `provider_options.exa` (atau `provider_options["exa-search"]`) dan `provider_options.tavily` (atau `provider_options["tavily-search"]`). Hanya kekunci di bawah dimajukan. Setiap satu disemak terhadap skema Zod sendiri dalam `open-sse/handlers/search/providerOptionsPassthrough.ts`, dan kunci dengan jenis yang salah digugurkan. Sebarang kunci lain diabaikan, termasuk auth, base URL, `stream` dan `outputSchema`. Kekunci rata yang digunakan oleh pembekal lain (`cx`, `depth`, ...) berfungsi seperti sebelum ini. | Pembekal | Medan peringkat atasan | Bersarang | | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | Exa | `type`, `category`, `userLocation`, `moderation`, `additionalQueries`, `objective`, `systemPrompt`, `compliance` (primitif rata), `startPublishedDate`, `endPublishedDate` | `contents.{text, highlights, summary, extras, livecrawlTimeout, maxAgeHours}` digabungkan ke atas `{ text: true, highlights: true }` lalai | | Tavily | `search_depth`, `chunks_per_source`, `time_range`, `start_date`, `end_date`, `include_published_date`, `filter_by_published_date`, `include_answer`, `include_raw_content`, `include_images`, `include_image_descriptions`, `include_favicon`, `include_domains_mode`, `language`, `filter_by_language`, `auto_parameters`, `exact_match`, `include_usage`, `safe_search` | — | Medan generik sentiasa menang: `query`, `max_results`, `filters` (domain), `country` dan topik yang diperoleh daripada `search_type`. Pada Exa, `search_type: "news"` mengekalkan `category: "news"`. Tavily juga menerima `search_type: "finance"` (`topic: "finance"`). Kos carian Firecrawl direkodkan bagi setiap blok permulaan bagi 10 hasil yang dikembalikan, pada $0.002 (2 kredit) satu blok dan sekurang-kurangnya satu blok setiap panggilan ( [Pengebilan Firecrawl](https://docs.firecrawl.dev/billing) ): 11 hasil kos $0.004. `time_range` generik kini mencapai kedua-dua penyedia: Exa mendapat `startPublishedDate` ( cap waktu ISO ) dan Tavily mendapat `start_date` (`YYYY-MM-DD`). Tarikh eksplisit dalam `provider_options` mengatasi tarikh yang dipetakan. Keputusan Exa mengekalkan `id`, `highlights` (setiap sorotan, bukan sahaja yang pertama digunakan sebagai `snippet`), `highlight_scores`, `summary`, `subpages`, `entities` dan `extras` dalam `provider_raw`. Hasil tavily kekalkan `images` dan `favicon`. Kos carian pautan direkodkan pada $0.005 untuk `depth` `fast` dan `standard` dan $0.05 untuk `deep` ( [Harga pautan](https://docs.linkup.so/pages/documentation/development/pricing) ), sama ada `depth` datang daripada `provider_options` atau tetapan sambungan. Exa `type: "lite"` (Exa 3.0) menerima set medan yang lebih kecil dan menolak keseluruhan permintaan apabila mana-mana medan lain ditetapkan. Untuk lite, `additionalQueries`, `systemPrompt` dan setiap kekunci `contents` kecuali `text` dan `highlights` digugurkan sebelum panggilan. `subpages`, `subpageTarget`, `highlights.numSentences` dan `highlights.highlightsPerUrl` yang ditamatkan tidak dimajukan lagi. Perakaunan kos ialah `costPerQuery` pendaftaran rata , kecuali untuk Exa, yang mengikut harga Exa sendiri: $0.007 setiap panggilan untuk `auto` (dan `fast` legasi ) atau $0.004 untuk `lite` (dan `instant` warisan ), meliputi 10 keputusan; $0.001 untuk setiap keputusan selanjutnya; dan $0.001 setiap hasil yang dikembalikan apabila `contents.summary` ditetapkan. Tavily direkodkan pada 1 kredit ($0.008) untuk `search_depth` `basic`, `fast` dan `ultra-fast`, dan 2 kredit ($0.016) untuk `advanced` ( [Tavily API credits](https://docs.tavily.com/documentation/api-credits) ). Panggilan dengan `auto_parameters: true` yang Tavily naik taraf kepada lanjutan masih direkodkan pada 1 kredit. --- ## API Ambilan Web Ekstrak kandungan daripada URL melalui penyedia ambilan web yang dikonfigurasi (Firecrawl, Jina Reader, Tavily Extract, TinyFish Fetch, Nimble Extract, Parallel Extract). Parallel Extract (`parallel-search`, kunci API yang sama seperti Parallel Search) hanya mengembalikan Markdown — sebarang `format` lain ialah `400` — dan mengehadkan kandungan kepada 100,000 aksara. Apabila halaman sasaran itu sendiri tidak dapat diekstrak, upstream melaporkannya dalam HTTP 200; OmniRoute mendedahkannya sebagai `422` dengan mesej tetap. | Kaedah | Laluan | Perihalan | | ------ | --------------- | -------------------------------------------------------- | | POST | `/v1/web/fetch` | Ambil/kerik URL — badan disahkan oleh `v1WebFetchSchema` | **Pengesahan:** Kunci API Bearer (`extractApiKey` + `isValidApiKey`). Dasar dikuatkuasakan melalui `enforceApiKeyPolicy`. **Fallback peka kuota (#8297):** apabila tiada `provider` yang dinyatakan secara eksplisit, kumpulan (`firecrawl` → `jina-reader` → `tavily-search` → `tinyfish` → `nimble-search` → `parallel-search`) dilalui mengikut susunan keutamaan tetap (isi dahulu) — penyedia yang dihadkan kadar tetapi telah dikonfigurasi dilangkau dan bukannya memendekkan permintaan, manakala kegagalan upstream yang boleh dicuba semula/berkaitan kuota (HTTP 429 sentiasa; 402/403 untuk peringkat percuma Firecrawl/Tavily/TinyFish yang bergaya kuota — bukan untuk Jina Reader, dan tidak pernah untuk permintaan buruk 400 biasa) diteruskan kepada penyedia bertauliah berikutnya yang belum dicuba pada masa permintaan. Apabila setiap penyedia dalam kumpulan telah habis digunakan, endpoint mengembalikan satu `429` (dengan pengepala `Retry-After`) dan bukannya `400` generik yang sebelumnya. Apabila `provider` eksplisit diminta, **tiada fallback senyap** — penyedia eksplisit yang dihadkan kadar atau gagal memaparkan ralatnya sendiri (`429` jika dihadkan kadar, selain itu status upstream). --- ## Penstriman WebSocket ```bash GET /v1/ws?handshake=1 ``` Mengesahkan jabat tangan naik taraf WebSocket dan mengembalikan mesej contoh protokol wayar (`request`, `cancel`). Bingkai WS sebenar dikendalikan oleh pelayan WS terbina dalam di luar jadual laluan Next.js. **Pengesahan:** Kunci API Bearer semasa jabat tangan. ### API Responses melalui WebSocket (codex sahaja) ```bash # Hos:port yang sama seperti API HTTP (lalai 20128); naik taraf sambungan: wscat -c "ws://localhost:20128/v1/responses?api_key=" # (atau: -H "Authorization: Bearer ") # Bingkai pertama MESTI ialah response.create: { "type": "response.create", "model": "gpt-5.5", "input": [ { "role": "user", "content": "hi" } ] } ``` Proksi Responses-API-over-WebSocket disambungkan **secara eksklusif kepada `codex`** (backend ChatGPT). Ia mendengar pada port yang sama seperti API/papan pemuka di laluan `/v1/responses`, `/responses`, dan `/api/v1/responses`. Pada bingkai `response.create` pertama, ia mengesahkan + membuat persediaan melalui jambatan dalaman `codex-responses-ws`, memilih sambungan OAuth codex, dan membuat terowong ke `wss://chatgpt.com/backend-api/codex/responses` melalui pengangkutan `wreq-js`. Model bukan codex ditolak (`codex_ws_provider_required`). Untuk penghalaan perkongsian kuota gunakan `model: "qtSd//codex/"`. Dilaksanakan dalam `app/server-ws.mjs` + `scripts/dev/responses-ws-proxy.mjs` + `src/app/api/internal/codex-responses-ws/route.ts`. **Pengesahan:** Kunci API Bearer semasa jabat tangan. Pelayan HTTP terbina dalam (`server-ws.mjs`) mesti menjadi titik masuk aktif (secara lalai, ia adalah aktif apabila `app/server-ws.mjs` wujud). #### ID model: gunakan ID ChatGPT tanpa awalan (tiada awalan `codex/`) **Codex CLI** OpenAI mengesahkan nama model pada pihak klien apabila `supports_websockets = true` dan **menolak** ID yang diawali penyedia seperti `codex/gpt-5.5` (`The 'codex/gpt-5.5' model is not supported when using Codex with a ChatGPT account`). Hantar ID **tanpa awalan** (contohnya `gpt-5.5`). Jambatan OmniRoute hanya untuk codex, jadi ia menyelesaikan semula ID tanpa awalan sebagai model codex (`resolveCodexWsModelInfo`) sebelum membuat terowong ke upstream — walaupun `gpt-5.5` tanpa awalan sebaliknya akan dihalakan kepada penyedia lain melalui HTTP. #### Mengkonfigurasi Codex CLI OpenAI Halakan Codex CLI ke OmniRoute dengan menambahkan penyedia tersuai yang menyokong WebSocket kepada `~/.codex/config.toml` (gunakan `CODEX_HOME` berasingan untuk mengelakkan pengubahsuaian konfigurasi sedia ada): ```toml model = "gpt-5.5" # id tanpa awalan — BUKAN "codex/gpt-5.5" model_provider = "omniroute" [model_providers.omniroute] name = "OmniRoute (WS)" base_url = "http://localhost:20128/v1" # tiada garis miring di hujung; URL WS diterbitkan daripadanya (gunakan https/wss dalam produksi) wire_api = "responses" # satu-satunya nilai yang disokong sejak Feb 2026 supports_websockets = true # mendayakan pengangkutan Responses-over-WS env_key = "OMNIROUTE_API_KEY" # menyimpan kunci API OmniRoute (Bearer) ``` ```bash export OMNIROUTE_API_KEY=sk-... # kunci API OmniRoute (sebarang kunci jika REQUIRE_API_KEY=false) codex exec "Responda apenas: PONG" ``` CLI menaik taraf `base_url + /responses` kepada WebSocket dan OmniRoute membuat terowong ke sambungan OAuth codex yang dipilih. Divalidasi dari hujung ke hujung terhadap pelayan tempatan: ChatGPT mengembalikan `codex.rate_limits` + `response.created` dan menstrim pelengkapan. --- ## Pelaporan Kuota & Isu | Kaedah | Laluan | Perihalan | | ------ | ------------------- | -------------------------------------------------------------------------------------------------- | | GET | `/v1/quotas/check` | Pra-pengesahan kuota untuk `provider` + `accountId` sebelum mengeluarkan kunci berdaftar | | POST | `/v1/issues/report` | Laporkan kegagalan pengeluaran kuota/kunci kepada GitHub (memerlukan `GITHUB_ISSUES_REPO` + token) | **Pengesahan:** Kunci API Bearer (`isAuthenticated`). ### Pemulihan sesi kuota (pilihan) Permintaan `POST /v1/chat/completions` atau `POST /v1/responses` tanpa penstriman yang gagal dengan ralat kuota terminal (`402`/`429`/`503` yang isi kandungannya menyatakan kuota atau kredit telah habis) boleh diletakkan sementara dan dimainkan semula kemudian dan bukannya memulangkan ralat tersebut. Pemanggil memilih fungsi ini untuk setiap permintaan menggunakan tiga pengepala: | Pengepala | Nilai | | ---------------------------- | ----------------------------------------------------- | | `x-omniroute-quota-recovery` | `auto` | | `x-omniroute-session` | id sesi, `[A-Za-z0-9._:-]{1,128}` | | `x-omniroute-recovery-turn` | id giliran yang unik dalam sesi (peraturan yang sama) | Hanya giliran `stream: false` tanpa alat, sejarah alat atau `previous_response_id`, dan tanpa pin `x-omniroute-connection`, layak diproses, serta `STORAGE_ENCRYPTION_KEY` mesti ditetapkan (permintaan disimpan secara disulitkan sehingga 24 jam). Respons kemudiannya ialah `202` dengan `recovery.poll`; lakukan tinjauan pada `GET /v1/quota-recoveries/{id}` (`202` sementara menunggu, `200` dengan isi kandungan yang dipulihkan apabila selesai) atau batalkan dengan `DELETE`. Tiket hanya boleh dilihat oleh kunci API yang menciptanya. Main semula yang keputusannya tidak pasti akan berakhir dalam `needs_confirmation` dan bukannya dihantar dua kali. Sumber: `src/lib/quota/quotaSessionRecovery.ts`. --- ## Penggunaan layan diri (`/api/usage/om-usage`) Mana-mana kunci API boleh baca** miliknya** penggunaan dan kuota — tiada pengesahan pengurusan. Ini ialah titik akhir yang digunakan oleh pelanggan (CLI, panel OmniCopilot ) untuk menunjukkan perbelanjaan mereka kepada pemegang kunci. ```bash # Text form (the historical contract — plain text for a terminal) curl -H "Authorization: Bearer " \ http://localhost:20128/api/usage/om-usage # Structured form — what a UI consumes curl -H "Authorization: Bearer " \ "http://localhost:20128/api/usage/om-usage?format=json" ``` Kuncinya mesti ada**`allowUsageCommand`** didayakan (dimatikan secara lalai — pengurus kunci API papan pemuka menogolnya setiap kekunci). Tanpanya titik akhir menjawab `403`. `?format=json` mengembalikan bentuk yang didiskriminasi supaya pemanggil tidak pernah membaca medan data daripada penolakan. Mengenai kejayaan: ```jsonc { "allowed": true, // present only when the key opted into per-key usage limits (daily/weekly/5-hour USD): "personal": { "dailySpentUsd": 1.25, "dailyLimitUsd": 5, "dailyResetAtIso": "…", "weeklySpentUsd": 8, "weeklyLimitUsd": 20, "weeklyResetAtIso": "…" /* … */, }, // the selected provider quota snapshot, or null when nothing is cached yet: "provider": { "connectionId": "…", "provider": "claude", "plan": "…", "quotas": {/* … */} }, // every connection's snapshot, so a UI can render several providers side by side: "providers": [ { "connectionId": "…", "provider": "claude" /* … */ }, { "provider": "codex" /* … */ }, ], } ``` Apabila penolakan ( kunci `401` buruk / `403` tidak dibenarkan) laluan yang sama mengembalikan `{ "allowed": false, "error": { "message": "…" } }` — `personal`/`provider` yang sekarang-tetapi-kosong (kunci dibenarkan, tiada apa yang dipelajari lagi) ialah keadaan yang berbeza daripada penolakan, dan hanya bentuk JSON yang membezakannya. **Pengesahan:** kunci API Pembawa pemanggil sendiri, disahkan dengan `isValidApiKey` — ini _bukan_ permukaan pengurusan (`/api/keys/…`), yang kekal di belakang `requireManagementAuth`. ### Peratusan Kuota Dilaraskan Mentah lwn Cutoff Apabila menggunakan `/api/usage/om-usage`, pemanggil harus perhatikan perbezaan antara peratusan yang dikemukakan oleh** output teks biasa** dan berstruktur** keluaran JSON** : | Aspek | Format teks biasa (`/api/usage/om-usage` / `@@om-usage`) | format JSON (`?format=json`) | | :------------------- | :------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------- | | **Medan keluaran** | `NN% left` (cth, `20% left`) | `provider.quotas` / `providers[].quotas` | | **Pengukuran** | **Elaun boleh guna terlaras cutoff** : baki kapasiti melebihi ambang cutoff | **Kuota huluan mentah** : pengukuran pembekal yang tidak diselaraskan | | **Skala pemotongan** | Diskalakan melalui `effectiveRemainingPercent()` supaya rizab dilindungi dibaca sebagai `0% left` | Tiada (nilai syot kilat mentah seperti yang dilaporkan oleh pembekal) | | **Data ambang** | Digabungkan ke dalam peratusan yang dipaparkan | Disimpan dalam `quotaWindowThresholds` setiap sambungan (atau lalai pelayan) | | **Pengguna utama** | CLIs interaktif, gesaan terminal, pengendali manusia | Penyepaduan program, papan pemuka, analitik, penjejak pengebilan | #### Formula Pelarasan Cutoff OmniRoute menyokong pemotongan kuota proaktif untuk mengelakkan keletihan huluan (dikonfigurasikan melalui sambungan `quotaWindowThresholds`, lalai pembekal atau tetapan daya tahan global). Apabila ambang cutoff (cth, `cutoff = 25%`) aktif pada tetingkap kuota, pemapar teks mengira baki elaun sebagai: - Jika `remaining <= cutoff`: kembalikan `0%`. - Jika `remaining > cutoff`: kembalikan `((remaining - cutoff) / (100 - cutoff)) * 100`. Output teks yang diformat membulatkan ini kepada integer terdekat (`Math.round(...)`). #### Contoh Ilustrasi Pertimbangkan tetingkap pembekal dengan** 60% penggunaan mentah** (oleh itu** 40% baki kuota mentah** ) dan dikonfigurasikan** Potongan kuota baki 25%.** ambang: | Perwakilan | Pengiraan | yang tinggal | Tersirat Digunakan | | :------------------------------- | :------------------------------------------------- | :----------: | :--------------------------------------: | | **JSON mentah (`?format=json`)** | Syot kilat hulu (`quotas[window]`) | **40%** | **60%** | | **Format teks (`NN% left`)** | `((40 - 25) / (100 - 25)) * 100 = (15 / 75) * 100` | **20%** | **80%** (jika mengira `100 - remaining`) | - **Mengapa teks menunjukkan baki 20%:** Daripada 40% kuota fizikal yang tinggal pada akaun, 25% dikhaskan oleh dasar cutoff. Pemanggil hanya mempunyai 15% daripada 75% ruang kepala yang boleh digunakan sebelum penghala berhenti menghala ke sambungan ini. Penskalaan memastikan sambungan menandakan keletihan (`0% left`) tepat apabila penghalaan akan berhenti. - **Mengapa JSON mengekalkan nilai mentah:** Muatan JSON mengembalikan syot kilat pembekal yang tepat (`UsageSnapshot`) supaya alatan luaran mempunyai akses kepada penggunaan huluan kebenaran tanah dan `quotaWindowThresholds` peringkat sambungan tanpa penskalaan lossy sebelah pelayan. #### Panduan Migrasi Pengguna Jika penyepaduan luaran (seperti pemalam editor atau sambungan ejen) sebelum ini mengikis titik akhir teks (`NN% left`) dan mengira peratusan yang digunakan sebagai `100 - NN`, berhijrah ke `?format=json` bermakna: - Membaca nilai JSON mentah akan mencerminkan** penggunaan huluan sebenar** (60% digunakan dalam contoh di atas). - Jika penyepaduan ingin mengekalkan semantik elaun boleh guna titik akhir teks, ia boleh menilai formula yang berkesan di sisi klien menggunakan `quotaWindowThresholds` untuk penggantian peringkat sambungan. --- ## Cache Semantik ```bash # Dapatkan statistik cache GET /api/cache/stats # Kosongkan semua cache DELETE /api/cache/stats ``` Contoh respons: ```json { "semanticCache": { "memorySize": 42, "memoryMaxSize": 500, "dbSize": 128, "hitRate": 0.65 }, "idempotency": { "activeKeys": 3, "windowMs": 5000 } } ``` ### Kesan kependaman Cache semantik HIT menyampaikan respons daripada cache **tanpa panggilan upstream**, jadi `X-OmniRoute-Response-Latency` yang dilaporkan adalah hampir sifar (tanpa mengira kependaman upstream asal). Klien yang sensitif terhadap kependaman (penanda aras, pemantauan p50/p99) hendaklah menyemak pengepala respons `X-OmniRoute-Cache-Latency`: | Nilai | Maksud | | ----------- | -------------------------------------------------------------------------- | | `synthetic` | Respons disampaikan daripada cache; kependaman bukan masa upstream sebenar | | _(absent)_ | Respons daripada panggilan upstream sebenar | ### Pintasan cache mengikut kunci Kunci API boleh memilih untuk tidak menggunakan bacaan cache semantik melalui `cacheDefaultMode`: | Nilai | Tingkah laku | | -------- | -------------------------------------------------------------- | | `legacy` | Tingkah laku cache biasa (lalai) | | `bypass` | Langkau carian cache sepenuhnya; sentiasa menghubungi upstream | Tetapkan semasa penciptaan kunci (`POST /api/keys`) atau kemas kini (`PATCH /api/keys/[id]`): ```json { "cacheDefaultMode": "bypass" } ``` ### Pintasan cache mengikut permintaan Mana-mana permintaan boleh memintas cache tanpa mengira tetapan kunci: ``` X-OmniRoute-No-Cache: true ``` --- ## Keserasian Pengurusan CLIProxyAPI OmniRoute menjawab tiga endpoint pengurusan [CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI) yang dipanggil oleh papan pemuka penggunaan untuk membaca had langganan Claude dan Codex (contohnya sumber had penggunaan `cliproxy` T3 Code). Halakan URL asas klien kepada OmniRoute dan gunakan kunci API dengan skop `manage` sebagai kunci pengurusan. Laluan ini disediakan di `/v0/management/*` dan `/api/v0/management/*`. | Kaedah | Laluan | Penerangan | | ------ | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | GET | `/v0/management/auth-files` | Sambungan OAuth Claude dan Codex sebagai `{ files: [{ id, auth_index, provider, email, disabled, id_token }] }`. Tiada token | | POST | `/v0/management/api-call` | Isi `{ auth_index, method, url, header?, data? }`. Menghantar satu permintaan yang dibenarkan menggunakan token akaun dan mengembalikan `{ status_code, body }` | | POST | `/v0/management/reset-quota` | Isi `{ auth_index }`. Mengosongkan tempoh bertenang sambungan, sekatan model dan tempoh bertenang mengikut skop Codex bagi satu akaun | - `auth_index` ialah id sambungan OmniRoute. `provider` ialah `claude` atau `codex` (sambungan OAuth sahaja; pembekal kunci API `anthropic` tidak disenaraikan). Untuk Codex, `id_token.chatgpt_account_id` ialah id ruang kerja yang disimpan dan `plan_type` ialah pelan yang disimpan. - `api-call` bukan proksi generik. Ia hanya menerima Claude `GET https://api.anthropic.com/api/oauth/usage` dan Codex `GET https://chatgpt.com/backend-api/wham/usage`, `GET .../wham/rate-limit-reset-credits` serta `POST .../wham/rate-limit-reset-credits/consume`, setiap satunya hanya untuk akaun pembekal yang sepadan. Apa-apa yang lain mengembalikan `403` tanpa menghubungi upstream. Pengepala `Authorization` pemanggil (termasuk ruang letak `$TOKEN$`) diabaikan: OmniRoute memasukkan token akses sambungan, menyegarkannya terlebih dahulu apabila hampir tamat tempoh, dan hanya memajukan pengepala yang dibenarkan (`anthropic-beta`; `OpenAI-Beta`, `Originator`, `Chatgpt-Account-Id`; `Accept`, `Content-Type`). `Chatgpt-Account-Id` yang tiada akan menggunakan id ruang kerja yang disimpan secara lalai. Permintaan tamat masa selepas 15 saat dan menggunakan proksi sambungan. - `reset-quota` membiarkan keadaan terminal (banned, expired, credits_exhausted) tanpa perubahan. `auth_index` yang tidak dikenali mengembalikan `404`. **Pengesahan:** sesi papan pemuka atau kunci API berskop `manage`, diperlukan walaupun log masuk dilumpuhkan (laluan tersebut berada dalam `ALWAYS_PROTECTED_API_PATHS`). Kunci yang hanya mempunyai keupayaan inferens menerima `403`. Sumber: `src/lib/cliproxyCompat/managementApi.ts`. --- ## Papan pemuka & Pengurusan Laluan pengurusan (`/api/*` kecuali auth/login awam ) adalah** bukan** dibenarkan oleh kunci API inferens biasa. Keluarga kelayakan, skop dan contoh curl: [Pengesahan Pengurusan](../guides/MANAGEMENT-AUTH.md). ### Pengesahan | Titik akhir | Kaedah | Penerangan | | ----------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/auth/login` | POST | Log masuk | | `/api/auth/logout` | POST | Log keluar | | `/api/settings/require-login` | GET/POST | Status log masuk (GET, awam). POST menetapkan kata laluan / togol log masuk: operator-hanya apabila kata laluan wujud (sesi papan pemuka, CLI tempatan, atau log masuk dilumpuhkan kekunci — API dan token `oma_` mendapat `403`); sesi papan pemuka menghantar `currentPassword` untuk menggantikan kata laluan | ### Pengurusan Pembekal | Titik akhir | Kaedah | Penerangan | | --------------------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/providers` | GET/POST | Senaraikan / buat pembekal | | `/api/providers/[id]` | GET/PUT/DELETE | Urus pembekal | | `/api/providers/[id]/test` | POST | Uji sambungan pembekal | | `/api/providers/[id]/models` | GET | Senaraikan model pembekal | | `/api/providers/validate` | POST | Sahkan konfigurasi pembekal | | `/api/providers/bulk` | POST | Pukal tambah kunci API untuk pembekal ONE | | `/api/providers/import` | POST | Import LIST pembekal heterogen daripada fail CSV/JSON yang dihuraikan (#6836); keputusan separa-kegagalan setiap baris | | `/api/provider-nodes*` | Macam-macam | Pengurusan nod pembekal | | `/api/provider-models` | GET/POST/PUT/PATCH/DELETE | Model tersuai dan penggantian setiap model (tambah, kemas kini, hide/show, padam) | | `/api/provider-models/validate-and-add` | POST | Pengesahan sambungan ketat yang disahkan pengurusan, ikut serta dan pendaftaran model tersuai atom; lihat [Pengesahan model](../guides/MODEL-VALIDATION.md) | Untuk model synced/imported, `PUT /api/provider-models` menerima `provider`, `modelId`, dan `maxOutputTokenOverride`: integer positif menetapkan had token output manual dan `null` mengosongkannya untuk memulihkan lalai. `GET /api/provider-models?provider=` mengembalikan nilai ini dalam `modelOutputOverrides`, termasuk model tanpa baris model tersuai. Penggantian menggunakan keupayaan `max_output_tokens` masa jalan dan bertahan dalam penyegerakan semula model. Halaman penyedia serasi OpenAI menawarkan model kawalan dan penandaan edit/clear yang sama dengan sokongan penglihatan yang jelas. Pada nod pembekal yang serasi, laluan tulis (`POST`, `PUT`, `PATCH`, `DELETE` dan `/api/provider-models/validate-and-add`) menyimpan id model sebagai id huluan kosong: id yang ditampal daripada penyenaraian awalan mempunyai sebarang tindanan utama awalan nod itu sendiri runtuh dan respons menggemakan id yang disimpan. Id yang dipotong oleh penyedia kanonik (cth `nvidia/nemotron-…`) disimpan secara verbatim. `/v1/models` tidak pernah mengeluarkan id `//` bertindan. Nod Penyelesaian Sembang Tersuai menyesuaikan penarikan diri penaakulan eksplisit ke bahagian belakang huluan. Ujian sambungan yang berjaya secara automatik memilih kawalan templat sembang untuk setiap ID model tepat yang entri `/models` membuktikan nilai `owned_by` yang diiktiraf: `vllm`, `sglang`, atau `llamacpp`. Pembalut serasi OpenAI lutsinar boleh mengekalkan kemasukan model asal di dalam objek `openai` bersarang; pengesanan mengikuti sehingga tiga sampul surat tersebut. Model dengan pemilikan yang hilang, tidak diketahui atau bercanggah mengekalkan gelagat OpenAI biasa. Pengesanan menggunakan semula permintaan katalog sedia ada, tidak menjana token penyiapan dan tidak sah apabila titik akhir sambungan berubah. Untuk menyematkan gelagat bagi bahagian belakang yang tidak mendedahkan metadata itu, gunakan kemas kini separa pembekal sedia ada API: ```json { "providerSpecificData": { "reasoningControl": "chat-template" } } ``` Hantar badan tu dengan `PUT /api/providers/`. Sehubungan itu, usaha penaakulan eksplisit `none` dihantar sebagai `chat_template_kwargs.thinking=false` dan `chat_template_kwargs.enable_thinking=false`. Nilai templat asli yang eksplisit kekal berwibawa melainkan peraturan penaakulan sebelah pelayan memaksa usaha. Tetapan hanya digunakan apabila sambungan serasi OpenAI tersuai menghantar badan Selesai Sembang; Permintaan respons dan pembekal biasa mengekalkan bentuk permintaan asal mereka. Tetapkan `reasoningControl` kepada `openai` untuk memaksa laluan OpenAI `reasoning_effort` biasa, atau tinggalkan it/set kepada `null` untuk menggunakan pengesanan automatik. Pengelas mod auto mod Claude Kod meminta pemikiran asli lalai untuk dilumpuhkan apabila ia tidak mengandungi kawalan penaakulan eksplisit. Pengesanan menggunakan penanda sistem pengelas dalam permintaan format Claude, bukan nama model atau had penyiapan. Kawalan badan eksplisit, pengepala effort/thinking yang disokong, peraturan penghalaan dan usaha model yang diselesaikan mengekalkan keutamaan sedia ada mereka. Kedua-dua peringkat pengelas mengekalkan gesaan, had penyelesaian, urutan hentian dan keputusan kebenaran huluan yang sebenar; peringkat kedua masih boleh menghasilkan penaakulan boleh dilihat yang diminta sebagai teks biasa. ### OAuth Mengalir | Titik akhir | Kaedah | Penerangan | | -------------------------------- | ----------- | --------------------- | | `/api/oauth/[provider]/[action]` | Macam-macam | OAuth khusus pembekal | ### Penghalaan & Konfigurasi | Titik akhir | Kaedah | Penerangan | | --------------------- | ----------- | ------------------------------------- | | `/api/models` | GET/PUT | Kemas kini senarai model / alias | | `/api/models/alias` | GET/POST | Alias model | | `/api/models/catalog` | GET | Semua model mengikut jenis pembekal + | | `/api/combos*` | Macam-macam | Pengurusan kombo | | `/api/keys*` | Macam-macam | pengurusan kunci API | | `/api/pricing` | GET | Harga model | #### Had model asal `GET /api/models?withLimits=1` (juga `true`; `0`/`false` atau meninggalkannya mengekalkan muatan lalai tidak berubah) menambah `contextWindow`, `maxInputTokens`, `maxOutputTokens` dan objek `capsSource` pada setiap baris model. `capsSource` menamakan peraturan yang membekalkan setiap had, jadi had yang mengejutkan (contohnya 128k pada model 1M) boleh dikesan ke asalnya. Nilai yang diselesaikan adalah sama dengan penggunaan penghalaan; bendera hanya menambah medan dan tidak pernah mengubah nilai. Sebarang nilai `withLimits` lain ditolak dengan `400`. | nilai `capsSource` | asal usul | | -------------------------------------------- | -------------------------------------------------------------------- | | `override:context` | Penggantian tetingkap konteks berterusan (`model_context_overrides`) | | `override:max_input` / `override:max_output` | Keupayaan `max_input_tokens` / `max_output_tokens` berterusan | | `static-authoritative:/` | Jadual tetingkap konteks berwibawa statik | | `synced:/` | baris keupayaan models.dev disegerakkan | | `registry:/` | Entri pendaftaran pembekal | | `spec:` | Spesifikasi model statik | | awalan `effort-base:` | Baris yang dipinjam daripada model asas varian dengan akhiran usaha | | `none` | Tiada sumber mengisytiharkan had (nilai ialah `null`) | Pelaksanaan: `getResolvedModelCapabilitiesWithLimitSources()` dalam `src/lib/modelCapabilities.ts` dan rantaian keutamaan dalam `src/lib/modelCapabilityLimits.ts`. ### Penggunaan & Analitis | Titik akhir | Kaedah | Penerangan | | -------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/usage/history` | GET | Sejarah penggunaan | | `/api/usage/logs` | GET | Log penggunaan | | `/api/usage/request-logs` | GET | Log peringkat permintaan | | `/api/usage/[connectionId]` | GET | Penggunaan setiap sambungan | | `/api/usage/token-limits` | GET/POST/DELETE | Belanjawan had token per-API-key | | `/api/usage/model-latency-stats` | GET | Agregat kependaman per-provider/model bergolek (avg/p50/p95/p99, kadar kejayaan); penapis: `windowHours`/`minSamples`/`maxRows`/`provider`/`model` (#6873) | | `/api/usage/cache-health` | GET | Ringkasan kesihatan cache segera atas nisbah `call_logs` — write/read, taburan saiz tulis p50/p90/p99, kepekatan tulisan berat, pemisahan setiap model dan keputusan `healthy`/`degraded`/`thrash`/`no-data` ; query params `range` (`1h`\| `24h`\| `7d`\| `30d`, lalai `24h`) dan `model` pilihan (#8827) | ### kebenaran kunci API `PATCH /api/keys/{id}` mengemas kini kebenaran kunci sedia ada. Seperti setiap laluan `/api/keys*` ia memerlukan kebenaran pengurusan (lihat [Pengesahan Pengurusan](../guides/MANAGEMENT-AUTH.md) ), bukan kunci inferens. Hantar hanya medan yang ingin anda ubah; permintaan dengan tiada satu pun daripadanya ditolak dengan `No valid fields to update`. Medan yang diterima ditakrifkan oleh `updateKeyPermissionsSchema` dalam `src/shared/validation/schemas/keys.ts`. | Padang | taip | Nota | | ------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | rentetan, 1-200 aksara | | | `isActive` | boolean | | | `isBanned` | boolean | | | `expiresAt` | ISO 8601 datetime atau `null` | `null` membersihkan tamat tempoh | | `modelAccessMode` | `all` \| `restricted` | `allowedModels` mesti kosong apabila mod `all` | | `allowedModels`, `blockedModels` | tatasusunan rentetan, sehingga 1000 | | | `allowedCombos` | susunan rentetan, sehingga 500 | Pintu yang menggabungkan kunci boleh memanggil; model langsung dikawal oleh `modelAccessMode` / `allowedModels` | | `connectionAccessMode` | `all` \| `restricted` | `allowedConnections` mestilah tidak kosong apabila `restricted` dan kosong apabila `all` | | `allowedConnections` | susunan UUIDs, sehingga 100 | | | `allowAutoCombos` | boolean | `false` menolak permintaan untuk model `auto/*` dengan kunci ini; kunci yang tidak pernah menetapkannya dibenarkan | | `catalogScope` | `all` \| `combos` \| `models` | Perkara yang `GET /v1/models` senaraikan untuk kunci ini (kombo sahaja, model sahaja, atau kedua-duanya); ia tidak mengubah apa yang mungkin dipanggil kunci | | `forcedModel` | rentetan sehingga 300 aksara, atau `null` | Halakan permintaan sembang ke model/combo ini , melalui `X-Route-Model` dan `body.model`; had kunci masih terpakai | | `noLog`, `autoResolve` | boolean | | | `throttleDelayMs` | integer, 0-300000 | | | `maxSessions` | integer, 0-10000 | | | `rateLimits` | tatasusunan `{ limit, window }` (integer positif, sehingga 50) atau `null` | `null` membersihkan had | | `accessSchedule` | jadual objek atau `null` | `null` mengosongkan jadual | | `scopes` | tatasusunan rentetan, sehingga 32 | | | `allowedEndpoints` | susunan rentetan, sehingga 20 | | | `streamDefaultMode` | `legacy` \| `json` | | | `cacheDefaultMode` | `legacy` \| `bypass` | Lihat [Pintasan cache setiap kekunci](#per-key-cache-bypass) | | `compressionEnabled` | boolean | | | `codexServiceMode` | salah satu mod perkhidmatan Codex | | | `disableNonPublicModels` | boolean | | | `allowUsageCommand` | boolean | | | `usageLimitEnabled` | boolean | | | `dailyUsageLimitUsd`, `weeklyUsageLimitUsd` | nombor >= 0 atau `null` | | | `fiveHourUsageLimitUsd` | nombor >= 0 atau `null` | Belanjawan USD 5 jam, dikuatkuasakan seperti had harian dan mingguan (`usageLimitEnabled`, `UNPRICED_USAGE_BUDGET_POLICY`). `retry-after` ialah apabila perbelanjaan tertua dalam tetingkap itu sudah tua, yang boleh meninggalkan kunci yang melebihi hadnya masih disekat. | | `chaosModeEnabled` | boolean | | ```bash curl -X PATCH "$OMNIROUTE_URL/api/keys/$KEY_ID" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "allowAutoCombos": false, "catalogScope": "combos" }' ``` ### tetapan | Titik akhir | Kaedah | Penerangan | | ------------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/settings` | GET/PUT/PATCH | Tetapan umum. Kunci dasar keselamatan (`requireLogin`, `newPassword`, `oidc*`, `corsOrigins`, `bruteForceProtection`) memerlukan `currentPassword` dan kunci kelayakan pengendali — API dan token `oma_` mendapat `403`; setiap mutasi memerlukan skop token akses `admin` | | `/api/settings/proxy` | GET/PUT | Konfigurasi proksi rangkaian | | `/api/settings/proxy/test` | POST | Uji sambungan proksi | | `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist | | `/api/settings/thinking-budget` | GET/PUT | Thinking/reasoning** permintaan** mod tulis semula (laluan / jalur automatik / tersuai / adaptif). Bebas daripada pemampatan. Lihat [THINKING_BUDGET.md](../guides/THINKING_BUDGET.md). | | `/api/settings/system-prompt` | GET/PUT | Gesaan sistem global | | `/api/settings/compression` | GET/PUT | Konfigurasi mampatan global | | `/api/settings/purge-request-history` | POST | Kosongkan baris log permintaan dan artifak log panggilan tempatan | ### Konteks & Mampatan | Titik akhir | Kaedah | Penerangan | | -------------------------------------- | -------------- | ------------------------------------------------------------------------- | | `/api/compression/preview` | POST | Pratonton mampatan off/lite/standard/aggressive/ultra/RTK/stacked | | `/api/compression/language-packs` | GET | Senaraikan pek bahasa Caveman yang tersedia | | `/api/compression/rules` | GET | Senaraikan metadata peraturan Caveman | | `/api/context/caveman/config` | GET/PUT | Alias tetapan khusus manusia gua | | `/api/context/rtk/config` | GET/PUT | Tetapan khusus RTK, termasuk penapis tersuai dan pengekalan output mentah | | `/api/context/rtk/filters` | GET | katalog penapis RTK dan diagnostik penapis tersuai | | `/api/context/rtk/test` | POST | Jalankan RTK preview/test terhadap muatan teks | | `/api/context/rtk/raw-output/[id]` | GET | Baca output mentah yang disunting yang dikekalkan oleh id penunjuk | | `/api/context/combos` | GET/POST | Kombo mampatan list/create | | `/api/context/combos/[id]` | GET/PUT/DELETE | Kombo mampatan detail/update/delete | | `/api/context/combos/[id]/assignments` | GET/PUT | Tetapkan gabungan mampatan kepada kombo penghalaan | | `/api/context/analytics` | GET | Alias analitik mampatan | ### Pemantauan | Titik akhir | Kaedah | Penerangan | | ------------------------------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `/api/sessions` | GET | Penjejakan sesi aktif | | `/api/rate-limits` | GET | Had kadar setiap akaun | | `/api/monitoring/health` | GET | Ringkasan pembekal + pemeriksaan kesihatan (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`). Paparan pengurusan termasuk `credentialHealth`: skalar cache probe, `failedConnections` apabila `failed>0`, dan `staleDbNonOkCount` (SQLite sticky `test_status`, bukan tolok). Lihat [MONITORING_GUIDE.md](../ops/MONITORING_GUIDE.md#credentialhealth-probe-cache-vs-sqlite-test_status). | | `/api/cache/stats` | GET/DELETE | Statistik cache / kosongkan | | `/api/modality-bridge/stats` | GET | `attempts` dalam ingatan , kejayaan/`bridged`, kegagalan, hit cache, `totalLatencyMs`, `latencySamples`, `averageLatencyMs` denominasi sampel dan masa penggunaan terakhir (set semula semasa dimulakan semula; pengesahan pengurusan) | | `/api/modality-bridge/video/runtime` | GET | Semakan trusted-loopback yang ketat sebelum pengurusan auth/probe; ketersediaan dan versi FFmpeg/ffprobe yang dibersihkan (tiada kedai) | | `/api/modality-bridge/video/extract` | POST | Broker bait gelung balik dipercayai dalaman yang disahkan; 50 input MiB, keluaran queue/32 MiB terhad, kapasiti `503`, cabut `499`, tarikh akhir `504` ; bukan muat naik awam API | ### Gerudi ke bawah bingkai video `GET /api/v1/video-bridge/drilldown` membaca pemegang legap terikat penyewa yang dikembalikan dalam `x-omniroute-video-drilldown` selepas permintaan Video Bridge yang dipersetujui secara jelas. Kedua-dua bacaan dan `DELETE` sentiasa memerlukan kunci API yang sah dan kebenaran `modalityBridgeVideoDrilldownRemoteEnabled` bebas pengendali. Pengekalan pengeluaran juga memerlukan `modalityBridgeVideoDrilldownEnabled` dan `drilldown: true` setiap bahagian yang ketat . Jika kunci mempunyai senarai dibenarkan titik akhir yang tidak kosong, ia mesti termasuk `video` untuk kedua-dua GET dan DELETE, sama ada pemanggil menggunakan `/v1` atau `/api/v1`. pertanyaan GET : diperlukan `handle`; `variant` pilihan (`preview`, `standard`, `detail`), `limit` (1–8; `frames` warisan diterima tetapi tidak boleh digabungkan dengan `limit`), `page` berasaskan sifar dan `start`/`end` saat. Apabila kedua-dua sempadan fokus dibekalkan, `end` mestilah lebih besar daripada `start`. kunci pertanyaan Duplicate/unknown ditolak. Respons yang berjaya mengandungi `derivation`, `durationSeconds`, `frames`, `hasMore`, `page`, `variant` dan `focusWindow` pilihan; JSON tanpa kedai dihadkan pada 32 MiB termasuk Base64. Keluaran bersaiz besar mengembalikan 413; minta lebih sedikit bingkai. `DELETE /api/v1/video-bridge/drilldown?handle=...` kembalikan `{ "removed": 0|1 }`. GETs tidak diketahui, tamat tempoh dan kekunci silang tidak dapat dibezakan 404 respons; kekunci silang DELETE tidak boleh mengalih keluar masukan pemilik. Akses yang dilumpuhkan mengembalikan 403, pengesahan missing/invalid 401, pertanyaan tidak sah 400, pembatalan 499 dan ralat sementara 503. Pengendalian adalah proses setempat, tamat tempoh selepas sepuluh minit dan tidak dapat dimulakan semula. Pemegang baharu menggunakan `v1.` ditambah token Base64URL rawak 32 bait; hanya cincang token dikekalkan. Token 64-hex warisan kekal boleh dibaca secara sintaksis untuk keserasian. Lihat [pagar Video Bridge](../security/GUARDRAILS.md#video-bridge-videobridgets-videobridgepipelinets) untuk mendapatkan persetujuan, kuota dan butiran terbitan varian. ### Sandaran & Export/Import | Titik akhir | Kaedah | Penerangan | | --------------------------- | ------ | -------------------------------------------------------------------------------------------- | | `/api/db-backups` | GET | Senaraikan sandaran yang tersedia | | `/api/db-backups` | PUT | Buat sandaran manual | | `/api/db-backups` | POST | Pulihkan daripada sandaran tertentu | | `/api/db-backups` | PATCH | Simpan tetapan pengekalan sandaran (pengendali sahaja) | | `/api/db-backups` | DELETE | Pangkas sandaran yang disimpan kepada tetapan pengekalan (pengendali sahaja) | | `/api/db-backups/export` | GET | Muat turun pangkalan data sebagai fail .sqlite | | `/api/db-backups/import` | POST | Muat naik fail .sqlite untuk menggantikan pangkalan data (`?dryRun=true` mengesahkan sahaja) | | `/api/db-backups/exportAll` | GET | Muat turun sandaran penuh sebagai arkib .tar.gz | `/api/db-backups/export`, `/api/db-backups/exportAll` dan `/api/settings/export-json` mengedarkan setiap bukti kelayakan yang disimpan, jadi mereka memerlukan sesi papan pemuka atau CLI setempat (atau log masuk dilumpuhkan). kunci API dari mana-mana skop dan token akses `oma_` mendapat `403`. Pemulihan memegang sempadan yang sama: `POST /api/db-backups/import` ( termasuk `dryRun=true` ), `POST /api/db-backups` (pulihkan mengikut id) dan `POST /api/settings/import-json` menggantikan pangkalan data atau tetapan langsung, jadi kelayakan mesin mendapat `403` di sana juga; `omniroute sync import` menghantar bukti kelayakan CLI tempatan. Begitu juga `DELETE /api/db-backups` (pangkas sandaran tersimpan) dan `PATCH /api/db-backups` (tetapan pengekalan: nilai berterusan memacu pemangkasan automatik selepas setiap sandaran). Penyenaraian (`GET`) dan mencipta sandaran manual (`PUT`) mengekalkan pengesahan pengurusan biasa. ### Penyegerakan Awan | Titik akhir | Kaedah | Penerangan | | ---------------------- | ----------- | ------------------------- | | `/api/sync/cloud` | Macam-macam | Operasi penyegerakan awan | | `/api/sync/initialize` | POST | Mulakan penyegerakan | | `/api/cloud/*` | Macam-macam | Pengurusan awan | ### Terowong | Titik akhir | Kaedah | Penerangan | | -------------------------- | ------ | --------------------------------------------------------------------------- | | `/api/tunnels/cloudflared` | GET | Baca status install/runtime Terowong Pantas Cloudflare untuk papan pemuka | | `/api/tunnels/cloudflared` | POST | Dayakan atau lumpuhkan Terowong Pantas Cloudflare (`action=enable/disable`) | | `/api/tunnels/ngrok` | GET | Baca status masa jalan Terowong ngrok untuk papan pemuka | | `/api/tunnels/ngrok` | POST | Dayakan atau lumpuhkan Terowong ngrok (`action=enable/disable`) | ### CLI Alat | Titik akhir | Kaedah | Penerangan | | ---------------------------------- | ------ | ---------------------- | | `/api/cli-tools/claude-settings` | GET | status Claude CLI | | `/api/cli-tools/codex-settings` | GET | status Codex CLI | | `/api/cli-tools/droid-settings` | GET | Status Droid CLI | | `/api/cli-tools/openclaw-settings` | GET | status OpenClaw CLI | | `/api/cli-tools/runtime/[toolId]` | GET | Masa jalan CLI generik | respons CLI termasuk: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`. ### ACP Ejen | Titik akhir | Kaedah | Penerangan | | ----------------- | ------ | --------------------------------------------------------------------------- | | `/api/acp/agents` | GET | Senaraikan semua ejen yang dikesan ( + terbina dalam tersuai) dengan status | | `/api/acp/agents` | POST | Tambahkan ejen tersuai atau muat semula cache pengesanan | | `/api/acp/agents` | DELETE | Alih keluar ejen tersuai oleh `id` query param | respons GET termasuk `agents[]` (id, nama, binari, versi, dipasang, protokol, isCustom) dan `summary` (jumlah, dipasang, notFound, builtIn, tersuai). ### Ketahanan & Had Kadar | Titik akhir | Kaedah | Penerangan | | --------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/resilience` | GET/PATCH | giliran permintaan Get/update, tempoh sambungan, pemutus pembekal dan tetapan tunggu | | `/api/resilience/reset` | POST | Tetapkan semula pemutus litar pembekal | | `/api/resilience/model-cooldowns` | GET | Senaraikan sekatan aktif setiap (penyedia, sambungan, model), diisih mengikut masa yang tinggal | | `/api/resilience/model-cooldowns` | DELETE | Kosongkan model lockout — body `{provider, model}` atau `{all: true}` untuk memadam semuanya | | `/api/rate-limits` | GET/POST | Status had kadar setiap akaun (GET) atau togol perlindungan had kadar untuk sambungan (POST `{connectionId, enabled}`). Laluan tulis yang disokong untuk `rateLimitProtection` (tidak pernah diubah suai melalui `PUT /api/providers/[id]`). Nota: `enabled: false` melumpuhkan perlindungan eksplisit tetapi tidak memilih sambungan kunci API aktif daripada rangkaian keselamatan autodaya global (`autoEnableApiKeyProviders`). | | `/api/rate-limit` | GET | Konfigurasi had kadar global (ditamatkan; alias kepada `/api/rate-limits`) | > Keempat-empat laluan `/api/resilience/*` memerlukan** pengesahan pengurusan** (`requireManagementAuth`). Lihat [Ketahanan (dilanjutkan)](#resilience-extended) untuk pecahan penuh pemutus penyedia vs tempoh masa sambungan vs penguncian model. ### Evals | Titik akhir | Kaedah | Penerangan | | ------------ | -------- | ------------------------------------------ | | `/api/evals` | GET/POST | Senaraikan suite eval / penilaian jalankan | ### dasar | Titik akhir | Kaedah | Penerangan | | --------------- | --------------- | --------------------- | | `/api/policies` | GET/POST/DELETE | Urus dasar penghalaan | ### Pematuhan | Titik akhir | Kaedah | Penerangan | | --------------------------- | ------ | -------------------------------- | | `/api/compliance/audit-log` | GET | Log audit pematuhan (N terakhir) | ### v1beta (Serasi Gemini) | Titik akhir | Kaedah | Penerangan | | -------------------------- | ------ | ------------------------------------ | | `/v1beta/models` | GET | Senaraikan model dalam format Gemini | | `/v1beta/models/{...path}` | POST | Gemini `generateContent` titik akhir | Titik akhir ini mencerminkan format GeminiAPI untuk pelanggan yang mengharapkan keserasian Gemini SDK asli. ### Dalaman / Sistem APIs | Titik akhir | Kaedah | Penerangan | | ------------------------ | ------ | ------------------------------------------------------------------------ | | `/api/init` | GET | Mulakan perkhidmatan penyegerakan latar belakang (pengesahan pengurusan) | | `/api/tags` | GET | Teg model yang serasi dengan Ollama (untuk pelanggan Ollama ) | | `/api/restart` | POST | Cetuskan permulaan semula pelayan yang anggun | | `/api/shutdown` | POST | Cetuskan penutupan pelayan yang anggun | | `/api/system/env/repair` | POST | Membaiki pembolehubah persekitaran pembekal OAuth | | `/api/system/version` | GET | versi Current/latest, status kemas kini, saluran keluaran | | `/api/system/version` | POST | Mulakan kemas kini yang menyedari penggunaan kepada versi terkini | > **Nota:** Titik akhir ini digunakan secara dalaman oleh sistem atau untuk keserasian klien Ollama. Mereka biasanya tidak dipanggil oleh pengguna akhir. ### OAuth Pembaikan Persekitaran _(v3.6.1 +)_ ```bash POST /api/system/env/repair Content-Type: application/json { "provider": "claude-code" } ``` Membaiki pembolehubah persekitaran OAuth yang hilang atau rosak untuk pembekal tertentu. Pulangan: ```json { "success": true, "repaired": ["CLAUDE_CODE_OAUTH_CLIENT_ID", "CLAUDE_CODE_OAUTH_CLIENT_SECRET"], "backupPath": "/home/user/.omniroute/backups/env-repair-2026-04-11.bak" } ``` ### Versi dan Saluran Keluaran ```bash GET /api/system/version ``` Laluan pengurusan gelung balik sahaja (auth pentadbir). Mengembalikan versi yang sedang berjalan, versi terbitan terkini dan status autokemas kini. `releaseChannel` dan `channels` ialah medan tambahan (rel 3.8.54); `channel` mengekalkan maksudnya — mod penggunaan yang digunakan oleh pengemas kini papan pemuka (`npm`, `source` atau `docker-compose`). ```json { "current": "3.8.52", "latest": "3.8.52", "updateAvailable": false, "channel": "npm", "autoUpdateSupported": true, "autoUpdateError": null, "news": null, "releaseChannel": "latest", "channels": { "latest": "3.8.52", "next": "3.8.53-rc.1" } } ``` - `releaseChannel` — npm saluran binaan berjalan: `nightly` untuk versi `-nightly.*`, `next` untuk pra-keluaran lain (`-rc.*`, `-beta.*`, `-alpha.*`), `lts` untuk versi stabil jurusan yang lebih lama daripada `channels.latest`, sebaliknya `latest`. Peraturan yang sama seperti `scripts/release/dist-tag.mjs`, yang memilih npm dist-tag pada masa penerbitan. - `channels` — menerbitkan kepala setiap teg dist, daripada `npm view omniroute dist-tags` (pendaftaran HTTP sandaran), dicache dengan TTL 10 minit yang sama dengan `latest`. `latest` sentiasa hadir (kembali ke medan `latest`, kemudian `"unavailable"`); `next`, `nightly` dan `lts` muncul hanya apabila dist-tag itu wujud. Permintaan `Cache-Control: no-cache` menyegarkan kedua-dua carian. Model saluran (`latest` = v3 sehingga 4.0 GA, `next` = rc, `nightly` = `develop` binaan, tampung `lts` = v3 selepas 4.0 GA) diterangkan dalam `docs/ops/RELEASE_STRATEGY.md`. --- ## Transkripsi Audio ```bash POST /v1/audio/transcriptions Authorization: Bearer your-api-key Content-Type: multipart/form-data ``` Transkripsikan fail audio menggunakan mana-mana penyedia STT yang dikonfigurasikan. Segmen laluan pertama memilih penyedia natif (`openai/…`, `deepgram/…`). Gateway yang mengeksport semula model vendor lain menggunakan ID berkelayakan (`openrouter/deepgram/nova-3`). **Permintaan:** ```bash curl -X POST http://localhost:20128/v1/audio/transcriptions \ -H "Authorization: Bearer your-api-key" \ -F "file=@recording.mp3" \ -F "model=openai/whisper-1" ``` **Respons:** ```json { "text": "Hello, this is the transcribed audio content.", "task": "transcribe", "language": "en", "duration": 12.5 } ``` **Contoh ID model:** `openai/whisper-1` (memerlukan kunci OpenAI), `openrouter/deepgram/nova-3` (memerlukan kunci OpenRouter), `deepgram/nova-3` (memerlukan kunci Deepgram natif). Permintaan `deepgram/nova-3` tanpa awalan **tidak** menggunakan OpenRouter. **Format yang disokong:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`. **Gemini Live (`gemini/gemini-3.5-transcribe-live`):** transkripsi mod fail melalui WebSocket Gemini Live (memerlukan kunci API Gemini). Muat naik ditukar kepada PCM mono 16 kHz menggunakan `ffmpeg` (`ffmpeg` mesti berada dalam `PATH`, melainkan fail tersebut sudah merupakan WAV PCM mono 16 kHz), distrim ke sesi dan teks yang dimuktamadkan dikembalikan sebagai `{ "text": "..." }`. Medan borang `language` dan `prompt` pilihan dimajukan. Had: muat naik melebihi 25 MiB atau audio yang dinyahkod melebihi 10 minit akan memberikan respons `413`; penukaran yang berjalan lebih daripada 60 saat akan dihentikan dan memberikan respons `504`. Kunci API dihantar hanya dalam pengepala `x-goog-api-key`, tidak pernah dalam URL WebSocket. --- ## Keserasian Ollama Untuk klien yang menggunakan format API Ollama: ```bash # Titik akhir sembang (format Ollama) POST /v1/api/chat # Penyenaraian model (format Ollama) GET /api/tags ``` Permintaan diterjemahkan secara automatik antara format Ollama dan format dalaman. ## Alias VS Code Bertoken / Tanpa Pengepala Gunakan alias ini apabila integrasi tidak dapat menyuntik pengepala `Authorization` dan memerlukan kunci API dibenamkan dalam URL asas. ```bash # Alias katalog gaya OpenAI GET /api/v1/vscode/{token}/ GET /api/v1/vscode/{token}/models # Alias sembang gaya OpenAI POST /api/v1/vscode/{token}/chat/completions POST /api/v1/vscode/{token}/responses # Alias gaya Ollama POST /api/v1/vscode/{token}/api/chat GET /api/v1/vscode/{token}/api/tags ``` Contoh: ```bash curl https://your-host.example/api/v1/vscode/YOUR_API_KEY/models curl -X POST https://your-host.example/api/v1/vscode/YOUR_API_KEY/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"auto","messages":[{"role":"user","content":"hello"}]}' ``` Nota: - Alias bertoken menggunakan semula pengendali yang sama seperti `/v1/*` dan `/api/tags`; bentuk respons kekal sama. - Utamakan `Authorization: Bearer ...` apabila klien menyokong pengepala tersuai. - Token berasaskan URL mungkin muncul dalam log proksi terbalik, sejarah pelayar dan telemetri di luar OmniRoute. Anggap token ini sebagai pilihan keserasian, bukan mod pengesahan lalai. --- ## Telemetri ```bash # Dapatkan ringkasan telemetri kependaman (p50/p95/p99 bagi setiap penyedia) GET /api/telemetry/summary ``` **Respons:** ```json { "providers": { "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 }, "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 } } } ``` --- ## Belanjawan ```bash # Dapatkan status belanjawan untuk semua kunci API GET /api/usage/budget # Tetapkan atau kemas kini belanjawan POST /api/usage/budget Content-Type: application/json { "apiKeyId": "key-123", "dailyLimitUsd": 5.00, "weeklyLimitUsd": 30.00, "monthlyLimitUsd": 100.00, "warningThreshold": 0.8, "resetInterval": "monthly" } ``` > **Nota skema** (`setBudgetSchema`): `apiKeyId` diperlukan; sekurang-kurangnya satu daripada `dailyLimitUsd`, `weeklyLimitUsd` atau `monthlyLimitUsd` mestilah lebih besar daripada sifar. Medan pilihan: `warningThreshold` (0–1), `resetInterval` (`daily` | `weekly` | `monthly`), `resetTime` (`HH:MM`). Bentuk legasi `{keyId, limit, period}` mengembalikan `400 Bad Request`. ## Had Token Had **token** bagi setiap kunci API (berbeza daripada Bajet berasaskan USD di atas). Dikuatkuasakan sebaris pada laluan permintaan: apabila penggunaan tetingkap semasa sesuatu kunci mencapai hadnya, permintaan ditolak dengan `429 Too Many Requests`. Had boleh dikhususkan kepada `model` tertentu, `provider`, atau digunakan secara `global` merentasi kunci; apabila beberapa had sepadan dengan sesuatu permintaan, had yang paling ketat akan digunakan. ```bash # Senaraikan had token sesuatu kunci (termasuk penggunaan tetingkap semasa) GET /api/usage/token-limits?apiKeyId=key-123 # Cipta atau kemas kini had token POST /api/usage/token-limits Content-Type: application/json { "apiKeyId": "key-123", "scopeType": "model", "scopeValue": "openai/gpt-4o", "tokenLimit": 1000000, "resetInterval": "monthly", "enabled": true } # Padam had token mengikut id DELETE /api/usage/token-limits?id=tl-abc ``` > **Nota skema** (`setTokenLimitSchema`): `apiKeyId` dan `scopeType` (`model` | `provider` | `global`) diperlukan. `scopeValue` diperlukan melainkan `scopeType` ialah `global` (contohnya, id model untuk skop `model`, id penyedia untuk skop `provider`). `tokenLimit` mestilah integer positif (ditukar daripada rentetan). Pilihan: `id` (tinggalkan untuk mencipta, bekalkan untuk mengemas kini), `resetInterval` (`daily` | `weekly` | `monthly`, lalai `monthly`), `resetTime` (`HH:MM`), `enabled` (lalai `true`). Respons `GET` memperkaya setiap had dengan `tokensUsed`, `remaining`, `windowStart`, `periodStartAt`, dan `nextResetAt`. Ini ialah titik akhir kelas pengurusan (pengesahan dikuatkuasakan secara berpusat oleh saluran paip authz). ## Pemprosesan Permintaan 1. Klien menghantar permintaan ke `/v1/*` 2. Pengendali laluan memanggil `handleChat`, `handleEmbedding`, `handleAudioTranscription`, atau `handleImageGeneration` 3. Model diselesaikan (penyedia/model secara langsung atau alias/gabungan) 4. Bukti kelayakan dipilih daripada pangkalan data tempatan dengan penapisan ketersediaan akaun 5. Untuk chat: `handleChatCore` menyemak cache semantik/tandatangan dan menyelesaikan tetapan pemampatan gabungan 6. Pemampatan proaktif dijalankan sebelum penterjemahan penyedia apabila didayakan (`lite`, Caveman, RTK, atau bertindan) 7. Pelaksana penyedia menghantar permintaan huluan 8. Respons diterjemahkan kembali kepada format klien (chat) atau dikembalikan seadanya (embeddings/imej/audio) 9. Penggunaan, analitik pemampatan, dan log permintaan direkodkan 10. Fallback digunakan apabila berlaku ralat mengikut peraturan gabungan Rujukan seni bina penuh: [`ARCHITECTURE.md`](../architecture/ARCHITECTURE.md) --- ## Pengurusan Gabungan Gabungan penghalaan peringkat lebih tinggi (yang telah diringkaskan di bawah `/api/combos*`) juga boleh dipetakan 1:1 daripada corak id model, membolehkan pengalihan telus bagi id model gaya OpenAI kepada sesuatu gabungan. | Kaedah | Laluan | Perihalan | | ------ | -------------------------------- | ----------------------------------------------------------------------------- | | GET | `/api/model-combo-mappings` | Senaraikan semua pemetaan model→gabungan | | POST | `/api/model-combo-mappings` | Cipta pemetaan — isi: `{pattern, comboId, priority?, enabled?, description?}` | | GET | `/api/model-combo-mappings/[id]` | Dapatkan satu pemetaan | | PUT | `/api/model-combo-mappings/[id]` | Kemas kini medan bagi pemetaan sedia ada | | DELETE | `/api/model-combo-mappings/[id]` | Buang satu pemetaan | **Pengesahan:** sesi/kunci API pengurusan (`requireManagementAuth`). --- ## Webhook Langganan webhook keluar untuk acara OmniRoute (penyelesaian permintaan, kehabisan kuota, penggiliran kunci, dll.). | Kaedah | Laluan | Perihalan | | ------ | ------------------------- | ---------------------------------------------------------------------- | | GET | `/api/webhooks` | Senaraikan webhook (rahsia disamarkan kepada `...`) | | POST | `/api/webhooks` | Cipta webhook — badan: `{url, events?: ["*"], secret?, description?}` | | GET | `/api/webhooks/[id]` | Dapatkan webhook | | PUT | `/api/webhooks/[id]` | Kemas kini url/events/secret/description | | DELETE | `/api/webhooks/[id]` | Alih keluar webhook | | POST | `/api/webhooks/[id]/test` | Hantar payload ujian ke URL webhook dan kembalikan status penghantaran | **Pengesahan:** sesi/kunci API pengurusan (`requireManagementAuth`). --- ## Kunci Berdaftar (Pengurusan Automatik) Digunakan oleh subsistem pengurusan kunci automatik untuk mengeluarkan dan menggil ir kunci API terhadap pembekal/akaun sokongan, dengan kuota harian/jam. | Kaedah | Laluan | Perihalan | | ------ | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/v1/registered-keys` | Senaraikan kunci berdaftar (hanya awalan yang disamarkan) | | POST | `/api/v1/registered-keys` | Keluarkan kunci berdaftar baharu — badan: `{name, provider?, accountId?, idempotencyKey?, expiresAt?, dailyBudget?, hourlyBudget?}`. Mengembalikan kunci mentah **sekali**. Mengembalikan `429` apabila kuota ditolak. | | GET | `/api/v1/registered-keys/[id]` | Dapatkan metadata kunci berdaftar (tiada nilai mentah) | | DELETE | `/api/v1/registered-keys/[id]` | Batalkan kunci berdaftar | | POST | `/api/v1/registered-keys/[id]/revoke` | Titik akhir pembatalan eksplisit (kesan yang sama seperti DELETE) | **Pengesahan:** sesi/kunci API pengurusan (`requireManagementAuth`) — pengawal yang sama seperti `/api/keys`: sesi papan pemuka, token CLI setempat atau kunci API dengan skop `manage`/`admin`; kunci API khusus inferens menerima `403`. Lihat juga `/v1/quotas/check` dan `/v1/issues/report`. --- ## Protokol Ejen Tugas ejen awan (Claude Code, Codex Cloud, OpenHands, dll.) yang dilaksanakan dari jauh bagi pihak pengguna OmniRoute. | Method | Path | Description | | ------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | GET | `/api/v1/agents/tasks` | Senaraikan tugas — pilihan `?provider=`, `?status=`, `?limit=` (1–500, lalai 50) | | POST | `/api/v1/agents/tasks` | Cipta tugas — badan disahkan oleh `CreateCloudAgentTaskSchema` (`providerId`, `prompt`, `source`, `options?`). Mengembalikan `201` dengan sampul tugas | | DELETE | `/api/v1/agents/tasks?id=...` | Padam tugas | | GET | `/api/v1/agents/tasks/[id]` | Baca tugas — menyegarkan status secara segerak daripada ejen awan huluan apabila `external_id` ditetapkan | | POST | `/api/v1/agents/tasks/[id]` | Tindakan berbeza: `{action: "approve"}`, `{action: "message", message}`, atau `{action: "cancel"}` | | DELETE | `/api/v1/agents/tasks/[id]` | Padam tugas tertentu mengikut id | > **Pengesahan:** pengesahan pengurusan diperlukan pada setiap kaedah (`requireCloudAgentManagementAuth`). Sebelum v3.8.0, kaedah ini tidak memerlukan pengesahan — lihat commit `588a0333` untuk perubahan yang tidak serasi. ```bash # Cipta tugas awan Claude Code curl -X POST http://localhost:20128/api/v1/agents/tasks \ -H "Authorization: Bearer your-management-key" \ -H "Content-Type: application/json" \ -d '{"providerId":"claude-code-cloud","prompt":"Fix the failing test","source":{"repo":"...","branch":"..."}}' ``` --- ## Proksi Pengurusan Proksi HTTP(S)/SOCKS keluar yang boleh ditetapkan kepada penyedia, akaun, atau secara global. | Method | Path | Description | | ------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | GET | `/api/v1/management/proxies` | Senaraikan proksi (dengan `?id=` mengembalikan satu; dengan `?id=&where_used=1` mengembalikan graf penetapan) | | POST | `/api/v1/management/proxies` | Cipta proksi — badan disahkan oleh `createProxyRegistrySchema` | | PATCH | `/api/v1/management/proxies` | Kemas kini proksi — badan disahkan oleh `updateProxyRegistrySchema` (memerlukan `id`) | | DELETE | `/api/v1/management/proxies?id=...&force=1` | Padam proksi (gunakan `force=1` untuk menanggalkan penetapan) | | GET | `/api/v1/management/proxies/assignments` | Senaraikan penetapan — boleh ditapis mengikut `proxy_id`, `scope`, `scope_id`; hantar `resolve_connection_id=` untuk menyelesaikan proksi aktif bagi sambungan | | PUT | `/api/v1/management/proxies/assignments` | Tetapkan — badan disahkan oleh `proxyAssignmentSchema` (`{scope, scopeId?, proxyId?}`). Mengosongkan cache penghantar | | PUT | `/api/v1/management/proxies/bulk-assign` | Tetapkan secara pukal — badan disahkan oleh `bulkProxyAssignmentSchema` (`{scope, scopeIds[], proxyId?}`) | | GET | `/api/v1/management/proxies/health?hours=24` | Kesihatan proksi agregat (kiraan berjaya/gagal, kependaman) dalam suatu tempoh | **Pengesahan:** sesi/kunci API pengurusan diperlukan pada setiap laluan (`requireManagementAuth`). > Penerangan tugas bagi `POST /api/v1/management/proxies/[id]/assignments` dan `POST /api/v1/management/proxies/[id]/health` disediakan oleh laluan rata `/assignments` dan `/health` yang ditunjukkan di atas — tiada sublaluan bagi setiap id dalam pangkalan kod. --- ## Ketahanan (dilanjutkan) OmniRoute menyediakan tiga mekanisme kegagalan sementara yang bebas; endpoint pengurusan di bawah membolehkan operator membacanya dan mengatasinya: | Skop | Penyimpanan keadaan | Baca | Tetapkan semula / kosongkan | | -------------------------- | ------------------------------------------ | ----------------------------------------- | --------------------------------------------------------------- | | Pemutus provider | `domain_circuit_breakers` + dalam memori | `/api/monitoring/health` | `POST /api/resilience/reset` | | Tempoh bertenang sambungan | `rateLimitedUntil` pada sambungan provider | `/api/rate-limits`, `/api/providers/[id]` | (didayakan semula secara malas; kosongkan melalui PUT provider) | | Sekatan model | Registry ketersediaan model dalam memori | `GET /api/resilience/model-cooldowns` | `DELETE /api/resilience/model-cooldowns` | `PATCH /api/resilience` menerima penggantian pemutus provider di bawah `providerBreaker.oauth` dan `providerBreaker.apikey`. Setiap profil menyokong `degradationThreshold`, `failureThreshold`, dan `resetTimeoutMs`; medan yang sama didedahkan dalam Papan Pemuka → Tetapan → Ketahanan. ```bash # Kosongkan sekatan satu model curl -X DELETE http://localhost:20128/api/resilience/model-cooldowns \ -H "Cookie: auth_token=..." \ -H "Content-Type: application/json" \ -d '{"provider":"openai","model":"gpt-4o-mini"}' # Kosongkan semua sekatan curl -X DELETE http://localhost:20128/api/resilience/model-cooldowns \ -H "Cookie: auth_token=..." \ -d '{"all":true}' ``` Rujukan konseptual penuh dan nilai lalai pemutus: lihat [`CLAUDE.md`](../../CLAUDE.md) → "Keadaan Runtime Ketahanan" dan [`docs/architecture/RESILIENCE_GUIDE.md`](../architecture/RESILIENCE_GUIDE.md). ### Baris Giliran Had Kadar & Jaring Keselamatan Pengaktifan Automatik - **Laluan tulis yang disokong**: `POST /api/rate-limits` dengan badan `{"connectionId": "", "enabled": true|false}` ialah endpoint pengurusan yang disokong untuk menogol perlindungan had kadar bagi sambungan. `PUT /api/providers/[id]` sengaja tidak mengubah atau menogol `rateLimitProtection` (#11278). - **Semantik `enabled: false`**: Menetapkan `enabled: false` mengalih keluar perlindungan eksplisit bagi sambungan tersebut, tetapi **tidak** mengecualikan sambungan kunci API yang aktif daripada jaring keselamatan pengaktifan automatik global (`autoEnableApiKeyProviders = true`). Dalam `reconcileEnabledConnections` (`open-sse/services/rateLimitManager.ts`), `false` dan `undefined` adalah setara; sambungan kunci API aktif tanpa perlindungan eksplisit kekal dilindungi di bawah jaring keselamatan pengaktifan automatik. - **Penyahdayaan global**: Untuk menjalankan sambungan kunci API tanpa baris giliran had kadar, nyahdayakan jaring keselamatan secara global melalui `RATE_LIMIT_AUTO_ENABLE=false` (env) atau `resilienceSettings.requestQueue.autoEnableApiKeyProviders = false` (Tetapan → Ketahanan / `PATCH /api/resilience`). --- ## Kemahiran Rangka kerja kemahiran untuk melanjutkan OmniRoute dengan pengendali boleh laku tersuai, serta integrasi marketplace. | Kaedah | Laluan | Perihalan | | ------ | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | GET | `/api/skills` | Senaraikan kemahiran yang dipasang — boleh ditapis mengikut `?q=`, `?mode=on\|off\|auto`, `?source=skillsmp\|skillssh\|local`, dengan penomboran | | GET | `/api/skills/[id]` | Dapatkan satu kemahiran | | PUT | `/api/skills/[id]` | Kemas kini kemahiran (nama, perihalan, mod, skema, pengendali, tag) | | DELETE | `/api/skills/[id]` | Nyahpasang kemahiran | | POST | `/api/skills/install` | Pasang kemahiran daripada manifes mentah — badan: `{name, version, description, schema:{input, output}, handlerCode, apiKeyId?}` | | GET | `/api/skills/executions` | Senaraikan pelaksanaan kemahiran terkini (jejak audit dengan input/output/tempoh) | | GET | `/api/skills/marketplace?q=...` | Cari/senarai popular daripada marketplace SkillsMP (memerlukan tetapan `skillsmpApiKey`) | | POST | `/api/skills/marketplace/install` | Pasang kemahiran mengikut id daripada SkillsMP | | GET | `/api/skills/skillssh?q=&limit=` | Cari registry skills.sh | | POST | `/api/skills/skillssh/install` | Pasang kemahiran mengikut id daripada skills.sh | **Pengesahan:** sesi pengurusan/kunci API. Laluan carian marketplace menerima sama ada pengesahan pengurusan atau kunci API Bearer (`isAuthenticated`). --- ## Memori Gedung memori perbualan/fakta berterusan, diskopkan mengikut kunci API / sesi. | Kaedah | Laluan | Perihalan | | ------ | -------------------- | -------------------------------------------------------------------------------------------------------------------- | | GET | `/api/memory` | Senaraikan memori — `?apiKeyId=`, `?type=`, `?sessionId=`, `?q=`, dengan penomboran `offset/limit` atau `page/limit` | | POST | `/api/memory` | Cipta memori — badan disahkan oleh Zod: `{content, key, type?, sessionId?, apiKeyId?, metadata?, expiresAt?}` | | GET | `/api/memory/[id]` | Dapatkan satu memori | | DELETE | `/api/memory/[id]` | Padam satu memori | | GET | `/api/memory/health` | Kesihatan subsistem memori (ketersambungan DB, bahagian belakang embeddings, status indeks vektor) | **Pengesahan:** sesi/kunci API pengurusan (`requireManagementAuth`). Enum `type`: `FACTUAL`, `EPISODIC`, `SEMANTIC`, `PROCEDURAL` (lihat `MemoryType` dalam `src/lib/memory/types.ts`). --- ## Pelayan MCP OmniRoute menyediakan pelayan Model Context Protocol terbenam dengan 3 pengangkutan (stdio, SSE, streamable-http) dan alat berskop. Titik akhir papan pemuka di bawah membaca data status/audit dan memproksikan pengangkutan HTTP. | Kaedah | Laluan | Perihalan | | ------ | ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------- | | GET | `/api/mcp/status` | Denyutan, pengangkutan, status dalam talian, panggilan terakhir, alat teratas, kadar kejayaan 24 jam | | GET | `/api/mcp/tools` | Senarai alat MCP dengan `name`, `description`, `scopes`, `phase`, `auditLevel`, `sourceEndpoints` | | GET | `/api/mcp/sse` | Buka strim SSE untuk pengangkutan SSE (mengembalikan `503` jika MCP dilumpuhkan atau pengangkutan tidak sepadan) | | POST | `/api/mcp/sse` | Hantar bingkai JSON-RPC pada pengangkutan SSE | | GET | `/api/mcp/stream` | Buka bahagian SSE pengangkutan Streamable HTTP (mesej yang dimulakan pelayan) | | POST | `/api/mcp/stream` | Hantar bingkai JSON-RPC pada pengangkutan Streamable HTTP | | DELETE | `/api/mcp/stream` | Tamatkan sesi Streamable HTTP | | GET | `/api/mcp/audit` | Buat pertanyaan log audit — `?limit=`, `?offset=`, `?tool=`, `?success=true | false`, `?apiKeyId=` | | GET | `/api/mcp/audit/stats` | Statistik audit terkumpul (jumlah, kadar kejayaan, tempoh purata, alat teratas) | **Pengesahan:** pengangkutan `sse`/`stream` mematuhi permukaan pengesahan khusus MCP (kunci API Bearer dengan skop `mcp`); laluan `status`/`tools`/`audit*` boleh dibaca daripada papan pemuka (tiada pengesahan tambahan diperlukan selain mencapai hos papan pemuka). > Kedua-dua pengangkutan HTTP dikawal oleh `settings.mcpEnabled` dan `settings.mcpTransport` — ketidakpadanan pengangkutan mengembalikan `400`, manakala keadaan MCP dilumpuhkan mengembalikan `503`. --- ## Pelayan A2A OmniRoute menyediakan titik akhir JSON-RPC 2.0 A2A (Agent-to-Agent) serta pembalut REST untuk tujuan pemeriksaan/papan pemuka. ### JSON-RPC ```bash POST /a2a Authorization: Bearer your-api-key # pilihan melainkan OMNIROUTE_API_KEY ditetapkan Content-Type: application/json { "jsonrpc": "2.0", "id": 1, "method": "message/send", "params": { "skill": "smart-routing", "messages": [{"role": "user", "content": "Route this coding task"}] } } ``` Kaedah yang disokong (semuanya dikawal oleh `settings.a2aEnabled`): | Kaedah | Penerangan | | ---------------- | -------------------------------------------------------------------------- | | `message/send` | Pelaksanaan kemahiran segerak; mengembalikan `{task, artifacts, metadata}` | | `message/stream` | Pelaksanaan SSE penstriman bagi set kemahiran yang sama | | `tasks/get` | Mendapatkan tugas berdasarkan `taskId` | | `tasks/cancel` | Membatalkan tugas berdasarkan `taskId` | Kemahiran terbina dalam: `smart-routing`, `quota-management`, `provider-discovery`, `cost-analysis`, `health-report`. ### Kad Ejen ```bash GET /.well-known/agent.json ``` Mengembalikan kad ejen A2A awam (nama, penerangan, keupayaan, katalog kemahiran, skema pengesahan) — dicache secara awam selama 1 jam. Tiada pengesahan diperlukan. ### Pembantu REST | Kaedah | Laluan | Penerangan | | ------ | ---------------------------- | --------------------------------------------------------------------------------------------------------------------- | | GET | `/api/a2a/status` | Status A2A diaktifkan + statistik tugas + ringkasan kad ejen yang dicache | | GET | `/api/a2a/tasks` | Senaraikan tugas — `?state=submitted\|working\|completed\|failed\|cancelled`, `?skill=`, `?limit=` (≤200), `?offset=` | | POST | `/api/a2a/tasks` | (Belum dilaksanakan sebagai pembantu REST — cipta melalui JSON-RPC `message/send`) | | GET | `/api/a2a/tasks/[id]` | Dapatkan satu tugas | | POST | `/api/a2a/tasks/[id]/cancel` | Batalkan satu tugas | **Pengesahan:** pembantu REST berjalan tanpa pengesahan pengurusan (boleh dibaca melalui papan pemuka); laluan JSON-RPC `/a2a` menggunakan Bearer `OMNIROUTE_API_KEY` jika dikonfigurasikan. --- ## Awan, Evals & Assess | Kaedah | Laluan | Penerangan | | ------ | ------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------- | ----------------------------------- | | POST | `/api/cloud/auth` | Sahkan kunci Bearer dan kembalikan sambungan pembekal yang ditopeng + alias model untuk klien penyegerakan awan | | POST | `/api/cloud/credentials/update` | Kemas kini kelayakan yang disulitkan untuk pembekal yang disegerakkan dengan awan | | POST | `/api/cloud/model/resolve` | Selesaikan id model logik kepada pembekal/model konkrit menggunakan jadual penghalaan setempat | | GET | `/api/cloud/models/alias` | Senaraikan alias model seperti yang didedahkan kepada penyegerakan awan | | GET | `/api/assess` | Baca pengkategorian penilaian terkini (mengikut pembekal/model) | | POST | `/api/assess` | Jalankan penilaian — badan: `{scope: {type:"all"} | {type:"provider", providerId} | {type:"model", modelId}, trigger?}` | | GET | `/api/evals` | Senaraikan suite eval terbina dalam + larian terkini | | POST | `/api/evals` | Cetuskan larian eval | | POST | `/api/evals/suites` | Cipta suite eval tersuai — badan disahkan oleh `evalSuiteSaveSchema` | | GET | `/api/evals/suites/[id]` | Dapatkan suite eval tersuai | **Pengesahan:** `/api/cloud/auth` mengesahkan kunci Bearer secara terus dan mengembalikan kunci bertopeng serta `projectId` bagi setiap sambungan hanya untuk kunci dengan skop `manage` / `admin`; laluan `/api/cloud/*`, `/api/evals/*` dan `/api/assess` yang lain memerlukan sesi/kunci API pengurusan. POST `/api/assess` menggunakan `validateBody` dengan skema skop kesatuan terbeza. --- ## Pengurusan ACP (Agent Client Protocol) sebagai proses anak. Titik akhir ini mengurus pengesanan ejen ACP dan pendaftaran ejen tersuai. | Method | Path | Description | | ------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/acp/agents` | Senaraikan semua ejen CLI yang diketahui (terbina dalam + tersuai) bersama status pemasangan, versi dan binari | | POST | `/api/acp/agents` | Daftarkan ejen ACP tersuai atau segarkan cache — body: `{id, name, binary, versionCommand, providerAlias, spawnArgs, protocol}` atau `{action: "refresh"}` | | DELETE | `/api/acp/agents` | Alih keluar ejen ACP tersuai — parameter pertanyaan: `?id=` | **Contoh respons** (`GET /api/acp/agents`): ```json { "agents": [ { "id": "claude", "name": "Claude Code CLI", "binary": "claude", "version": "1.0.45", "installed": true, "protocol": "stdio", "providerAlias": "claude", "isCustom": false }, { "id": "my-custom-cli", "name": "My Custom CLI", "installed": false, "protocol": "stdio", "providerAlias": "my-provider", "isCustom": true } ], "cacheTtlMs": 60000, "cacheAge": 1234 } ``` **Pengesahan:** Memerlukan sesi pengurusan (kuki `auth_token` papan pemuka) atau kunci API berskop pengurusan. Lihat [Rangka Kerja ACP](../frameworks/ACP.md) untuk butiran penuh. --- ## Analitik & Kebolehcerapan Titik akhir analitik masa nyata untuk memantau penghalaan, pemampatan dan kepelbagaian penyedia. Titik akhir ini menggerakkan halaman `/dashboard/analytics/*`. ### Analitik penghalaan automatik | Method | Path | Description | | ------ | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | | GET | `/api/analytics/auto-routing` | Statistik penghalaan automatik terkumpul: jumlah panggilan, taburan strategi, taburan peringkat, penyedia teratas | | GET | `/api/analytics/auto-routing?days=7` | Statistik berdasarkan tetingkap masa (lalai 24j) | **Contoh respons**: ```json { "window": "24h", "totalCalls": 1234, "strategyBreakdown": { "rules": 800, "cost": 200, "latency": 150, "sla-aware": 50, "lkgp": 34 }, "tierBreakdown": { "ultra": 100, "pro": 500, "standard": 400, "free": 234 }, "topProviders": [ { "provider": "openai", "calls": 500, "avgLatencyMs": 850 }, { "provider": "anthropic", "calls": 300, "avgLatencyMs": 1200 } ] } ``` ### Analitik pemampatan | Method | Path | Description | | ------ | ---------------------------- | -------------------------------------------------------------------------------------------------- | | GET | `/api/analytics/compression` | Statistik pemampatan terkumpul: token yang dijimatkan, % penjimatan, taburan mod, penggunaan enjin | **Contoh respons**: ```json { "window": "24h", "totalOriginalTokens": 5000000, "totalCompressedTokens": 3500000, "totalSavings": 1500000, "savingsPct": 30.0, "modeBreakdown": { "lite": 400, "standard": 600, "aggressive": 100, "ultra": 50, "rtk": 84 }, "engineBreakdown": { "caveman": 800, "rtk": 434 } } ``` ### Penjejakan kepelbagaian penyedia | Method | Path | Description | | ------ | -------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | GET | `/api/analytics/diversity` | Penjejakan kepelbagaian berdasarkan entropi Shannon: mencegah titik kegagalan tunggal dengan mengukur taburan penyedia | **Contoh respons**: ```json { "window": "24h", "shannonEntropy": 2.45, "maxEntropy": 3.17, "diversityRatio": 0.77, "providerUsage": { "openai": 0.4, "anthropic": 0.25, "google": 0.2, "kiro": 0.15 }, "warnings": ["OpenAI accounts for 40% of traffic — consider diversifying"] } ``` **Pengesahan:** Memerlukan sesi pengurusan atau kunci API berskop pengurusan. --- ## Operasi Pentadbir Titik akhir khusus pentadbir untuk pengurusan operasi. | Kaedah | Laluan | Penerangan | | ------ | ------------------------ | ---------------------------------------------------------------------------------------------- | | GET | `/api/admin/concurrency` | Baca had keserentakan semasa (global + setiap penyedia) | | POST | `/api/admin/concurrency` | Kemas kini had keserentakan — badan: `{global?: number, perProvider?: Record}` | **Pengesahan:** Memerlukan sesi pengurusan dengan skop pentadbir. --- ## Pengurusan Alat CLI Urus alat CLI yang berintegrasi dengan OmniRoute (antigravity, commandCode, devin-cli, dll.). Lihat [Rujukan Penyedia](./PROVIDER_REFERENCE.md) untuk senarai penuh. | Kaedah | Laluan | Penerangan | | ------ | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/cli-tools/all-statuses` | Status semua alat CLI (dipasang, versi, kali terakhir dilihat) | | GET | `/api/cli-tools/status` | Perincian status untuk satu alat CLI (pertanyaan `?tool=`) | | POST | `/api/cli-tools/apply` | Tulis konfigurasi yang dijana untuk sesuatu alat (`dryRun` mempratonton; `422` + `containerEphemeralTarget` apabila dikontena; `migration` mencatat YAML Codex legasi) | | GET | `/api/cli-tools/backups` | Senaraikan sandaran konfigurasi alat CLI | | POST | `/api/cli-tools/backups` | Cipta sandaran semua konfigurasi alat CLI | | POST | `/api/cli-tools/backups` | Pulihkan: titik akhir yang sama dengan `{tool, backupId}` dalam badan akan memulihkan sandaran tersebut | | GET | `/api/cli-tools/antigravity-mitm` | Status proksi MITM Antigravity (alat CLI "antigravity-mitm") | | POST | `/api/cli-tools/antigravity-mitm/alias` | Konfigurasikan alias antigravity-mitm | **Pengesahan:** Memerlukan sesi pengurusan. --- ## Kemahiran Ejen Urus kemahiran ejen AI (serupa dengan GPT tersuai OpenAI tetapi untuk ejen). | Kaedah | Laluan | Penerangan | | ------ | ---------------------------- | ----------------------------------------------------------------------------------------- | | GET | `/api/agent-skills` | Senaraikan semua kemahiran ejen (terbina dalam + tersuai) | | GET | `/api/agent-skills/[id]` | Dapatkan kemahiran ejen tertentu | | POST | `/api/agent-skills` | Cipta kemahiran ejen tersuai — badan: `{name, description, prompt, model?, temperature?}` | | PUT | `/api/agent-skills/[id]` | Kemas kini kemahiran ejen tersuai | | DELETE | `/api/agent-skills/[id]` | Padam kemahiran ejen tersuai | | GET | `/api/agent-skills/[id]/raw` | Dapatkan gesaan mentah + metadata (tanpa pelaksanaan) | | POST | `/api/agent-skills/generate` | Jana kemahiran baharu dengan AI daripada penerangan bahasa semula jadi | **Pengesahan:** Memerlukan sesi pengurusan atau kunci API berskop pengurusan. --- ## Pengurusan Cache Urus cache semantik dan cache penaakulan. | Kaedah | Laluan | Perihalan | | ------ | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/cache` | Gambaran keseluruhan cache: jumlah entri, kadar hit, saiz pada cakera | | GET | `/api/cache/entries` | Senaraikan entri cache (dengan penomboran) | | DELETE | `/api/cache/entries` | Padam entri cache (tapis mengikut parameter pertanyaan) | | GET | `/api/cache/stats` | Statistik cache terperinci (mengikut penyedia, mengikut model) | | GET | `/api/cache/reasoning` | Status cache penaakulan (untuk main semula penaakulan) | | DELETE | `/api/cache/reasoning` | Kosongkan cache penaakulan — parameter pertanyaan: `?toolCallId=` (tunggal) atau `?provider=

` atau tiada parameter (semua) | **Pengesahan:** Memerlukan sesi pengurusan. --- ## Sistem Memori Urus memori berterusan (FTS5 + pembenaman vektor). | Kaedah | Laluan | Perihalan | | ------ | ------------------ | -------------------------------------------------------------------------- | | GET | `/api/memory` | Senaraikan entri memori (tapis mengikut skop, jenis, pertanyaan carian) | | POST | `/api/memory` | Cipta entri memori baharu — badan: `{scope, type, content, metadata?}` | | GET | `/api/memory/[id]` | Dapatkan entri memori tertentu | | PUT | `/api/memory/[id]` | Kemas kini entri memori | | DELETE | `/api/memory/[id]` | Padam entri memori | | GET | `/api/memory?q=` | Cari memori (FTS5 + vektor) — statistik disertakan dalam respons yang sama | **Pengesahan:** Memerlukan sesi pengurusan atau kunci API dengan skop pengurusan. --- ## Webhook Urus langganan webhook untuk acara. | Kaedah | Laluan | Perihalan | | ------ | ------------------------------- | ---------------------------------------------------------------------- | | GET | `/api/webhooks` | Senaraikan semua langganan webhook | | POST | `/api/webhooks` | Cipta langganan webhook — badan: `{url, events[], secret?, active?}` | | GET | `/api/webhooks/[id]` | Dapatkan langganan webhook tertentu | | PUT | `/api/webhooks/[id]` | Kemas kini langganan webhook | | DELETE | `/api/webhooks/[id]` | Padam langganan webhook | | GET | `/api/webhooks/[id]/deliveries` | Senaraikan sejarah penghantaran untuk webhook (log kejayaan/kegagalan) | | POST | `/api/webhooks/[id]/test` | Hantar acara ujian kepada webhook | **Pengesahan:** Memerlukan sesi pengurusan. Lihat [Rangka Kerja Webhook](../frameworks/WEBHOOKS.md) untuk jenis acara penuh. --- ## Rangka Kerja Kemahiran Urus Kemahiran (rangka kerja sambungan ejen). | Kaedah | Laluan | Penerangan | | ------ | ------------------------ | ------------------------------------------------------------------------------------------------- | | GET | `/api/skills` | Senaraikan semua kemahiran yang dipasang (terbina dalam + tersuai) | | POST | `/api/skills/install` | Pasang kemahiran daripada laluan setempat atau URL | | DELETE | `/api/skills/[id]` | Nyahpasang kemahiran | | PUT | `/api/skills/[id]` | Dayakan atau nyahdayakan kemahiran — badan: `{enabled?: boolean, mode?: "on" \| "off" \| "auto"}` | | POST | `/api/skills/executions` | Jalankan kemahiran — badan: `{skillName, apiKeyId, input?, sessionId?}` | | GET | `/api/skills/executions` | Senaraikan sejarah pelaksanaan untuk semua kemahiran (tapis mengikut `?apiKeyId=`) | **Pengesahan:** Memerlukan sesi pengurusan atau kunci API berskop pengurusan. Lihat [Rangka Kerja Kemahiran](../frameworks/SKILLS.md) untuk butiran penuh. --- ## Pemalam Urus pemalam OmniRoute (sambungan pihak ketiga). | Kaedah | Laluan | Penerangan | | ------ | ---------------------------------- | ----------------------------------- | | GET | `/api/plugins` | Senaraikan pemalam yang dipasang | | POST | `/api/plugins/marketplace/install` | Pasang pemalam daripada marketplace | | DELETE | `/api/plugins/[name]` | Nyahpasang pemalam | | POST | `/api/plugins/[name]/activate` | Aktifkan pemalam | | POST | `/api/plugins/[name]/deactivate` | Nyahaktifkan pemalam | | GET | `/api/plugins/[name]/config` | Dapatkan konfigurasi pemalam | | PUT | `/api/plugins/[name]/config` | Kemas kini konfigurasi pemalam | **Pengesahan:** Memerlukan sesi pengurusan. Lihat [Rangka Kerja Pemalam](../frameworks/PLUGIN_SDK.md) untuk butiran penuh. --- ## Penghalaan Bayangan Perbandingan Shadow / A-B bagi penyedia **bukan permukaan REST kendiri** — ia dikonfigurasikan melalui penghalaan gabungan (lihat [Auto-Combo](../routing/AUTO-COMBO.md)). Metrik perbandingan bagi setiap gabungan disediakan oleh `GET /api/combos/metrics`. --- ## Perlindungan Periksa perlindungan masa jalan (pengesanan PII, pengesanan suntikan prompt, penyambungan visi). Perlindungan dijalankan pada setiap permintaan; pilihan keluar setiap panggilan dilakukan melalui pengepala permintaan `x-omniroute-disabled-guardrails` — tiada permukaan dayakan/nyahdayakan yang disimpan secara kekal. | Kaedah | Laluan | Penerangan | | ------ | ---------------------- | ----------------------------------------------------------------------------------------------------------------- | | GET | `/api/guardrails` | Senaraikan perlindungan yang didaftarkan dan statusnya (nama / didayakan / keutamaan) | | POST | `/api/guardrails/test` | Jalankan simulasi saluran paip sebelum panggilan menggunakan input sampel — badan: `{input, disabledGuardrails?}` | **Pengesahan:** Memerlukan sesi pengurusan. Lihat [Keselamatan > Perlindungan](../security/GUARDRAILS.md) untuk butiran penuh. --- --- ## Pengesahan Lihat [Pengesahan Pengurusan](../guides/MANAGEMENT-AUTH.md) untuk empat keluarga kelayakan (sesi papan pemuka, token CLI tempatan, Token Akses `oma_live_…`, kunci API berskop pengurusan) dan perbezaannya daripada kunci inferens. - Laluan papan pemuka (`/dashboard/*`) menggunakan kuki `auth_token` - Log masuk menggunakan cincangan kata laluan yang disimpan; kembali kepada `INITIAL_PASSWORD` - Togol `requireLogin` boleh ditukar melalui `/api/settings/require-login` - Laluan `/v1/*` secara pilihan memerlukan kunci API Bearer apabila `REQUIRE_API_KEY=true` - "token pengurusan" / "kunci API berskop pengurusan" dalam rujukan ini bermaksud salah satu keluarga dalam panduan tersebut — bukan jenis rahsia tambahan yang tidak ditakrifkan > **Perubahan pecah (v3.8.0)** — `/api/v1/agents/tasks/*` dan titik akhir pengurusan tempoh bertenang kini memerlukan **pengesahan pengurusan** (kuki `auth_token` papan pemuka atau kunci API berskop pengurusan). Klien yang sebelum ini memanggil laluan ini tanpa pengesahan akan menerima `401 Unauthorized`. Lihat komit `588a0333` (`fix(auth): require management auth for agent and cooldown APIs`).