# API Reference (العربية) 🌐 **Languages:** 🇺🇸 [English](../../../../reference/API_REFERENCE.md) · 🇪🇹 [am](../../../am/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) · 🇲🇾 [ms](../../../ms/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) --- 🌐 **اللغات:** 🇺🇸 [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) المرجع الأساسي لواجهة OmniRoute API. يغطي الواجهة العامة `/v1` ونقاط نهاية الإدارة الأكثر استخدامًا؛ ويُعدّ كلٌّ من [`docs/openapi.yaml`](../openapi.yaml) وشجرة المسارات ضمن `src/app/api/` المصدرين الشاملين. للاطلاع على البروتوكول المتوافق مع OpenAI ومصفوفة إمكانات موفّري الخدمة، راجع [`OPENAI_COMPATIBILITY.md`](./OPENAI_COMPATIBILITY.md). --- ## جدول المحتويات - [إكمالات الدردشة](#chat-completions) - [عقود إيجار حصرية للجلسات المُدارة](#exclusive-managed-session-leases) - [التضمينات](#embeddings) - [توليد الصور](#image-generation) - [التعرّف الضوئي على المستندات](#document-ocr) - [سرد النماذج](#list-models) - [بيان إضافة المزوّد](#provider-plugin-manifest) - [نقاط نهاية التوافق](#compatibility-endpoints) - [واجهة برمجة تطبيقات الملفات](#files-api) - [واجهة برمجة تطبيقات الدُفعات](#batches-api) - [واجهة برمجة تطبيقات البحث](#search-api) - [البث عبر WebSocket](#websocket-streaming) - [الحصص والإبلاغ عن المشكلات](#quotas--issues-reporting) - [ذاكرة التخزين المؤقت الدلالية](#semantic-cache) - [لوحة المعلومات والإدارة](#dashboard--management) - [إدارة المجموعات](#combo-management) - [خطافات الويب](#webhooks) - [المفاتيح المسجّلة (الإدارة التلقائية)](#registered-keys-auto-management) - [بروتوكول الوكلاء](#agents-protocol) - [وكلاء الإدارة](#management-proxies) - [المرونة (موسّعة)](#resilience-extended) - [المهارات](#skills) - [الذاكرة](#memory) - [خادم MCP](#mcp-server) - [خادم A2A](#a2a-server) - [السحابة والتقييمات والتقدير](#cloud-evals--assess) - [معالجة الطلبات](#request-processing) - [المصادقة](#authentication) --- ## إكمالات المحادثة ```bash POST /v1/chat/completions Authorization: Bearer your-api-key Content-Type: application/json { "model": "cc/claude-opus-4-6", "messages": [ {"role": "user", "content": "اكتب دالةً لـ..."} ], "stream": true } ``` ### الترويسات المخصصة | الترويسة | الاتجاه | الوصف | | ------------------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `X-OmniRoute-No-Cache` | الطلب | اضبطها على `true` لتجاوز ذاكرة التخزين المؤقت | | `x-omniroute-no-memory` | الطلب | اضبطها على `true` لتخطي حقن الذاكرة والمهارات لهذا الطلب (يماثل عدم استخدام ذاكرة التخزين المؤقت؛ ويتجنب التكلفة الإضافية للرموز المميزة/التكلفة لكل استدعاء) | | `X-OmniRoute-Progress` | الطلب | اضبطها على `true` لتلقي أحداث التقدم | | `X-Session-Id` | الطلب | مفتاح جلسة ثابت لتقارب الجلسات الخارجية | | `x_session_id` | الطلب | صيغة الشرطة السفلية مقبولة أيضًا (عبر HTTP مباشرةً) | | `X-OmniRoute-Session-Id` | الطلب | وسم جلسة/محادثة يوفره المستدعي (ويغذي الذاكرة أيضًا). عند وجوده، يُحفَظ حرفيًا في `call_logs.session_tag` لإسناد التكلفة لكل جلسة (#8249) — ولا يُنشأ مطلقًا عند غيابه | | `Idempotency-Key` | الطلب | مفتاح إزالة التكرار (نافذة مدتها 5 ثوانٍ) | | `X-Request-Id` | الطلب | مفتاح بديل لإزالة التكرار | | `x-omniroute-connection` | الطلب | ثبّت طلبًا أحادي النموذج على اتصال واحد بموفر الخدمة (الحساب) باستخدام معرّفه — راجع [تثبيت الحساب لكل طلب](#account-pinning-per-request) | | `X-OmniRoute-Cache` | الاستجابة | `HIT` أو `MISS` (من دون بث) | | `X-OmniRoute-Idempotent` | الاستجابة | `true` إذا أزيل التكرار | | `X-OmniRoute-Progress` | الاستجابة | `enabled` إذا كان تتبع التقدم مفعّلًا | | `X-OmniRoute-Session-Id` | الاستجابة | معرّف الجلسة الفعلي الذي يستخدمه OmniRoute | | `X-OmniRoute-Request-Id` | الاستجابة | معرّف ربط الطلب (عندما يكون معروفًا) | | `X-OmniRoute-Version` | الاستجابة | إصدار بناء OmniRoute (موجود دائمًا) | | `X-OmniRoute-Cost-Saved` | الاستجابة | المبلغ بالدولار الأمريكي الذي وفرته ذاكرة التخزين المؤقت عند `HIT` (إصابات ذاكرة التخزين المؤقت فقط) | | `X-OmniRoute-Decision` | الاستجابة | تتبع التوجيه: `strategy=; provider=; latency_ms=` (`` هي الاستراتيجية المركبة، أو `single` لطلب غير مركب) — موجود دائمًا في استجابات الإكمال | > ملاحظة حول Nginx: إذا كنت تعتمد على الترويسات التي تحتوي على شرطات سفلية (مثل `x_session_id`)، ففعّل `underscores_in_headers on;`. #### تثبيت الحساب لكل طلب عندما يكون لدى موفر الخدمة عدة اتصالات (حسابات أو مفاتيح)، يختار OmniRoute عادةً أحدها من خلال استراتيجية اختيار الحساب. وبدلًا من ذلك، يمكن للطلب تثبيت اتصال محدد باستخدام الترويسة `x-omniroute-connection`: ```bash curl http://localhost:20128/v1/chat/completions \ -H "Authorization: Bearer <مفتاح OmniRoute API الخاص بك>" \ -H "Content-Type: application/json" \ -H "x-omniroute-connection: " \ -d '{"model": "codex/gpt-5.5", "messages": [{"role": "user", "content": "مرحبًا"}]}' ``` - **مكان العثور على المعرّف.** افتح صفحة المزوّد في لوحة المعلومات (**لوحة المعلومات → المزوّدون → **) وانقر على شارة المعرّف `xxxxxxxx…` في صف الاتصال — سيؤدي ذلك إلى نسخ معرّف الاتصال الكامل. - **الطلبات التي تستخدمه.** طلبات النموذج الواحد (`provider/model`) على `/v1/chat/completions` و`/v1/messages` و`/v1/responses`. تتجاهل التركيبات هذا الرأس: ثبّت حسابًا لكل خطوة في التركيبة من خلال الاتصال الخاص بتلك الخطوة بدلًا من ذلك. - **التثبيت صارم وليس تفضيلًا.** يُستخدم الاتصال المثبّت حصريًا. يؤدي أي فشل داخل الطلب إلى تسجيل فترة التهدئة الخاصة بالحساب، لكنه **لا** ينتقل إلى حساب آخر تابع للمزوّد نفسه. - **فترة التهدئة والحصة تلغيان التثبيت.** عندما يكون الاتصال المثبّت في فترة تهدئة، أو تكون حصته مستنفدة، أو يكون محظورًا بموجب سياسة حصة، تتراجع الطلبات اللاحقة إلى اتصالات المزوّد الأخرى، تمامًا مثل حركة البيانات غير المثبّتة. - **تفشل المعرّفات المجهولة أو المعطّلة.** المعرّف غير الموجود في مجموعة المزوّد النشطة (سواء كان محذوفًا، أو معطّلًا، أو تابعًا لمزوّد آخر) لا يترك أي حساب مؤهّل، ولذلك يفشل الطلب بدلًا من توجيهه ضمنيًا إلى مكان آخر. يرسل Claude Code الرؤوس المخصّصة من خلال `ANTHROPIC_CUSTOM_HEADERS`. ضعه في كتلة `env` داخل `~/.claude/settings.json`، أو في `.claude/settings.json` على مستوى المشروع لتثبيت حساب مختلف لكل مشروع: ```jsonc { "env": { "ANTHROPIC_BASE_URL": "http://:20128", "ANTHROPIC_AUTH_TOKEN": "", "ANTHROPIC_CUSTOM_HEADERS": "x-omniroute-connection: ", }, } ``` المصدر: `src/sse/handlers/chat.ts` (قراءة الرأس)، و`src/sse/services/auth.ts` و `src/sse/services/sessionAffinityPin.ts` (إلغاء التثبيت والتحقق من عدم الوجود في المجموعة). > **رؤوس قياس التكلفة:** تحمل استجابات النجاح غير المتدفقة أيضًا مجموعة قياس التكلفة `X-OmniRoute-*` — وهي `X-OmniRoute-Response-Cost` (بالدولار الأمريكي، مع 10 منازل عشرية ثابتة؛ `0.0000000000` للخدمات المجانية/غير المسعّرة)، و`X-OmniRoute-Tokens-In` / `X-OmniRoute-Tokens-Out`، و`X-OmniRoute-Model`، و`X-OmniRoute-Provider`، و`X-OmniRoute-Latency-Ms`، و`X-OmniRoute-Cache-Hit`، و`X-OmniRoute-Fallback-Attempts` (فقط عندما تكون القيمة > 0)، بالإضافة إلى `X-OmniRoute-Request-Id` و`X-OmniRoute-Version`. تُصدَر هذه الرؤوس بواسطة إكمالات المحادثة، و`/v1/responses`، و`/v1/messages`، **وكذلك نقاط نهاية الوسائط** — `/v1/embeddings`، و`/v1/images/generations`، و`/v1/audio/speech`، و`/v1/audio/transcriptions`، و`/v1/rerank`، و`/v1/videos/generations`، و`/v1/music/generations`، و`/v1/moderations` (بتكلفة `0` دائمًا). تُحتسب تكلفة الوسائط لكل نوع (لكل صورة، أو لكل ثانية، أو لكل حرف، أو لكل وحدة بحث) عند توفر التسعير، وإلا فتكون `0` (السماح بالمتابعة عند الفشل). > **دلالات تكلفة إصابة ذاكرة التخزين المؤقت:** عند حدوث إصابة في ذاكرة التخزين المؤقت الدلالية (`X-OmniRoute-Cache-Hit: true`)، لا يُجرى أي استدعاء إلى الخدمة الأصلية، ولذلك تكون قيمة `X-OmniRoute-Response-Cost` هي `0.0000000000` (التكلفة **الإضافية** لخدمة الإصابة). تُبلّغ التكلفة الأصلية/التي كان سيجري تكبدها بشكل منفصل في `X-OmniRoute-Cost-Saved`. ينبغي لمستهلكي بيانات الفوترة جمع قيم `X-OmniRoute-Response-Cost` (لا تكلّف الإصابات شيئًا)؛ ويمكن لتحليلات ذاكرة التخزين المؤقت تجميع قيم `X-OmniRoute-Cost-Saved`. ## عقود الإيجار الحصرية للجلسات المُدارة يُعد تأجير الجلسات المُدارة حصريًا عقد توجيه اختياريًا ومحايدًا تجاه العميل: يحتفظ مالك نشط واحد باتصال OmniRoute مؤهل واحد. ولا يؤجّر نموذجًا، ولا يتطلب OAuth، ولا يحدد عميلًا بعينه، ولا يتطلب مزودًا بعينه. يجب أن يحتوي مفتاح API المستخدم للمصادقة على النطاق `lease:exclusive` وقائمة صريحة غير فارغة باسم `allowedConnections`. وتفرض حدود عمليات التعديل في قاعدة البيانات وجود الحقلين معًا عند إنشاء المفتاح وإجراء التحديثات الجزئية. ```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"} ``` تعرض استجابات الاستحواذ والتجديد والتحرير الناجحة الطوابع الزمنية و`state` والقيمة الموجبة الدقيقة لـ`generation`، لكنها لا تعرض أبدًا الاتصال المحدد أو بيانات الاعتماد. ويوفر التجديد والتحرير قيمة `generation` في متن JSON: ```json { "action": "renew", "generation": 1 } ``` ```json { "action": "release", "generation": 1, "reason": "OWNER_EXIT" } ``` يمكن لمالك عقد إيجار نشط أن يطلب صراحةً بيانات تعريف وصفية آمنة للخصوصية لارتباطه الحالي: ```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" } } ``` يُسيَّج إجراء الحالة الاختياري هذا بالمالك المبهم، ومفتاح API المُدار والمُصادق عليه، والقيمة الدقيقة للجيل النشط، وذلك ضمن معاملة واحدة في قاعدة البيانات. لا تكون `displayName` سوى اسم الاتصال المضبوط بعد إزالة المسافات الزائدة؛ وتكون `null` عند عدم وجود اسم مضبوط وآمن. لا يستبدل OmniRoute هذا الاسم أبدًا بعنوان بريد إلكتروني أو بهوية حساب مُنشأة. وقيمة المزود هي تسمية عرض غير حساسة، وليست أبدًا معرّفًا مُنشأً لمزود متوافق. وتُستبعد بيانات الاعتماد والرموز المميزة وملفات تعريف الارتباط ومعرّفات الاتصال أو مفاتيح API الأولية وتجزئات المالك وأسرار التسييج وبيانات التوجيه الداخلية. تُرجع جميع عمليات البحث ذات المفتاح الخاطئ أو المالك الخاطئ أو الجيل القديم، وكذلك عمليات البحث المفقودة أو المنتهية الصلاحية أو المُحررة أو المُبطلة، الخطأ نفسه `409 LEASE_FENCE_STALE` من دون بيانات تعريف الاتصال. ولا يكون لدى العميل الذي تلقى استجابة انتظار السعة أي ارتباط نشط لفحصه. عندما ينقل التوجيه عقد إيجار نشطًا، يظل الجيل نفسه صالحًا وتُرجع الحالة ذريًا الارتباط الجديد، وليس القديم أبدًا. ويظل العملاء الحاليون من دون تغيير لأن استجابات الاستحواذ والتجديد والتحرير والانتظار تحتفظ ببُناها السابقة. لا يغيّر عقد الخادم هذا نقطة `/status` القياسية في OpenAI Codex. يُبلغ Codex القياسي حاليًا عن مزود النموذج وحالة المصادقة/الحساب المضمنة، لكنه لا يعرض بيانات تعريف حسابات اعتباطية لمزودين مخصصين؛ ويجب أن يستدعي تكامل لاحق للعميل هذا الإجراء وأن يقرر كيفية عرض `connection.displayName`. بعد ذلك، يرسل كل طلب استدلال مُدار ترويستي التحكم كلتيهما: ```http X-OmniRoute-Lease-Owner: vlo_<43-base64url-characters> X-OmniRoute-Lease-Generation: 1 ``` يُسيَّج المالك الدقيق والجيل والاتصال النشط ومفتاح API المُصادق عليه مباشرةً قبل كل محاولة مدعومة مع المزود العلوي. تفشل إعادة تشغيل المالك والجيل باستخدام مفتاح آخر حتى عندما يسمح ذلك المفتاح بالاتصال نفسه. ولا تُخزَّن قيم المالك الأولية بصورة دائمة، ولا تُسجَّل، ولا يُحتفظ بها في لقطة الطلب، ولا تُمرَّر إلى المزود العلوي. يُرجع التنافس المؤقت HTTP `429` مع `Retry-After` وما يلي: ```json { "state": "WAITING_FOR_CAPACITY", "error": { "type": "lease_error", "code": "LEASE_CAPACITY_UNAVAILABLE" }, "reason": "NO_FREE_ELIGIBLE_CONNECTION", "retryAfter": 30 } ``` تعني هذه الاستجابة فقط أن مجموعة العناصر المؤهلة العادية لم تكن فارغة، وأن كل اتصال مرشح متاح كان محجوزًا بعقد إيجار نشط لمالك آخر. وتحتفظ النماذج/المزودون غير المدعومين، وعدم تطابق السياسة، وفترة التهدئة، والحصة، والحالة الصحية، وغيرها من حالات فشل الأهلية العادية، باستجابات OmniRoute الحالية الخاصة بها. ### `x-omniroute-compression` تجاوز خطة الضغط لكل طلب. يتمتع بأعلى أولوية — إذ يتقدم على تجاوز مجموعة التوجيه، والملف الشخصي النشط، والمشغّل التلقائي، والقيمة Default في اللوحة. القيم: | القيمة | التأثير | | ------------- | -------------------------------------------------------------------------------------- | | `off` | لا يوجد ضغط لهذا الطلب. | | `default` | ملف Default المستمد من اللوحة (يتجاهل الملف الشخصي النشط). تظل المحركات الفاقدة معطلة. | | `safe` | إزالة التكرار وطي المسافات البيضاء فقط. | | `allow-lossy` | الاحتفاظ بخطة المشغّل لهذا الطلب، بما في ذلك الملخصات وإعادة صياغة الأسلوب. | | `engine:` | محرك واحد عند تمكينه، مثل `engine:rtk`. اشتراك اختياري لذلك المحرك على مستوى الطلب. | | `` | مجموعة مُسمّاة، تتم مطابقتها بالاسم أولًا (من دون حساسية لحالة الأحرف)، ثم بالمعرّف. | ملاحظات: - تُتجاهل القيم غير المعروفة (ولا يُرفض الطلب أبدًا)؛ ويعود الحل إلى ترتيب الأولوية العادي للمشغّل. - إذا اشتركت مجموعات متعددة في اسم واحد، فمرّر **id** المجموعة للحصول على تطابق حتمي. - لا يمكن تحديد مجموعة اسمها `off` أو `default` بالاسم (لأن هاتين الكلمتين المفتاحيتين تُفسَّران أولًا)؛ لذا أشِر إلى هذه المجموعة بواسطة معرّفها. - مفتاح الضغط الرئيسي هو بوابة صارمة: عندما يكون الضغط معطلًا عموميًا، لا يمكن لهذا الترويس تمكينه. تُعاد الخطة المطبقة في ترويسة الاستجابة: ``` X-OmniRoute-Compression: ; source= ``` حيث تكون `` واحدة من `request-header` أو `routing-override` أو `active-profile` أو `auto-trigger` أو `default` أو `off`. --- ## التضمينات ```bash POST /v1/embeddings Authorization: Bearer your-api-key Content-Type: application/json { "model": "nebius/Qwen/Qwen3-Embedding-8B", "input": "The food was delicious" } ``` المزوّدون المتاحون: Nebius، وOpenAI، وMistral، وTogether AI، وFireworks، وNVIDIA، و**OpenRouter**، وJina AI. تكون معرّفات الكتالوج بالصيغة `provider/model` (مثال: `jina-ai/jina-embeddings-v5-omni-small`). كما يتم التعرّف على معرّفات نماذج Jina المجرّدة التي تظهر في السجل (على سبيل المثال `jina-embeddings-v5-text-small` و`jina-reranker-v3.5`). تستخدم عمليات التضمين/إعادة الترتيب/التصنيف/التقسيم في Jina بيانات اعتماد لوحة التحكم `jina-ai` أولًا؛ ولا يُستخدم `JINA_AI_API_KEY` كخيار احتياطي إلا في حال عدم وجود مفتاح في لوحة التحكم. بطاقة `jina-reader` مخصّصة لـ Reader / `r.jina.ai` فقط (`POST /v1/web/fetch`)، ولا توفّر مطلقًا خدمات التضمين أو إعادة الترتيب. تقبل نماذج السجل التي تعلن دعمها للوسائط المتعددة أيضًا ما يصل إلى 32 عنصرًا منظّمًا ومحايدًا تجاه المزوّد. أنواع عناصر الوسائط هي `text` و`image` و`audio` و`video` و`document`. ويكون `source` الخاص بالوسائط إما `{"type":"url","url":"https://..."}` أو `{"type":"base64","data":"...","media_type":"..."}`. يقبل Jina v5 Omni (`jina-ai/jina-embeddings-v5-omni-small` و`jina-ai/jina-embeddings-v5-omni-nano` والاسم البديل للعائلة `jina-ai/jina-embeddings-v5-omni` → omni-small) أيضًا مستندات EmbeddingsV5Request الأصلية الخاصة بـ Jina، ويقوم **بتمريرها كما هي** إلى `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,..." }] } ] } ``` يمكن لقيم `{ image | audio | video | pdf }` الأصلية أن تكون عنوان URL عامًا يستخدم HTTPS، أو URI من نوع `data:`، أو بيانات base64 خامًا. لا يحوّل OmniRoute هذه الكائنات إلى سلاسل نصية ولا يجلب عناوين URL الأصلية للصور — بل تسترجع Jina الوسائط العامة بنفسها. تُمرَّر حقول Jina الإضافية (`task` و`normalized` و`truncate` و`embedding_type`). وتظل وحدات SKU النصية فقط من Jina ترفض المستندات غير النصية. حدود الأمان والنقل: - يجب أن تكون عناوين URL للوسائط البعيدة عامة وتستخدم HTTPS. تُجلب عناصر `{type,source:url}` القياسية من جهة الخادم (مع إعادة التحقق من عمليات إعادة التوجيه، والمهلة الزمنية، وحدود الحجم، وDNS العام، وتثبيت الاتصال)، ثم تُضمَّن قبل استدعاء المزوّد. أما عناصر Jina الأصلية `{image:"https://..."}` فتُمرَّر كما هي بعد إجراء فحص HTTPS العام نفسه؛ وتتولى Jina جلب عنوان URL. - تقتصر وسائط base64 المضمّنة على 8 MiB بعد فك الترميز لكل عنصر، و16 MiB بعد فك الترميز عبر الطلب بأكمله. التحويل الخاص بالمزوّد (لا تُمرَّر العناصر القياسية دون تغيير مطلقًا): - نماذج Jina متعددة الوسائط: يتحول كل عنصر من المستوى الأعلى إلى كائن واحد مرتبط بنمط وسائط (`text` / `image` / `audio` / `video` / `pdf`) باستخدام عناوين URI من نوع data للوسائط المضمّنة؛ متجه واحد لكل عنصر من المستوى الأعلى. - عائلة Gemini Embedding 2: تتحول مصفوفة واحدة من المستوى الأعلى إلى طلب أصلي واحد `models/{model}:embedContent` يحتوي على `content.parts` (`text` أو `inline_data`). - llama.cpp (`llama-cpp/`، وأي نموذج حمّله الخادم المحلي): تتحول عناصر `text` القياسية إلى سلاسل نصية عادية، وتتحول عناصر `image` / `audio` / `video`، كل منها، إلى كائن `{"content": [part]}` واحد، باستخدام أجزاء محتوى المحادثة الخاصة بـ llama-server (`image_url`، و`input_audio` بالتنسيق `wav` / `mp3` / `flac`، و`input_video`) مع بيانات مضمّنة؛ متجه واحد لكل عنصر من المستوى الأعلى. يجب تشغيل الخادم باستخدام `--embedding --mmproj …`؛ ومن دون جهاز إسقاط، سيرفض الخادم الوسائط بنفسه. `document` غير مدعوم. - ترفض النماذج غير المعروفة/الديناميكية التي لا تحتوي على بيانات وصفية صريحة للأنماط الإدخال المنظّم باستخدام 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" } ``` تُرجع تركيبات النموذج/النمط غير المدعومة HTTP 400 بدلًا من فرض تحويل العنصر. وتستمر حقول الامتداد غير المرتبطة بالإدخال في طلبات السلاسل النصية/الرموز القديمة في المرور دون تغيير. ```bash # عرض جميع نماذج التضمين GET /v1/embeddings ``` --- ## توليد الصور ```bash POST /v1/images/generations Authorization: Bearer your-api-key Content-Type: application/json { "model": "openai/gpt-image-2", "prompt": "غروب شمس جميل فوق الجبال", "size": "1024x1024" } ``` تشمل الجهات المزوّدة المتاحة OpenAI (GPT Image 2)، وxAI (Grok Image)، وTogether AI (FLUX)، وFireworks AI، وNebius (FLUX)، وHyperbolic، وNanoBanana، و**OpenRouter**، و**ZenMux**، وSD WebUI (محلي)، وComfyUI (محلي). يعيد `n` عدد `n` من الصور في `data[]`. بالنسبة إلى الجهات المزوّدة التي تعيد واجهة API الأولية لديها صورة واحدة لكل استدعاء (Black Forest Labs، وStability AI، وLeonardo، وIdeogram، وHaiper، وHyperbolic، وMagnific/Freepik، وNVIDIA NIM، وCloudflare Workers AI)، يُجرى عدد `n` من الاستدعاءات الأولية المنفصلة، بحد أقصى 4 استدعاءات متزامنة. تُزاح قيمة `seed` الثابتة حسب فهرس الاستدعاء (`seed`، و`seed + 1`، و…)، بحيث تختلف الصور مع بقائها قابلة لإعادة الإنتاج. الحد الأقصى لـ`n` هو 10. يفشل الطلب بأكمله إذا فشل أي استدعاء. توجد قائمة تنسيقات التوزيع المتوازي في `SINGLE_IMAGE_FANOUT_FORMATS` داخل `open-sse/handlers/imageGeneration/fanOut.ts`. يعيد ZenMux استخدام اتصال مفتاح API الحالي، ويقبل البادئتين `zenmux/` أو `zm/`: - يستخدم `zenmux/openai/gpt-image-2` واجهة OpenAI Images API الخاصة بـZenMux. تشمل الخيارات `size`، و`quality`، و`n`، و`output_format`، و`output_compression`، و`background`، و`response_format`. - تستخدم الجهات الناشرة الأخرى، مثل `zm/meta/muse-image-1.0`، نقطة النهاية `:predict` في Vertex AI لدى ZenMux. يُطابق `n` الحقل `sampleCount`، ويُطابق `aspect_ratio` الحقل `aspectRatio`، ويُطابق `image_size` (`1K`، و`2K`، و`4K`) الحقل `sampleImageSize`. لا توفّر قيمة `size` بالبكسل سوى نسبة أبعاد، ولا تضمن أبعادًا محددة بالبكسل. تختلف النسب والدقات والأعداد المدعومة حسب النموذج. - يختار `zm/inclusionai/ming-image-0.1-design` أبعاده بنفسه. احذف `size`، و`aspect_ratio`، و`image_size`؛ إذ تُرجع القيم الصريحة HTTP 400. يمكن طلب PNG وJPEG وWebP باستخدام `output_format`. يدعم هذا التكامل توليد الصور من النص، وليس تحرير الصور المرجعية. تُوحَّد مخرجات Vertex إلى `data[].b64_json`؛ ويُرجع `response_format: "url"` عنوان URL أوليًا عبر HTTPS أو عنوان URL لبيانات base64 عندما لا تتوفر سوى بايتات الصورة. تُرجع المخرجات الفارغة أو المصفّاة خطأً بدلًا من نجاح فارغ. يعتمد الوصول إلى النماذج على حساب ZenMux. راجع [واجهة Vertex API الخاصة بـZenMux](https://docs.zenmux.ai/api/vertexai/generate-images) و [واجهة OpenAI Images API](https://docs.zenmux.ai/api/openai/generate-an-image). ```bash # سرد جميع نماذج الصور GET /v1/images/generations ``` --- ## التعرّف الضوئي على الأحرف في المستندات ```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` مزوّد OCR عبر بادئة `provider/model`؛ ويُربط معرّف النموذج المجرّد (مثل `mistral-ocr-latest`) بمزوّده المسجّل، وعند حذف `model` يكون الإعداد الافتراضي هو Mistral (`mistral-ocr-latest`). المزوّدون المسجّلون (`open-sse/config/ocrRegistry.ts`): | معرّف المزوّد | معرّف النموذج | قيمة `model` | ملاحظات | | ----------------------------- | -------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | `mistral` | `mistral-ocr-latest` | `mistral/mistral-ocr-latest` (أو `mistral-ocr-latest` مجرّدًا) | متزامن — تُعاد الاستجابة مباشرةً من استدعاء المصدر الوحيد. | | `azure-document-intelligence` | `prebuilt-read` | `azure-document-intelligence/prebuilt-read` | مصدر غير متزامن (`analyze` + الاستقصاء) — انظر أدناه. | | `vertex-deepseek-ocr` | `deepseek-ocr-maas` | `vertex-deepseek-ocr/deepseek-ocr-maas` | متزامن، عبر نقطة نهاية الشريك `openapi/chat/completions` في Vertex AI — انظر أدناه للمصادقة/عنوان URL. | يستجيب المزوّدون الثلاثة جميعًا بالنص نفسه ذي البنية المشابهة لبنية Mistral: ```json { "pages": [{ "index": 0, "markdown": "# النص المستخرج..." }], "model": "mistral-ocr-latest", "usage_info": { "pages_processed": 1 } } ``` ### تدفّق الاستقصاء في Azure Document Intelligence واجهة API المسماة `analyze` في Azure Document Intelligence غير متزامنة: يُعيد الطلب الأولي ترويسة `Operation-Location` بدلًا من نص استجابة، ويجب استقصاء النتيجة. يستقصي المعالج (`open-sse/handlers/ocr.ts`) عنوان URL ذلك كل ثانية لما يصل إلى 30 محاولة، ويفشل سريعًا (أي لا يواصل الاستقصاء) عند استجابة استقصاء ليست `ok` أو عند حالة `"failed"`، ويُعيد `504` إذا كانت العملية لا تزال قيد التشغيل بعد استنفاد عدد المحاولات. تُطبَّع استجابة Azure النهائية إلى بنية `pages`/`markdown` نفسها التي تستخدمها Mistral قبل إعادتها إلى المستدعي، ولذلك لا تحتاج شيفرة العميل إلى معالجة المزوّد كحالة خاصة. ### مصادقة Vertex AI DeepSeek OCR وتحديد نقطة النهاية يعيد `vertex-deepseek-ocr` استخدام مصادقة Vertex AI نفسها التي يدعمها OmniRoute بالفعل لحركة مرور المحادثات/الصور (`open-sse/executors/vertex.ts`): يكون مفتاح API الخاص بالاتصال إما بيانات اعتماد JSON لحساب خدمة (تُستبدل برمز وصول OAuth قصير الأجل عبر تدفّق JWT bearer) أو رمز وصول OAuth مُنشأ مسبقًا يُستخدم كما هو. عنوان URL لنقطة نهاية المصدر هو نقطة نهاية الشريك العامة `openapi/chat/completions` الخاصة بـ Vertex، ويُنشأ من مشروع الاتصال ومنطقته — تكون لقيمة `providerSpecificData.project`/`providerSpecificData.region` الصريحة الأولوية دائمًا؛ وإلا فيُستمد المشروع من `project_id` في JSON الخاص بحساب الخدمة، وتكون المنطقة الافتراضية `us-central1`. يحدث كلا التحديدين في `open-sse/handlers/ocr.ts` (`resolveVertexOcrAccessToken`، `resolveVertexOcrBaseUrl`)، وتستخدمهما `src/app/api/v1/ocr/route.ts` قبل تمرير الطلب إلى `handleOcr`. --- ## سرد النماذج ```bash GET /v1/models Authorization: Bearer your-api-key → يُرجع جميع نماذج المحادثة والتضمين والصور + التركيبات بتنسيق OpenAI ``` ### بادئات معرّفات النماذج (`?prefix=`) تُعرض معظم النماذج تحت **بادئة المزوّد**. تتحكم علامة الميزة `MODELS_CATALOG_PREFIX_MODE` في البادئة التي تحصل عليها، ويمكن تجاوزها **لكل طلب** باستخدام معامل استعلام — وهذا مفيد لعميل يريد قائمة مرتبة دون تغيير الإعداد على مستوى الخادم لجميع المستخدمين الآخرين: ```bash GET /v1/models?prefix=alias # معرّف واحد لكل نموذج — بادئة الاسم المستعار القصيرة GET /v1/models?prefix=dual # كلا الشكلين (الإعداد الافتراضي للخادم) GET /v1/models?prefix=canonical # بادئة معرّف المزوّد الكاملة فقط ``` | الوضع | ما يصدر | ملاحظات | | ----------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `dual` | `cc/claude-sonnet-4-6` **و** `claude/claude-sonnet-4-6` | **الافتراضي.** يوجَّه كلا المعرّفين إلى النموذج نفسه؛ وقد أُبقي عليهما لكي تستمر إعدادات العملاء التي ثبّتت أيًّا من الشكلين في العمل. يؤدي ذلك إلى مضاعفة حجم الكتالوج تقريبًا. | | `alias` | `cc/claude-sonnet-4-6` | إدخال واحد لكل نموذج. يستمر المزوّدون الذين لا يملكون اسمًا مستعارًا مميزًا في إصدار إدخالهم، لذا لا يُفقد أي شيء. | | `canonical` | `claude/claude-sonnet-4-6` | إدخال واحد لكل نموذج تحت بادئة معرّف المزوّد الكاملة. يصدر أيضًا المزوّدون الذين لا يملكون اسمًا مستعارًا مميزًا (مثل `antigravity/…` و`agy/…`) معرّفهم الوحيد هنا، لذا لا يُفقد أي شيء. | يمكن أيضًا التعرّف على النسخة المطابقة في وضع `dual` دون معامل الاستعلام: إذ تحمل حقل `parent` يشير إلى المعرّف الأساسي. ينبغي للعملاء الذين يعرضون منتقي نماذج طلب `?prefix=alias` — وهذا ما يفعله [امتداد OmniCopilot لـ VS Code](../guides/VSCODE-COPILOT.md). ### مرشحات الاستكشاف (`?capability=` و`?min_context=` و`?kind=` و`?q=`) تقبل `GET /v1/models` مرشحات استكشاف اختيارية. من دون أي منها، تظل الاستجابة دون تغيير. وهي تضيّق نطاق الكتالوج الذي يراه المستدعي بالفعل (تُطبّق أذونات مفتاح API أولًا)، وتُشغّل قبل ترقيم الصفحات ذي نمط OpenAI باستخدام `limit` / `after`: ```bash GET /v1/models?capability=vision&capability=tool_calling # يجب أن تكون كل إمكانية مدرجة صحيحة GET /v1/models?capability=vision,reasoning&min_context=200000 GET /v1/models?kind=embedding # قيمة `type` في الكتالوج؛ الصفوف التي لا تحتوي عليها تُعد `chat` GET /v1/models?q=sonnet&limit=10 # مطابقة غير حساسة لحالة الأحرف على المعرّف أو الاسم ``` | المعامل | القيم | | ------------- | --------------------------------------------------------------------------------------------------- | | `capability` | `attachment`, `reasoning`, `structured_output`, `temperature`, `thinking`, `tool_calling`, `vision` | | `min_context` | عدد صحيح غير سالب، تتم مقارنته مع `context_length` | | `kind` | `chat`, `audio`, `embedding`, `image`, `moderation`, `music`, `rerank`, `video` | | `q` | من 1 إلى 200 حرف | تؤدي القيمة غير المعروفة، أو قيمة `min_context` التي ليست عددًا صحيحًا غير سالب (مثل `1.5`)، إلى إرجاع HTTP `400`، وتسرد الرسالة القيم الصالحة. التنفيذ: `src/app/api/v1/models/catalogFilters.ts`. ### القائمة المختصرة للنماذج (`POST /v1/models/query`) تعيد `POST /v1/models/query` قائمة قصيرة وحتمية من الكتالوج نفسه، مع المصادقة نفسها والرؤية الخاصة بكل مفتاح كما في `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 ] } ``` كل حقل اختياري. يقبل `capabilities` و`exclude` مصفوفة أو سلسلة مفصولة بفواصل؛ وتُقارن `max_output` مع `max_output_tokens`. تُرتّب النتائج حسب `owned_by`، ثم `id`. القيمة الافتراضية لـ`limit` هي `20`، وتُقيّد القيم التي تتجاوز `100` عند `100`. تؤدي بيانات JSON غير الصالحة، أو حقل غير معروف، أو قيمة غير صالحة إلى إرجاع HTTP `400`. ### نماذج المحادثة المخفية بشكل فردي يُستبعد من الكتالوج أي نموذج يحمل علامة **مخفي** في صفحة المزوّد الخاصة به، ويُرفض باستخدام HTTP `404` / `model_not_found` عند طلبه صراحةً. يستخدم الفحص المزوّد والنموذج اللذين جرى حلهما، بما في ذلك الأسماء المستعارة للمزوّدين، وبادئات عُقد المزوّد المتوافق، والقيم الافتراضية للاتصال. يتخطى التركيب الأهداف المخفية ويمكنه استخدام نموذج شقيق ظاهر؛ وعندما لا يتبقى أي هدف قابل للتنفيذ، فإنه يعيد رمز الخطأ نفسه. يسري إلغاء الإخفاء عند الطلب التالي. لا تؤدي تجاوزات الرؤية الخاصة بالصور فقط إلى إخفاء نموذج المحادثة الذي يحمل المعرّف نفسه. يُعد إعداد النموذج الفردي هذا منفصلًا عن [قوائم السماح/المنع لإظهار النماذج](../routing/MODEL_EXPOSURE_LIST.md)، التي ترشّح النماذج المعروضة في الكتالوج ومرشحي التوجيه التلقائي مع الإبقاء على الإرسال الصريح. تستمر أذونات النماذج الخاصة بمفتاح API في التطبيق بصورة مستقلة. يظل وضع بادئة الكتالوج الافتراضي `dual`. ### متغيرات النماذج من دون تفكير بالنسبة إلى نماذج Claude الداعمة للتفكير، تعرض `/v1/models` أيضًا متغيرًا **من دون تفكير** تكون بادئة معرّفه `claude-3-omniroute-no-thinking/`: ``` claude-3-omniroute-no-thinking// ``` يؤدي تحديد هذا المعرّف (على سبيل المثال، في إعداد Claude Code يُرفق دائمًا كتلة `thinking`) إلى الرجوع إلى `/` الحقيقي مع تعطيل الاستدلال — باستخدام `thinking:{type:"disabled"}` في مسار `/v1/messages`، أو حذف حقلي `reasoning` و`reasoning_effort` في مسار `/v1/chat/completions`. لا يُدرج هذا المتغير إلا لنماذج عائلة Claude التي تدعم التفكير **وتلتزم** بالقيمة `disabled` (لذلك تُستبعد، على سبيل المثال، النماذج التكيفية فقط التي ترفض `disabled`). يمكن للمشغّلين فرض تفعيل هذا المتغير أو تعطيله لكل نموذج عبر `ModelSpec.noThinkingAlias`. --- ## بيان إضافة المزوّد ```bash GET /api/v1/provider-plugin-manifest ``` يعيد بيان إضافة المزوّد الآمن للاستخدام بصيغة JSON، والذي تستخدمه Bifrost وCLIProxyAPI وأجهزة التوجيه الجانبية المستقبلية. تُنشأ الاستجابة من سجل مزوّدي TypeScript، وتستبعد عمدًا أسرار عملاء OAuth، وحلّ بيئة وقت التشغيل، ودوال التنفيذ، وترويسات الطلبات، وبيانات الحسابات. استخدم نقطة النهاية هذه عندما تعمل خدمة جانبية خارج العملية ولا يمكنها استيراد `open-sse/config/providerPluginManifestRegistry.ts` مباشرةً. --- ## نقاط نهاية التوافق | الطريقة | المسار | التنسيق | | ------- | ----------------------------------------- | ------------------------------------------------- | | POST | `/v1/chat/completions` | OpenAI | | POST | `/v1/messages` | Anthropic | | POST | `/v1/responses` | استجابات OpenAI | | POST | `/v1/embeddings` | OpenAI | | POST | `/v1/images/generations` | صور OpenAI | | POST | `/v1/images/edits` | صور OpenAI (تحرير/ترميم) | | POST | `/v1/videos/generations` | توليد فيديو بأسلوب OpenAI | | POST | `/v1/music/generations` | توليد موسيقى بأسلوب OpenAI | | POST | `/v1/audio/transcriptions` | صوت OpenAI (تحويل الكلام إلى نص) | | POST | `/v1/audio/speech` | تحويل النص إلى كلام من OpenAI (يعيد محتوى صوتيًا) | | POST | `/v1/rerank` | إعادة ترتيب بأسلوب Cohere/Voyage | | POST | `/v1/classify` | تصنيف Jina (`api.jina.ai`) | | POST | `/v1/segment` | مُجزّئ Jina (`segment.jina.ai`) | | POST | `/v1/moderations` | الإشراف من OpenAI | | GET | `/v1/models` | OpenAI | | POST | `/v1/models/query` | قائمة مختصرة ومُرشّحة من النماذج | | 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}/` | اسم مستعار لكتالوج OpenAI | | GET | `/api/v1/vscode/{token}/models` | اسم مستعار لنماذج OpenAI | | POST | `/api/v1/vscode/{token}/chat/completions` | اسم مستعار مرمّز برمز مميز لـ OpenAI | | POST | `/api/v1/vscode/{token}/responses` | اسم مستعار مرمّز برمز مميز لاستجابات OpenAI | | POST | `/api/v1/vscode/{token}/api/chat` | اسم مستعار مرمّز برمز مميز لـ Ollama | | GET | `/api/v1/vscode/{token}/api/tags` | اسم مستعار مرمّز برمز مميز لوسوم Ollama | تتبع جميع مسارات POST البنية نفسها: `Bearer your-api-key` + محتوى JSON تم التحقق منه بواسطة Zod (`v1RerankSchema` و`v1ModerationSchema` و`v1AudioSpeechSchema` وما إلى ذلك، راجع `src/shared/validation/schemas.ts`). تُعاد استجابة 4xx عند فشل التحقق من المخطط. بالنسبة إلى العملاء الذين لا يمكنهم إرفاق `Authorization: Bearer ...`، يقبل OmniRoute أيضًا مفاتيح API في عنوان URL، إما عبر توافق سلسلة الاستعلام (`?token=...` أو `?apiKey=...` أو `?api_key=...` أو `?key=...`) أو عبر نقاط النهاية المخصصة `/api/v1/vscode/{token}/...` الموثقة أدناه. ```bash # إعادة الترتيب (موفّر سجل سحابي، أو عقدة موفّر متوافقة مع OpenAI بصيغة "/") POST /v1/rerank { "model": "jina-ai/jina-reranker-v3.5", "query": "...", "documents": ["..."] } # تصنيف Jina (بيانات اعتماد Foundation API) POST /v1/classify { "model": "jina-embeddings-v5-text-small", "input": ["..."], "labels": ["a", "b"] } # مُجزّئ Jina POST /v1/segment { "content": "...", "return_chunks": true } # بحث Jina ‏(s.jina.ai؛ الأسماء المستعارة للموفّر: jina-search وjina-ai وjina) POST /v1/search { "query": "...", "provider": "jina-search" } # الإشراف POST /v1/moderations { "model": "omni-moderation-latest", "input": "..." } # تحويل النص إلى كلام — يعيد محتوى audio/mpeg (أو بالتنسيق المطلوب) POST /v1/audio/speech { "model": "openai/tts-1", "input": "Hello", "voice": "alloy" } # يتطلب تحويل النص إلى كلام من Soniox لغةً وصوتًا: القيمة الافتراضية لـ `language` هي "en"؛ ويصبح الصوت # المفقود أو اسم صوت افتراضي من OpenAI ‏(alloy وnova و…) هو "Adrian" POST /v1/audio/speech { "model": "soniox/tts-rt-v1", "input": "Xin chào", "voice": "Adrian", "language": "vi" } # تحرير الصورة (متعدد الأجزاء) POST /v1/images/edits -F image=@input.png -F prompt="..." -F mask=@mask.png # توليد الفيديو / الموسيقى (معرّف نموذج مسبوق باسم الموفّر) POST /v1/videos/generations { "model": "runway/gen-3", "prompt": "..." } POST /v1/music/generations { "model": "kie/suno-v4.0", "prompt": "..." } ``` > **عُقد مزوّدي إعادة الترتيب:** يُوجَّه `POST /v1/rerank` أيضًا إلى عُقد مزوّدين متوافقة مع OpenAI > ‏(oMLX وvLLM وInfinity وTEI خلف بوابة، …) يُشار إليها بالصيغة `/`. تكون عُقد > الاسترجاع المحلي (`localhost` و`127.0.0.1` و`172.16.0.0/12`) مؤهلة دائمًا، وكذلك أسماء المضيفين التي > يدرجها المشغّل في `OMNIROUTE_LOCAL_PROVIDER_NODE_HOSTS` (مثل اسم خدمة Docker/Compose > كـ `http://reranker:8080/v1`؛ إذ تُستدعى هذه مباشرةً، ولا تمر مطلقًا عبر `HTTP(S)_PROXY` أو > الوكيل المثبّت للاتصال). لا تكون العُقد الموجودة على أي مضيف آخر > — كجهاز على شبكة LAN أو نظير Tailscale — مؤهلة إلا عندما يفعّل المشغّل علامة الميزة > `RERANK_REMOTE_PROVIDER_NODES` **و** يجتاز عنوان URL الأساسي للعقدة سياسة عناوين URL الصادرة الخاصة بالمزوّد > (`OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS` / `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS`). > تستدعي خطوة إعادة الترتيب في محرك الذاكرة هذا المسار عبر > الاسترجاع المحلي، لذا تحكم القاعدة نفسها `rerankProviderModel` في إعدادات الذاكرة. > > **أشكال الخادم المحلي:** تُستدعى العقدة عند `/v1/rerank`، وعند تلقي 404، عند `/rerank` > ‏(Infinity وTEI). يحمل نص الطلب المرسل إلى المنبع كلاً من تسمية Cohere/OpenAI (`documents`، > `return_documents`) وتسمية TEI (`texts` و`return_text`)، وتُطبَّع استجابة المنبع إلى غلاف Cohere: > إذ تعود مصفوفة TEI المجرّدة `[{index, score, text}]`، و`{results: [{index, score}]}` > من البوابات الخفيفة، و`{data: [...]}` بأسلوب Voyage جميعها إلى العميل بالصيغة > `{results: [{index, relevance_score, document?}]}`، مرتبة حسب الدرجة ومحدودة بالقيمة `top_n`. > **اكتشاف عُقد المزوّد:** تظهر النماذج الموجودة على عقدة مزوّد متوافقة مع OpenAI في `GET /v1/models` > تحت بادئة العقدة. ترث الصفوف التي لا تحتوي على بيانات وصفية لنقاط النهاية (وهو أمر شائع في قوائم `/v1/models` المحلية) > قيمة `apiType` الخاصة بالعقدة، لذا تكون نماذج عقدة `embeddings` من النوع `type: "embedding"` وتكون > نماذج عقدة `rerank` من النوع `type: "rerank"` بدلًا من تعيين الدردشة افتراضيًا؛ ومع ذلك تظل قيمة > `supportedEndpoints` الصريحة في صف متزامن أو مضاف يدويًا ذات أولوية. ### مسارات المزوّد المخصصة ```bash POST /v1/providers/{provider}/chat/completions POST /v1/providers/{provider}/embeddings POST /v1/providers/{provider}/images/generations ``` تُضاف بادئة المزوّد تلقائيًا إذا كانت مفقودة. تُرجع النماذج غير المتطابقة `400`. --- ## واجهة برمجة تطبيقات الملفات نقطة نهاية متوافقة مع OpenAI للملفات، مخصّصة للإدخال/الإخراج على دفعات ولتحميل الملفات وفق الغرض. | الطريقة | المسار | الوصف | | ------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------ | | POST | `/v1/files` | تحميل ملف (متعدد الأجزاء: `file`، `purpose`، `expires_after[anchor]`، `expires_after[seconds]`) — بحد أقصى 512 MiB | | GET | `/v1/files` | سرد الملفات الخاصة بمفتاح API المُصادَق عليه | | GET | `/v1/files/[id]` | استرداد البيانات الوصفية لملف | | DELETE | `/v1/files/[id]` | حذف ملف | | GET | `/v1/files/[id]/content` | إعادة بث المحتوى الأولي للملف | **المصادقة:** مفتاح API من نوع Bearer — تُحدَّد نطاقات الملفات لكل مفتاح API عبر `getApiKeyRequestScope`. لا يمكن للمفتاح رؤية ملفاته وتنزيلها وحذفها إلا؛ بينما يمكن لجلسة لوحة المعلومات من دون مفتاح قراءة المثيل بأكمله؛ ويُحظر على كل مستدعٍ لا يستخدم جلسة الوصول إلى ملف بلا مالك (تحميل مجهول أو عبر جلسة لوحة المعلومات). يرفض `GET /v1/files` المستدعي المجهول — وكذلك المفتاح المقدَّم الذي يتعذر التحقق منه — باستخدام `401` حتى عندما تكون `REQUIRE_API_KEY=false`، بدلًا من سرد ملفات جميع المستأجرين (GHSA-m3hp-hq9g-fpmv، GHSA-2jm2-mpx8-6523). --- ## واجهة برمجة تطبيقات الدفعات معالجة دفعية متوافقة مع OpenAI. | الطريقة | المسار | الوصف | | ------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | POST | `/v1/batches` | إنشاء دفعة — يتم التحقق من صحة النص الأساسي بواسطة `v1BatchCreateSchema` (`input_file_id`، `endpoint`، `completion_window`) | | GET | `/v1/batches` | سرد الدفعات | | GET | `/v1/batches/[id]` | استرداد حالة الدفعة + `request_counts` | | DELETE | `/v1/batches/[id]` | حذف دفعة مكتملة/فاشلة | | POST | `/v1/batches/[id]/cancel` | إلغاء دفعة قيد التنفيذ | **المصادقة:** مفتاح API من نوع Bearer. تُحدَّد نطاقات الدفعات لكل مفتاح API وفق القاعدة الثلاثية نفسها المطبقة على الملفات: مفتاحه الخاص فقط، وجلسة لوحة المعلومات على مستوى المثيل بالكامل، وتُحظر السجلات ذات المالك الفارغ على كل مستدعٍ لا يستخدم جلسة (الاسترداد والحذف والإلغاء، وكذلك التحقق من `input_file_id` عند الإنشاء). يرفض `GET /v1/batches` المستدعي المجهول باستخدام `401` حتى عندما تكون `REQUIRE_API_KEY=false`. --- ## واجهة برمجة تطبيقات البحث طبقة تجريد لموفّري بحث الويب (Tavily، وBrave، وExa، وSerper، وغيرها). | الطريقة | المسار | الوصف | | ------- | ---------------------- | -------------------------------------------------------------------------------------------- | | GET | `/v1/search` | سرد موفّري البحث المُهيّئين + إمكاناتهم | | POST | `/v1/search` | تنفيذ استعلام بحث — يُتحقق من صحة المتن بواسطة `v1SearchSchema`، مع دعم التخزين المؤقت/الدمج | | GET | `/v1/search/analytics` | إحصاءات النتائج/زمن الاستجابة/التخزين المؤقت لكل موفّر | **المصادقة:** مفتاح API من نوع Bearer ‏(`extractApiKey` + `isValidApiKey`). تُطبَّق سياسة البحث عبر `enforceApiKeyPolicy`. ### `provider_options` في Exa وTavily يقرأ Exa وTavily الحقول الخاصة بالموفّر من حاوية ذات نطاق اسمي: `provider_options.exa` (أو `provider_options["exa-search"]`) و`provider_options.tavily` (أو `provider_options["tavily-search"]`). لا تُمرَّر إلا المفاتيح أدناه. ويُتحقق من كل واحد منها باستخدام مخطط Zod الخاص به في `open-sse/handlers/search/providerOptionsPassthrough.ts`، ويُستبعد أي مفتاح من نوع غير صحيح. ويُتجاهل أي مفتاح آخر، بما في ذلك المصادقة وعنوان URL الأساسي و`stream` و`outputSchema`. وتستمر المفاتيح المسطحة التي تستخدمها الموفّرات الأخرى (`cx`، و`depth`، ...) في العمل كما كانت من قبل. | الموفّر | حقول المستوى الأعلى | المتداخلة | | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Exa | `type`، `category`، `userLocation`، `moderation`، `additionalQueries`، `objective`، `systemPrompt`، `compliance` (قيم أولية مسطحة)، `startPublishedDate`، `endPublishedDate` | تُدمج `contents.{text, highlights, summary, extras, subpages, subpageTarget, livecrawlTimeout, maxAgeHours}` فوق القيمة الافتراضية `{ text: true, highlights: true }` | | 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` | — | تحظى الحقول العامة دائمًا بالأولوية: `query`، و`max_results`، و`filters` (النطاقات)، و`country`، والموضوع المشتق من `search_type`. في Exa، يُبقي `search_type: "news"` على `category: "news"`. كما يقبل Tavily القيمة `search_type: "finance"` ‏(`topic: "finance"`). يصل الحقل العام `time_range` الآن إلى كلا الموفّرين: يتلقى Exa الحقل `startPublishedDate` (طابعًا زمنيًا بتنسيق ISO)، ويتلقى Tavily الحقل `start_date` ‏(`YYYY-MM-DD`). ويتجاوز التاريخ المحدد صراحةً في `provider_options` التاريخ المعيّن تلقائيًا. تحتفظ نتائج Exa بالحقول `id`، و`highlight_scores`، و`summary`، و`subpages`، و`entities`، و`extras` داخل `provider_raw`. وتحتفظ نتائج Tavily بالحقلين `images` و`favicon`. لا تزال محاسبة التكلفة تستخدم السجل المسطح `costPerQuery`. يفرض Tavily تكلفة اعتمادات أكبر لكل استدعاء عند استخدام `search_depth: "advanced"`، ولا ينعكس هذا الفرق في `usage.search_cost_usd`. --- ## واجهة Web Fetch API استخرج المحتوى من عنوان URL عبر موفّر جلب ويب مُهيّأ (Firecrawl أو Jina Reader أو Tavily Extract أو TinyFish Fetch أو Nimble Extract أو Parallel Extract). يُرجع Parallel Extract (`parallel-search`، باستخدام مفتاح API نفسه الخاص بـ Parallel Search) محتوى Markdown فقط — وأي قيمة أخرى لـ `format` تؤدي إلى `400` — كما يحدّ المحتوى بـ 100,000 حرف. عندما يتعذّر استخراج الصفحة المستهدفة نفسها، تُبلغ الخدمة المصدرية عن ذلك ضمن استجابة HTTP 200؛ ويعرض OmniRoute ذلك كخطأ `422` برسالة ثابتة. | الطريقة | المسار | الوصف | | ------- | --------------- | -------------------------------------------------------------------------- | | POST | `/v1/web/fetch` | جلب/استخلاص عنوان URL — يجري التحقق من جسم الطلب بواسطة `v1WebFetchSchema` | **المصادقة:** مفتاح API من نوع Bearer ‏(`extractApiKey` + `isValidApiKey`). تُطبَّق السياسة عبر `enforceApiKeyPolicy`. **الرجوع الاحتياطي المراعي للحصة (#8297):** عند عدم تحديد `provider` صراحةً، يجري المرور على المجموعة (`firecrawl` → `jina-reader` → `tavily-search` → `tinyfish` → `nimble-search` → `parallel-search`) بترتيب أولوية ثابت (الملء أولًا) — يُتخطّى الموفّر المُهيّأ الذي يخضع لتحديد المعدل بدلًا من إنهاء الطلب فورًا، كما يؤدي فشل الخدمة المصدرية القابل لإعادة المحاولة/المرتبط بالحصة (HTTP 429 دائمًا؛ و402/403 للحصص من نمط الطبقات المجانية في Firecrawl/Tavily/TinyFish — وليس في Jina Reader، ولا ينطبق مطلقًا على طلب غير صالح عادي بحالة 400) إلى الانتقال إلى الموفّر التالي المزوّد ببيانات اعتماد والذي لم تتم تجربته بعد في وقت الطلب. عند استنفاد جميع الموفّرين في المجموعة، تُرجع نقطة النهاية استجابة `429` واحدة (مع ترويسة `Retry-After`) بدلًا من استجابة `400` العامة السابقة. عند طلب `provider` صراحةً، **لا** يحدث رجوع احتياطي ضمني — إذ يعرض الموفّر المحدد صراحةً والمقيّد بالمعدل أو المتعطّل خطأه الخاص (`429` إذا كان مقيّدًا بالمعدل، وإلا فحالة الخدمة المصدرية). --- ## البث عبر WebSocket ```bash GET /v1/ws?handshake=1 ``` يتحقق من صحة مصافحة ترقية WebSocket ويُرجع أمثلة رسائل بروتوكول النقل (`request` و`cancel`). يتولى خادم WS المضمّن معالجة إطارات WS الفعلية خارج جدول مسارات Next.js. **المصادقة:** مفتاح API بنمط Bearer أثناء المصافحة. ### واجهة Responses API عبر WebSocket (لـ codex فقط) ```bash # المضيف:المنفذ نفسه لواجهة HTTP API (الافتراضي 20128)؛ رقِّ الاتصال: wscat -c "ws://localhost:20128/v1/responses?api_key=" # (أو: -H "Authorization: Bearer ") # يجب أن يكون الإطار الأول response.create: { "type": "response.create", "model": "gpt-5.5", "input": [ { "role": "user", "content": "hi" } ] } ``` يُوصَّل وكيل Responses-API-over-WebSocket **حصريًا بـ `codex`** (الواجهة الخلفية لـ ChatGPT). ويستمع على المنفذ نفسه الذي تستخدمه واجهة API/لوحة المعلومات عند المسارات `/v1/responses` و`/responses` و`/api/v1/responses`. عند أول إطار `response.create`، ينفّذ المصادقة والتحضير عبر جسر `codex-responses-ws` الداخلي، ويختار اتصال codex OAuth، ثم ينشئ نفقًا إلى `wss://chatgpt.com/backend-api/codex/responses` عبر ناقل `wreq-js`. **تُرفض النماذج غير التابعة لـ codex** (`codex_ws_provider_required`). لاستخدام التوجيه بمشاركة الحصة، استخدم `model: "qtSd//codex/"`. جرى التنفيذ في `app/server-ws.mjs` + `scripts/dev/responses-ws-proxy.mjs` + `src/app/api/internal/codex-responses-ws/route.ts`. **المصادقة:** مفتاح API بنمط Bearer أثناء المصافحة. يجب أن يكون خادم HTTP المضمّن (`server-ws.mjs`) هو نقطة الدخول النشطة (وهو كذلك افتراضيًا عند وجود `app/server-ws.mjs`). #### معرّف النموذج: استخدم معرّف ChatGPT المجرّد (من دون البادئة `codex/`) تتحقق **Codex CLI** الخاصة بـ OpenAI من اسم النموذج من جانب العميل عندما تكون `supports_websockets = true`، كما **ترفض المعرّفات المسبوقة باسم الموفّر** مثل `codex/gpt-5.5` (`The 'codex/gpt-5.5' model is not supported when using Codex with a ChatGPT account`). أرسل المعرّف **المجرّد** (مثل `gpt-5.5`). جسر OmniRoute مخصص لـ codex فقط، لذا يعيد تحليل المعرّف المجرّد باعتباره نموذج codex (`resolveCodexWsModelInfo`) قبل إنشاء النفق إلى الجهة المصدرية — رغم أن `gpt-5.5` المجرّد كان سيُوجَّه بخلاف ذلك إلى موفّر آخر عبر HTTP. #### تهيئة OpenAI Codex CLI وجّه Codex CLI إلى OmniRoute بإضافة موفّر مخصص يدعم WebSocket إلى `~/.codex/config.toml` (استخدم `CODEX_HOME` منفصلًا لتجنب تعديل تهيئة موجودة): ```toml model = "gpt-5.5" # معرّف مجرّد — وليس "codex/gpt-5.5" model_provider = "omniroute" [model_providers.omniroute] name = "OmniRoute (WS)" base_url = "http://localhost:20128/v1" # بلا شرطة مائلة لاحقة؛ يُشتق عنوان WS (استخدم https/wss في الإنتاج) wire_api = "responses" # القيمة الوحيدة المدعومة منذ فبراير 2026 supports_websockets = true # يفعّل ناقل Responses-over-WS env_key = "OMNIROUTE_API_KEY" # يحتوي على مفتاح OmniRoute API ‏(Bearer) ``` ```bash export OMNIROUTE_API_KEY=sk-... # مفتاح OmniRoute API (أي مفتاح إذا كانت REQUIRE_API_KEY=false) codex exec "Responda apenas: PONG" ``` ترقّي CLI العنوان `base_url + /responses` إلى WebSocket، وتنشئ OmniRoute نفقًا له إلى اتصال codex OAuth المحدد. جرى التحقق من طرف إلى طرف مقابل الخادم المحلي: يُرجع ChatGPT ‏`codex.rate_limits` + `response.created` ويبث الإكمال. --- ## الحصص والإبلاغ عن المشكلات | الطريقة | المسار | الوصف | | ------- | ------------------- | -------------------------------------------------------------------------------------------- | | GET | `/v1/quotas/check` | التحقق مسبقًا من حصة `provider` + `accountId` قبل إصدار مفتاح مسجّل | | POST | `/v1/issues/report` | الإبلاغ عن فشل في الحصة/إصدار المفتاح إلى GitHub (يتطلب `GITHUB_ISSUES_REPO` + رمزًا مميزًا) | **المصادقة:** مفتاح API من نوع Bearer ‏(`isAuthenticated`). --- ## استخدام الخدمة الذاتية (`/api/usage/om-usage`) يمكن لأي مفتاح API قراءة استخدامه وحصصه **الخاصة به** — من دون مصادقة إدارية. هذه هي نقطة النهاية التي يستخدمها العميل (CLI، لوحة OmniCopilot) لعرض إنفاق صاحب المفتاح. ```bash # الصيغة النصية (العقد التاريخي — نص عادي للطرفية) curl -H "Authorization: Bearer " \ http://localhost:20128/api/usage/om-usage # الصيغة المنظّمة — ما تستهلكه واجهة المستخدم curl -H "Authorization: Bearer " \ "http://localhost:20128/api/usage/om-usage?format=json" ``` يجب أن يكون الخيار **`allowUsageCommand`** مفعّلًا للمفتاح (وهو معطّل افتراضيًا — يبدّله مدير مفاتيح API في لوحة المعلومات لكل مفتاح على حدة). من دونه، تستجيب نقطة النهاية بالحالة `403`. يعيد `?format=json` بنيةً مميّزة بحيث لا يقرأ المستدعي مطلقًا حقل بيانات من استجابة رفض. عند النجاح: ```jsonc { "allowed": true, // لا يظهر إلا عندما يختار المفتاح استخدام حدود استخدام خاصة به (يومية/أسبوعية بالدولار الأمريكي): "personal": { "dailySpentUsd": 1.25, "dailyLimitUsd": 5, "dailyResetAtIso": "…", "weeklySpentUsd": 8, "weeklyLimitUsd": 20, "weeklyResetAtIso": "…" /* … */, }, // لقطة حصة المزوّد المحدد، أو null عندما لا يكون قد تم تخزين أي شيء مؤقتًا بعد: "provider": { "connectionId": "…", "provider": "claude", "plan": "…", "quotas": {/* … */}, }, // لقطة كل اتصال، كي تتمكن واجهة المستخدم من عرض عدة مزوّدين جنبًا إلى جنب: "providers": [ { "connectionId": "…", "provider": "claude" /* … */ }, { "provider": "codex" /* … */ }, ], } ``` عند الرفض (`401` لمفتاح غير صالح / `403` لعدم السماح)، يعيد المسار نفسه `{ "allowed": false, "error": { "message": "…" } }` — وتختلف حالة وجود `personal`/`provider` مع كونهما فارغين (المفتاح مسموح، ولكن لم تُجمع أي معلومات بعد) عن حالة الرفض، ولا تميّز بينهما سوى صيغة JSON. **المصادقة:** مفتاح Bearer API الخاص بالمستدعي، والذي يتم التحقق منه باستخدام `isValidApiKey` — وهذه _ليست_ واجهة الإدارة (`/api/keys/…`)، التي تظل محمية بواسطة `requireManagementAuth`. ### النسب المئوية الخام مقابل النسب المعدّلة وفق حد الإيقاف عند استهلاك `/api/usage/om-usage`، ينبغي للمستدعين ملاحظة الفرق بين النسب المئوية المعروضة في **المخرجات النصية العادية** وتلك الموجودة في **مخرجات JSON** المنظّمة: | الجانب | تنسيق النص العادي (`/api/usage/om-usage` / `@@om-usage`) | تنسيق JSON (`?format=json`) | | :------------------- | :------------------------------------------------------------------------------------- | :------------------------------------------------------------------------ | | **حقل الإخراج** | `NN% left` (مثلًا، `20% left`) | `provider.quotas` / `providers[].quotas` | | **القياس** | **السماح القابل للاستخدام المعدّل وفق حد الإيقاف**: السعة المتبقية فوق عتبة الإيقاف | **حصة المزوّد الخام**: قياس المزوّد غير المعدّل | | **تحجيم حد الإيقاف** | يُحجَّم عبر `effectiveRemainingPercent()` بحيث يظهر الاحتياطي المحمي على أنه `0% left` | لا يوجد (قيم اللقطة الخام كما أبلغ عنها المزوّد) | | **بيانات العتبة** | مضمّنة في النسبة المئوية المعروضة | مخزنة في `quotaWindowThresholds` لكل اتصال (أو إعدادات الخادم الافتراضية) | | **المستهلك الأساسي** | واجهات CLI التفاعلية، وموجّهات الطرفية، والمشغّلون البشريون | عمليات التكامل البرمجية، ولوحات المعلومات، والتحليلات، ومتتبّعات الفوترة | #### صيغة التعديل وفق حد الإيقاف يدعم OmniRoute حدود إيقاف استباقية للحصص لمنع استنفاد موارد المزوّد (والتي تُضبط عبر `quotaWindowThresholds` للاتصال، أو إعدادات المزوّد الافتراضية، أو إعدادات المرونة العامة). عندما تكون عتبة إيقاف (مثلًا، `cutoff = 25%`) نشطة ضمن نافذة حصة، يحسب عارض النص السماح المتبقي كما يلي: - إذا كان `remaining <= cutoff`: يُرجع `0%`. - إذا كان `remaining > cutoff`: يُرجع `((remaining - cutoff) / (100 - cutoff)) * 100`. تقرّب المخرجات النصية المنسّقة هذه القيمة إلى أقرب عدد صحيح (`Math.round(...)`). #### مثال توضيحي لنفترض وجود نافذة مزوّد بها **استخدام خام بنسبة 60%** (ومن ثم **حصة خام متبقية بنسبة 40%**) مع عتبة **إيقاف عند بقاء 25% من الحصة**: | التمثيل | العملية الحسابية | المتبقي | الاستخدام الضمني | | :------------------------------ | :------------------------------------------------- | :-----: | :---------------------------------------------: | | **JSON الخام (`?format=json`)** | لقطة المزوّد (`quotas[window]`) | **40%** | **60%** | | **التنسيق النصي (`NN% left`)** | `((40 - 25) / (100 - 25)) * 100 = (15 / 75) * 100` | **20%** | **80%** (عند الحساب باستخدام `100 - remaining`) | - **سبب عرض النص لتبقّي 20%:** من أصل 40% من الحصة الفعلية المتبقية في الحساب، تحتفظ سياسة الإيقاف بنسبة 25%. لا يتبقى للمستدعي سوى 15% من أصل هامش قابل للاستخدام مقداره 75% قبل أن يتوقف الموجّه عن توجيه الطلبات إلى هذا الاتصال. يضمن التحجيم أن يشير الاتصال إلى الاستنفاد (`0% left`) في اللحظة نفسها التي سيتوقف فيها التوجيه. - **سبب احتفاظ JSON بالقيم الخام:** تعيد حمولة JSON لقطة المزوّد الدقيقة (`UsageSnapshot`) لكي تتمكن الأدوات الخارجية من الوصول إلى بيانات الاستخدام الفعلية لدى المزوّد وإعدادات `quotaWindowThresholds` على مستوى الاتصال، من دون تحجيم فاقد للمعلومات من جانب الخادم. #### إرشادات ترحيل المستهلكين إذا كان تكامل خارجي (مثل إضافة محرر أو امتداد وكيل) يستخرج سابقًا بيانات نقطة النهاية النصية (`NN% left`) ويحسب نسبة الاستخدام باستخدام `100 - NN`، فإن الترحيل إلى `?format=json` يعني: - ستعكس قراءة قيم JSON الخام **الاستهلاك الفعلي لدى المزوّد** (استخدام بنسبة 60% في المثال أعلاه). - إذا أراد التكامل الحفاظ على دلالة السماح القابل للاستخدام الخاصة بنقطة النهاية النصية، فيمكنه حساب صيغة المتبقي الفعلي من جانب العميل باستخدام `quotaWindowThresholds` للتجاوزات الخاصة بكل اتصال. --- ## ذاكرة التخزين المؤقت الدلالية ```bash # الحصول على إحصاءات ذاكرة التخزين المؤقت GET /api/cache/stats # مسح جميع ذاكرات التخزين المؤقت DELETE /api/cache/stats ``` مثال على الاستجابة: ```json { "semanticCache": { "memorySize": 42, "memoryMaxSize": 500, "dbSize": 128, "hitRate": 0.65 }, "idempotency": { "activeKeys": 3, "windowMs": 5000 } } ``` ### التأثير في زمن الاستجابة يقدّم تطابق ذاكرة التخزين المؤقت الدلالية الاستجابة من الذاكرة المؤقتة **من دون إجراء استدعاء إلى المصدر العلوي**، ولذلك تكون قيمة `X-OmniRoute-Response-Latency` المُبلّغ عنها قريبة من الصفر (بغض النظر عن زمن استجابة المصدر العلوي الأصلي). يجب على العملاء الحساسين لزمن الاستجابة (الاختبارات المعيارية، ومراقبة p50/p99) التحقق من ترويسة الاستجابة `X-OmniRoute-Cache-Latency`: | القيمة | المعنى | | ----------- | ---------------------------------------------------------------------------------------- | | `synthetic` | قُدّمت الاستجابة من ذاكرة التخزين المؤقت؛ وزمن الاستجابة ليس زمنًا حقيقيًا للمصدر العلوي | | _(غائبة)_ | الاستجابة واردة من استدعاء حقيقي إلى المصدر العلوي | ### تجاوز ذاكرة التخزين المؤقت لكل مفتاح يمكن لمفاتيح API إلغاء الاشتراك في عمليات القراءة من ذاكرة التخزين المؤقت الدلالية عبر `cacheDefaultMode`: | القيمة | السلوك | | -------- | -------------------------------------------------------------------------- | | `legacy` | سلوك ذاكرة التخزين المؤقت العادي (الافتراضي) | | `bypass` | تخطي البحث في ذاكرة التخزين المؤقت بالكامل؛ والاتصال دائمًا بالمصدر العلوي | يُضبط عند إنشاء المفتاح (`POST /api/keys`) أو تحديثه (`PATCH /api/keys/[id]`): ```json { "cacheDefaultMode": "bypass" } ``` ### التجاوز لكل طلب يمكن لأي طلب تجاوز ذاكرة التخزين المؤقت بغض النظر عن إعدادات المفتاح: ``` X-OmniRoute-No-Cache: true ``` --- ## لوحة التحكم والإدارة مسارات الإدارة (`/api/*` باستثناء auth/login العام) **لا** يتم تخويلها بواسطة مفاتيح API العادية للاستدلال. عائلات بيانات الاعتماد والنطاقات وأمثلة curl: [مصادقة الإدارة](../guides/MANAGEMENT-AUTH.md). ### المصادقة | Endpoint | Method | Description | | ----------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/auth/login` | POST | تسجيل الدخول | | `/api/auth/logout` | POST | تسجيل الخروج | | `/api/settings/require-login` | GET/POST | حالة تسجيل الدخول (GET، عام). يعيّن POST كلمة المرور / يبدّل تسجيل الدخول: للمشغّل فقط بمجرد وجود كلمة مرور (جلسة لوحة التحكم، أو CLI المحلي، أو تسجيل الدخول معطّل — مفاتيح API ورموز `oma_` تحصل على `403`)؛ ترسل جلسة لوحة التحكم `currentPassword` لاستبدال كلمة المرور | ### إدارة المزوّدات | Endpoint | Method | Description | | --------------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `/api/providers` | GET/POST | عرض / إنشاء المزوّدات | | `/api/providers/[id]` | GET/PUT/DELETE | إدارة مزوّد | | `/api/providers/[id]/test` | POST | اختبار اتصال المزوّد | | `/api/providers/[id]/models` | GET | عرض نماذج المزوّد | | `/api/providers/validate` | POST | التحقق من إعدادات المزوّد | | `/api/providers/bulk` | POST | إضافة مجمّعة لمفاتيح API لمزوّد واحد | | `/api/providers/import` | POST | استيراد قائمة مزوّدات غير متجانسة من ملف CSV/JSON مُحلَّل (#6836)؛ نتائج فشل جزئي لكل صف | | `/api/provider-nodes*` | Various | إدارة عُقد المزوّد | | `/api/provider-models` | GET/POST/PUT/PATCH/DELETE | نماذج مخصصة وتجاوزات لكل نموذج (إضافة، تحديث، إخفاء/إظهار، حذف) | | `/api/provider-models/validate-and-add` | POST | تحقق صارم اختياري من الاتصال بمصادقة الإدارة وتسجيل ذرّي للنموذج المخصص؛ راجع [التحقق من النموذج](../guides/MODEL-VALIDATION.md) | بالنسبة للنماذج المتزامنة/المستوردة، يقبل `PUT /api/provider-models` المعطيات `provider` و`modelId` و `maxOutputTokenOverride`: يعيّن العدد الصحيح الموجب الحد الأقصى اليدوي لرموز الإخراج، ويمسحه `null` لاستعادة الوضع الافتراضي. يعيد `GET /api/provider-models?provider=` هذه القيم في `modelOutputOverrides`، بما في ذلك النماذج التي لا تحتوي على صف نموذج مخصص. يستخدم التجاوز قدرة `max_output_tokens` في وقت التشغيل ويصمد أمام إعادة مزامنة النموذج. تقدّم صفحة المزوّد المتوافق مع OpenAI عناصر التحكم نفسها للتعديل/المسح وتضع علامة على النماذج ذات دعم الرؤية الصريح. تكيّف عُقد Chat Completions المخصصة عمليات الإلغاء الصريح لميزة التفكير مع الواجهة الخلفية للمصدر. يختار اختبار الاتصال الناجح تلقائيًا عناصر تحكم قالب المحادثة لكل معرّف نموذج مطابق تمامًا يثبت إدخال `/models` الخاص به قيمة `owned_by` معروفة: `vllm` أو `sglang` أو `llamacpp`. قد تحتفظ الأغلفة الشفافة المتوافقة مع OpenAI بإدخال النموذج الأصلي داخل كائن `openai` متداخل؛ يتتبّع الكشف ما يصل إلى ثلاثة من هذه الأغلفة. تحتفظ النماذج ذات الملكية المفقودة أو غير المعروفة أو المتضاربة بسلوك OpenAI العادي. يعيد الكشف استخدام طلب الكتالوج الحالي، ولا يولّد أي رموز إكمال، ويُبطل عند تغيير نقطة نهاية الاتصال. لتثبيت السلوك لواجهة خلفية لا تعرض تلك البيانات الوصفية، استخدم واجهة API الحالية للتحديث الجزئي للمزوّد: ```json { "providerSpecificData": { "reasoningControl": "chat-template" } } ``` أرسل هذا الجسم مع `PUT /api/providers/`. في هذا الاتصال، يُرسَل جهد استدلال صريح بقيمة `none` على شكل `chat_template_kwargs.thinking=false` و`chat_template_kwargs.enable_thinking=false`. تظل قيم القالب الأصلية الصريحة هي المرجعية ما لم تفرض قاعدة استدلال من جهة الخادم جهدًا معينًا. لا ينطبق هذا الإعداد إلا عندما يرسل اتصال مخصص متوافق مع OpenAI جسم طلب Chat Completions؛ أما طلبات Responses والموفّرون العاديون فيحتفظون بشكل طلباتهم الأصلي. اضبط `reasoningControl` على `openai` لفرض تمرير `reasoning_effort` المعتاد من OpenAI، أو احذفه/اضبطه على `null` لاستخدام الاكتشاف التلقائي. تُعطِّل طلبات مصنِّف الوضع التلقائي في Claude Code التفكير الأصلي افتراضيًا عندما لا تحتوي على أي عناصر تحكم صريحة في الاستدلال. يعتمد الاكتشاف على علامة النظام الخاصة بالمصنِّف في الطلبات بتنسيق Claude، وليس على أسماء النماذج أو حدود الإكمال. تحتفظ عناصر التحكم الصريحة في الجسم، وترويسات effort/thinking المدعومة، وقواعد التوجيه، وجهد النموذج المحدَّد بأولويتها القائمة. تحتفظ كلتا مرحلتي المصنِّف بموجّهاتها وحدود الإكمال وتسلسلات الإيقاف وأحكام الأذونات الفعلية من المصدر؛ ولا تزال المرحلة الثانية قادرة على إنتاج الاستدلال المرئي المطلوب كنص عادي. ### تدفقات OAuth | نقطة النهاية | الطريقة | الوصف | | -------------------------------- | ------- | --------------------- | | `/api/oauth/[provider]/[action]` | متنوعة | OAuth الخاص بكل موفّر | ### التوجيه والإعدادات | نقطة النهاية | الطريقة | الوصف | | --------------------- | -------- | ------------------------------- | | `/api/models/alias` | GET/POST | الأسماء المستعارة للنماذج | | `/api/models/catalog` | GET | جميع النماذج حسب الموفّر والنوع | | `/api/combos*` | متنوعة | إدارة المجموعات (Combos) | | `/api/keys*` | متنوعة | إدارة مفاتيح API | | `/api/pricing` | GET | أسعار النماذج | ### الاستخدام والتحليلات | نقطة النهاية | الطريقة | الوصف | | -------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/usage/history` | GET | سجل الاستخدام | | `/api/usage/logs` | GET | سجلات الاستخدام | | `/api/usage/request-logs` | GET | سجلات على مستوى الطلب | | `/api/usage/[connectionId]` | GET | الاستخدام لكل اتصال | | `/api/usage/token-limits` | GET/POST/DELETE | ميزانيات حدود الرموز لكل مفتاح API | | `/api/usage/model-latency-stats` | GET | تجميع متحرك لزمن الاستجابة لكل موفّر/نموذج (المتوسط/p50/p95/p99، ومعدل النجاح)؛ عوامل التصفية: `windowHours`/`minSamples`/`maxRows`/`provider`/`model` (#6873) | | `/api/usage/cache-health` | GET | ملخص لصحة ذاكرة التخزين المؤقت للموجّهات عبر `call_logs` — نسبة الكتابة/القراءة، وتوزيع p50/p90/p99 لأحجام الكتابة، وتركّز عمليات الكتابة الكثيفة، والتقسيم حسب النموذج، وحكم نهائي بقيمة `healthy`/`degraded`/`thrash`/`no-data`؛ معاملات الاستعلام `range` (`1h`\|`24h`\|`7d`\|`30d`، الافتراضي `24h`) و`model` الاختياري (#8827) | ### أذونات مفاتيح API يحدِّث `PATCH /api/keys/{id}` أذونات مفتاح موجود. ومثل جميع مسارات `/api/keys*`، يتطلب تفويض إدارة (راجع [مصادقة الإدارة](../guides/MANAGEMENT-AUTH.md))، وليس مفتاح استدلال. أرسل فقط الحقول التي تريد تغييرها؛ فالطلب الذي لا يتضمن أيًا منها يُرفَض مع الرسالة `No valid fields to update`. الحقول المقبولة محددة في `updateKeyPermissionsSchema` ضمن `src/shared/validation/schemas/keys.ts`. | الحقل | النوع | ملاحظات | | ------------------------------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | `name` | سلسلة نصية، 1-200 حرف | | | `isActive` | قيمة منطقية | | | `isBanned` | قيمة منطقية | | | `expiresAt` | تاريخ ووقت بصيغة ISO 8601 أو `null` | القيمة `null` تمحو تاريخ الانتهاء | | `modelAccessMode` | `all` \| `restricted` | يجب أن تكون `allowedModels` فارغة عندما يكون الوضع `all` | | `allowedModels`، `blockedModels` | مصفوفة من السلاسل النصية، حتى 1000 | | | `allowedCombos` | مصفوفة من السلاسل النصية، حتى 500 | يتحكم في المجموعات التي يجوز للمفتاح استدعاؤها؛ أما النماذج المباشرة فتحكمها `modelAccessMode` / `allowedModels` | | `connectionAccessMode` | `all` \| `restricted` | يجب أن تكون `allowedConnections` غير فارغة عند `restricted` وفارغة عند `all` | | `allowedConnections` | مصفوفة من معرفات UUID، حتى 100 | | | `allowAutoCombos` | قيمة منطقية | القيمة `false` ترفض طلبات نماذج `auto/*` بهذا المفتاح؛ أما المفاتيح التي لم تضبطها مطلقًا فهي مسموح لها | | `catalogScope` | `all` \| `combos` \| `models` | ما يعرضه `GET /v1/models` لهذا المفتاح (المجموعات فقط، أو النماذج فقط، أو كليهما)؛ ولا يغيّر ما يجوز للمفتاح استدعاؤه | | `forcedModel` | سلسلة نصية حتى 300 حرف، أو `null` | يوجّه طلبات المحادثة إلى هذا النموذج/المجموعة، متجاوزًا `X-Route-Model` و`body.model`؛ وتظل حدود المفتاح سارية | | `noLog`، `autoResolve` | قيمة منطقية | | | `throttleDelayMs` | عدد صحيح، 0-300000 | | | `maxSessions` | عدد صحيح، 0-10000 | | | `rateLimits` | مصفوفة من `{ limit, window }` (أعداد صحيحة موجبة، حتى 50) أو `null` | القيمة `null` تمحو الحدود | | `accessSchedule` | كائن جدول زمني أو `null` | القيمة `null` تمحو الجدول الزمني | | `scopes` | مصفوفة من السلاسل النصية، حتى 32 | | | `allowedEndpoints` | مصفوفة من السلاسل النصية، حتى 20 | | | `streamDefaultMode` | `legacy` \| `json` | | | `cacheDefaultMode` | `legacy` \| `bypass` | انظر [تجاوز ذاكرة التخزين المؤقت لكل مفتاح](#per-key-cache-bypass) | | `compressionEnabled` | قيمة منطقية | | | `codexServiceMode` | أحد أوضاع خدمة Codex | | | `disableNonPublicModels` | boolean | | | `allowUsageCommand` | boolean | | | `usageLimitEnabled` | boolean | | | `dailyUsageLimitUsd`, `weeklyUsageLimitUsd` | number >= 0 أو `null` | | | `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" }' ``` ### الإعدادات | نقطة النهاية | الطريقة | الوصف | | ------------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/settings` | GET/PUT/PATCH | الإعدادات العامة. مفاتيح سياسة الأمان (`requireLogin`، `newPassword`، `oidc*`، `corsOrigins`، `bruteForceProtection`) تتطلب `currentPassword` وبيانات اعتماد المشغّل — مفاتيح API ورموز `oma_` تتلقى `403`؛ وكل عملية تعديل تتطلب نطاق `admin` لرمز الوصول | | `/api/settings/proxy` | GET/PUT | إعدادات بروكسي الشبكة | | `/api/settings/proxy/test` | POST | اختبار اتصال البروكسي | | `/api/settings/ip-filter` | GET/PUT | قائمة السماح/الحظر لعناوين IP | | `/api/settings/thinking-budget` | GET/PUT | وضع إعادة كتابة **الطلب** الخاص بالتفكير/الاستدلال (passthrough / auto-strip / custom / adaptive). مستقل عن الضغط. راجع [THINKING_BUDGET.md](../guides/THINKING_BUDGET.md). | | `/api/settings/system-prompt` | GET/PUT | موجّه النظام العام | | `/api/settings/compression` | GET/PUT | إعدادات الضغط العامة | | `/api/settings/purge-request-history` | POST | مسح صفوف سجل الطلبات والعناصر الناتجة عن سجل الاستدعاءات المحلي | ### السياق والضغط | نقطة النهاية | الطريقة | الوصف | | -------------------------------------- | -------------- | -------------------------------------------------------------------------- | | `/api/compression/preview` | POST | معاينة ضغط off/lite/standard/aggressive/ultra/RTK/stacked | | `/api/compression/language-packs` | GET | سرد حزم لغات Caveman المتاحة | | `/api/compression/rules` | GET | سرد البيانات الوصفية لقواعد Caveman | | `/api/context/caveman/config` | GET/PUT | اسم مستعار لإعدادات خاصة بـ Caveman | | `/api/context/rtk/config` | GET/PUT | إعدادات خاصة بـ RTK، بما في ذلك المرشحات المخصصة والاحتفاظ بالمخرجات الخام | | `/api/context/rtk/filters` | GET | كتالوج مرشحات RTK وتشخيصات المرشحات المخصصة | | `/api/context/rtk/test` | POST | تشغيل معاينة/اختبار RTK على حمولة نصية | | `/api/context/rtk/raw-output/[id]` | GET | قراءة المخرجات الخام المحتجبة المحتفظ بها حسب معرّف المؤشر | | `/api/context/combos` | GET/POST | سرد/إنشاء مجموعات الضغط | | `/api/context/combos/[id]` | GET/PUT/DELETE | تفاصيل/تحديث/حذف مجموعة الضغط | | `/api/context/combos/[id]/assignments` | GET/PUT | تعيين مجموعات الضغط إلى مجموعات التوجيه | | `/api/context/analytics` | GET | اسم مستعار لتحليلات الضغط | ### المراقبة | نقطة النهاية | الطريقة | الوصف | | ------------------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/sessions` | GET | تتبع الجلسات النشطة | | `/api/rate-limits` | GET | حدود المعدل لكل حساب | | `/api/monitoring/health` | GET | فحص الصحة + ملخص المزوّد (`catalogCount`، `configuredCount`، `activeCount`، `monitoredCount`). يتضمن عرض الإدارة `credentialHealth`: مقاييس ذاكرة التخزين المؤقت للفحص، و`failedConnections` عندما `failed>0`، و`staleDbNonOkCount` (حالة `test_status` الثابتة في SQLite، وليس المقياس). انظر [MONITORING_GUIDE.md](../ops/MONITORING_GUIDE.md#credentialhealth-probe-cache-vs-sqlite-test_status). | | `/api/cache/stats` | GET/DELETE | إحصاءات ذاكرة التخزين المؤقت / مسح | | `/api/modality-bridge/stats` | GET | `attempts` في الذاكرة، والنجاحات/`bridged`، والإخفاقات، وإصابات ذاكرة التخزين المؤقت، و`totalLatencyMs`، و`latencySamples`، و`averageLatencyMs` المحسوب على أساس العينات، ووقت آخر استخدام (يُعاد ضبطه عند إعادة التشغيل؛ مصادقة الإدارة) | | `/api/modality-bridge/video/runtime` | GET | فحص صارم للاسترجاع الموثوق قبل مصادقة/فحص الإدارة؛ توفر FFmpeg/ffprobe والإصدارات بعد التعقيم (no-store) | | `/api/modality-bridge/video/extract` | POST | وسيط بايتات داخلي مُصادق عبر الاسترجاع الموثوق؛ إدخال 50 MiB، طابور محدود/إخراج 32 MiB، `503` للسعة، `499` لانقطاع الاتصال، `504` للمهلة الزمنية؛ ليس واجهة برمجة تطبيقات عامة للرفع | ### النسخ الاحتياطي والتصدير/الاستيراد | نقطة النهاية | الطريقة | الوصف | | --------------------------- | ------- | -------------------------------------------------------------------- | | `/api/db-backups` | GET | سرد النُسخ الاحتياطية المتاحة | | `/api/db-backups` | PUT | إنشاء نسخة احتياطية يدويًا | | `/api/db-backups` | POST | الاستعادة من نسخة احتياطية محددة | | `/api/db-backups` | PATCH | حفظ إعدادات الاحتفاظ بالنسخ الاحتياطية (للمشغّلين فقط) | | `/api/db-backups` | DELETE | تنقية النسخ الاحتياطية المخزّنة وفق إعدادات الاحتفاظ (للمشغّلين فقط) | | `/api/db-backups/export` | GET | تنزيل قاعدة البيانات كملف .sqlite | | `/api/db-backups/import` | POST | رفع ملف .sqlite لاستبدال قاعدة البيانات (`?dryRun=true` للتحقق فقط) | | `/api/db-backups/exportAll` | GET | تنزيل النسخة الاحتياطية الكاملة كأرشيف .tar.gz | تُسلِّم `/api/db-backups/export` و`/api/db-backups/exportAll` و`/api/settings/export-json` جميع بيانات الاعتماد المخزّنة، لذا تتطلب جلسة لوحة التحكم أو واجهة سطر الأوامر (CLI) المحلية (أو تسجيل دخول معطّل). تحصل مفاتيح API بأي نطاق ورموز الوصول `oma_` على `403`. وتلتزم عمليات الاستعادة بالحدّ نفسه: إذ إن `POST /api/db-backups/import` (بما في ذلك `dryRun=true`) و`POST /api/db-backups` (الاستعادة بالمعرّف) و`POST /api/settings/import-json` تستبدل قاعدة البيانات أو الإعدادات المباشرة، لذا تحصل بيانات اعتماد الآلة على `403` هناك أيضًا؛ ويرسل `omniroute sync import` بيانات اعتماد CLI المحلية. وينطبق الشيء نفسه على `DELETE /api/db-backups` (تنقية النسخ الاحتياطية المخزّنة) و`PATCH /api/db-backups` (إعدادات الاحتفاظ: القيم المحفوظة هي التي تُوجّه التنقية التلقائية بعد كل نسخة احتياطية). أما السرد (`GET`) وإنشاء نسخة احتياطية يدوية (`PUT`) فيحتفظان بمصادقة الإدارة العادية. ### المزامنة السحابية | نقطة النهاية | الطريقة | الوصف | | ---------------------- | ------- | ------------------------ | | `/api/sync/cloud` | Various | عمليات المزامنة السحابية | | `/api/sync/initialize` | POST | تهيئة المزامنة | | `/api/cloud/*` | Various | الإدارة السحابية | ### الأنفاق | نقطة النهاية | الطريقة | الوصف | | -------------------------- | ------- | ------------------------------------------------------------------ | | `/api/tunnels/cloudflared` | GET | قراءة حالة التثبيت/التشغيل لـ Cloudflare Quick Tunnel للوحة التحكم | | `/api/tunnels/cloudflared` | POST | تمكين أو تعطيل Cloudflare Quick Tunnel (`action=enable/disable`) | | `/api/tunnels/ngrok` | GET | قراءة حالة تشغيل نفق ngrok للوحة التحكم | | `/api/tunnels/ngrok` | POST | تمكين أو تعطيل نفق ngrok (`action=enable/disable`) | ### أدوات سطر الأوامر (CLI) | نقطة النهاية | الطريقة | الوصف | | ---------------------------------- | ------- | --------------------- | | `/api/cli-tools/claude-settings` | GET | حالة Claude CLI | | `/api/cli-tools/codex-settings` | GET | حالة Codex CLI | | `/api/cli-tools/droid-settings` | GET | حالة Droid CLI | | `/api/cli-tools/openclaw-settings` | GET | حالة OpenClaw CLI | | `/api/cli-tools/runtime/[toolId]` | GET | بيئة تشغيل CLI العامة | تتضمن استجابات CLI ما يلي: `installed`، `runnable`، `command`، `commandPath`، `runtimeMode`، `reason`. ### وكلاء ACP | نقطة النهاية | الطريقة | الوصف | | ----------------- | ------- | ------------------------------------------------------------ | | `/api/acp/agents` | GET | سرد جميع الوكلاء المكتشفين (المضمّنون + المخصّصون) مع الحالة | | `/api/acp/agents` | POST | إضافة وكيل مخصّص أو تحديث ذاكرة التخزين المؤقت للاكتشاف | | `/api/acp/agents` | DELETE | إزالة وكيل مخصّص عبر معامل الاستعلام `id` | تتضمن استجابة GET ‏`agents[]` (id, name, binary, version, installed, protocol, isCustom) و`summary` (total, installed, notFound, builtIn, custom). ### المرونة وحدود المعدل | نقطة النهاية | الطريقة | الوصف | | --------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/resilience` | GET/PATCH | الحصول على/تحديث قائمة انتظار الطلبات، وفترة تهدئة الاتصال، وقاطع دائرة المزوّد، وإعدادات الانتظار | | `/api/resilience/reset` | POST | إعادة تعيين قواطع دوائر المزوّدين | | `/api/resilience/model-cooldowns` | GET | عرض عمليات القفل النشطة لكل (مزوّد، اتصال، نموذج)، مرتبةً حسب الوقت المتبقي | | `/api/resilience/model-cooldowns` | DELETE | مسح قفل نموذج — المحتوى `{provider, model}` أو `{all: true}` لمسح كل شيء | | `/api/rate-limits` | GET/POST | حالة حد المعدل لكل حساب (GET) أو تبديل حماية حد المعدل لاتصال معين (POST `{connectionId, enabled}`). مسار الكتابة المدعوم لـ `rateLimitProtection` (لا يُعدَّل أبدًا عبر `PUT /api/providers/[id]`). ملاحظة: `enabled: false` يعطّل الحماية الصريحة لكنه لا يُخرج اتصال مفتاح API النشط من شبكة الأمان العامة للتفعيل التلقائي (`autoEnableApiKeyProviders`). | | `/api/rate-limit` | GET | تكوين حد المعدل العام (مهمل؛ اسم مستعار لـ `/api/rate-limits`) | > تتطلب جميع مسارات `/api/resilience/*` الأربعة **مصادقة الإدارة** (`requireManagementAuth`). راجع [المرونة (الموسّعة)](#resilience-extended) للحصول على شرح كامل للفرق بين قاطع دائرة المزوّد وفترة تهدئة الاتصال وقفل النموذج. ### التقييمات | نقطة النهاية | الطريقة | الوصف | | ------------ | -------- | ----------------------------------- | | `/api/evals` | GET/POST | عرض مجموعات التقييم / تشغيل التقييم | ### السياسات | نقطة النهاية | الطريقة | الوصف | | --------------- | --------------- | -------------------- | | `/api/policies` | GET/POST/DELETE | إدارة سياسات التوجيه | ### الامتثال | نقطة النهاية | الطريقة | الوصف | | --------------------------- | ------- | ---------------------------------- | | `/api/compliance/audit-log` | GET | سجل تدقيق الامتثال (آخر N إدخالات) | ### v1beta (متوافق مع Gemini) | نقطة النهاية | الطريقة | الوصف | | -------------------------- | ------- | --------------------------------------------- | | `/v1beta/models` | GET | عرض النماذج بتنسيق Gemini | | `/v1beta/models/{...path}` | POST | نقطة نهاية `generateContent` الخاصة بـ Gemini | تعكس نقاط النهاية هذه تنسيق واجهة برمجة تطبيقات Gemini للعملاء الذين يتوقعون توافقًا أصليًا مع Gemini SDK. ### واجهات برمجة التطبيقات الداخلية / الخاصة بالنظام | نقطة النهاية | الطريقة | الوصف | | ------------------------ | ------- | --------------------------------------------------- | | `/api/init` | GET | فحص تهيئة التطبيق (يُستخدم عند التشغيل الأول) | | `/api/tags` | GET | علامات نماذج متوافقة مع Ollama (لعملاء Ollama) | | `/api/restart` | POST | بدء إعادة تشغيل سلسة للخادم | | `/api/shutdown` | POST | بدء إيقاف تشغيل سلس للخادم | | `/api/system/env/repair` | POST | إصلاح متغيرات بيئة مزوّد OAuth | | `/api/system/version` | GET | الإصدار الحالي/الأحدث، وحالة التحديث، وقناة الإصدار | | `/api/system/version` | POST | بدء تحديث واعٍ بالنشر إلى أحدث إصدار | > **ملاحظة:** تُستخدم نقاط النهاية هذه داخليًا بواسطة النظام أو لتوافق عملاء Ollama. ولا يستدعيها المستخدمون النهائيون عادةً. ### إصلاح بيئة OAuth _(v3.6.1+)_ ```bash POST /api/system/env/repair Content-Type: application/json { "provider": "claude-code" } ``` يُصلح متغيرات بيئة OAuth المفقودة أو التالفة لمزوّد محدد. يُعيد: ```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" } ``` ### الإصدار وقناة الإصدار ```bash GET /api/system/version ``` مسار إدارة متاح عبر loopback فقط (مصادقة المسؤول). يُعيد الإصدار الجاري حاليًا، وأحدث إصدار منشور، وحالة التحديث التلقائي. الحقلان `releaseChannel` و`channels` حقول إضافية (مسار 3.8.54)؛ بينما يحتفظ `channel` بمعناه — وضع النشر الذي يستخدمه محدِّث لوحة التحكم (`npm` أو `source` أو `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 للبناء الجاري: `nightly` للإصدارات `-nightly.*`، و`next` لباقي الإصدارات التمهيدية (`-rc.*`، `-beta.*`، `-alpha.*`)، و`lts` لإصدار مستقر ينتمي إلى إصدار رئيسي أقدم من `channels.latest`، وإلا فتكون `latest`. القواعد نفسها المستخدمة في `scripts/release/dist-tag.mjs`، الذي يختار وسم dist-tag الخاص بـ npm وقت النشر. - `channels` — الرأس المنشور لكل dist-tag، مأخوذ من `npm view omniroute dist-tags` (مع رجوع احتياطي عبر HTTP إلى السجل)، ويُخزَّن مؤقتًا بنفس مدة TTL البالغة 10 دقائق الخاصة بـ `latest`. يكون `latest` موجودًا دائمًا (يرجع احتياطيًا إلى حقل `latest`، ثم إلى `"unavailable"`)؛ بينما تظهر `next` و`nightly` و`lts` فقط عندما يكون ذلك الـ dist-tag موجودًا. يؤدي طلب يحمل الترويسة `Cache-Control: no-cache` إلى تحديث كلتا العمليتين. نموذج القنوات (`latest` = v3 حتى الإصدار العام 4.0 GA، و`next` = rc، و`nightly` = بناءات `develop`، و`lts` = تصحيحات v3 بعد الإصدار العام 4.0 GA) موصوف في `docs/ops/RELEASE_STRATEGY.md`. --- ## نسخ الصوت ```bash POST /v1/audio/transcriptions Authorization: Bearer your-api-key Content-Type: multipart/form-data ``` انسخ الملفات الصوتية باستخدام أي موفّر STT تم إعداده. يحدد مقطع المسار الأول الموفّر الأصلي (`openai/…`، `deepgram/…`). تستخدم البوابات التي تعيد تصدير نموذج مورّد آخر معرّفًا مؤهلًا (`openrouter/deepgram/nova-3`). **الطلب:** ```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" ``` **الاستجابة:** ```json { "text": "مرحبًا، هذا هو المحتوى الصوتي المنسوخ.", "task": "transcribe", "language": "en", "duration": 12.5 } ``` **أمثلة على معرّفات النماذج:** `openai/whisper-1` (يتطلب مفتاح OpenAI)، `openrouter/deepgram/nova-3` (يتطلب مفتاح OpenRouter)، `deepgram/nova-3` (يتطلب مفتاح Deepgram أصليًا). الطلب المجرّد `deepgram/nova-3` **لا** يستخدم OpenRouter. **التنسيقات المدعومة:** `mp3`، `wav`، `m4a`، `flac`، `ogg`، `webm`. --- ## التوافق مع Ollama للعملاء الذين يستخدمون تنسيق API الخاص بـ Ollama: ```bash # نقطة نهاية الدردشة (بتنسيق Ollama) POST /v1/api/chat # عرض قائمة النماذج (بتنسيق Ollama) GET /api/tags ``` تُترجم الطلبات تلقائيًا بين تنسيقات Ollama والتنسيقات الداخلية. ## الأسماء البديلة المرمّزة لـ VS Code / من دون ترويسات استخدم هذه الأسماء البديلة عندما يتعذر على عملية تكامل إدخال ترويسة `Authorization` وتحتاج إلى تضمين مفتاح API في عنوان URL الأساسي. ```bash # اسم بديل للفهرس بنمط OpenAI GET /api/v1/vscode/{token}/ GET /api/v1/vscode/{token}/models # أسماء بديلة للدردشة بنمط OpenAI POST /api/v1/vscode/{token}/chat/completions POST /api/v1/vscode/{token}/responses # أسماء بديلة بنمط Ollama POST /api/v1/vscode/{token}/api/chat GET /api/v1/vscode/{token}/api/tags ``` مثال: ```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":"مرحبًا"}]}' ``` ملاحظات: - تعيد الأسماء البديلة المرمّزة استخدام معالجات الطلبات نفسها التي تستخدمها `/v1/*` و`/api/tags`؛ وتظل بُنى الاستجابات متطابقة. - يُفضّل استخدام `Authorization: Bearer ...` متى كان العميل يدعم الترويسات المخصصة. - قد تظهر الرموز المميزة المستندة إلى عناوين URL في سجلات الوكيل العكسي وسجل المتصفح وبيانات القياس عن بُعد خارج OmniRoute. تعامل معها باعتبارها خيارًا للتوافق، وليس وضع المصادقة الافتراضي. --- ## القياس عن بُعد ```bash # الحصول على ملخص بيانات زمن الاستجابة (p50/p95/p99 لكل موفّر) GET /api/telemetry/summary ``` **الاستجابة:** ```json { "providers": { "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 }, "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 } } } ``` --- ## الميزانية ```bash # الحصول على حالة الميزانية لجميع مفاتيح API GET /api/usage/budget # تعيين ميزانية أو تحديثها 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" } ``` > **ملاحظات المخطط** (`setBudgetSchema`): الحقل `apiKeyId` مطلوب؛ ويجب أن تكون قيمة واحد على الأقل من `dailyLimitUsd` أو `weeklyLimitUsd` أو `monthlyLimitUsd` أكبر من صفر. الحقول الاختيارية: `warningThreshold` ‏(0–1)، و`resetInterval` ‏(`daily` | `weekly` | `monthly`)، و`resetTime` ‏(`HH:MM`). يؤدي التنسيق القديم `{keyId, limit, period}` إلى إرجاع `400 Bad Request`. ## حدود الرموز ميزانيات **الرموز** لكل مفتاح API (وهي منفصلة عن الميزانية المستندة إلى الدولار الأمريكي أعلاه). تُطبَّق مباشرةً ضمن مسار الطلب: عندما يصل استخدام المفتاح خلال النافذة الحالية إلى الحد المسموح به، تُرفض الطلبات مع `429 Too Many Requests`. يمكن تحديد نطاق الحدود لنموذج `model` معيّن أو مزوّد `provider` معيّن، أو تطبيقها `global` على المفتاح بأكمله؛ وعندما تتطابق عدة حدود مع طلب، يُطبَّق الحد الأكثر تقييدًا. ```bash # عرض حدود الرموز لمفتاح (يتضمن الاستخدام المباشر ضمن النافذة) GET /api/usage/token-limits?apiKeyId=key-123 # إنشاء حد للرموز أو تحديثه POST /api/usage/token-limits Content-Type: application/json { "apiKeyId": "key-123", "scopeType": "model", "scopeValue": "openai/gpt-4o", "tokenLimit": 1000000, "resetInterval": "monthly", "enabled": true } # حذف حد للرموز حسب المعرّف DELETE /api/usage/token-limits?id=tl-abc ``` > **ملاحظات المخطط** (`setTokenLimitSchema`): الحقلان `apiKeyId` و`scopeType` (`model` | `provider` | `global`) مطلوبان. الحقل `scopeValue` مطلوب ما لم تكن قيمة `scopeType` هي `global` (على سبيل المثال، معرّف نموذج لنطاق `model` أو معرّف مزوّد لنطاق `provider`). يجب أن تكون قيمة `tokenLimit` عددًا صحيحًا موجبًا (تُحوَّل من سلسلة نصية). اختياري: `id` (احذفه للإنشاء وقدّمه للتحديث)، و`resetInterval` (`daily` | `weekly` | `monthly`، والقيمة الافتراضية `monthly`)، و`resetTime` (`HH:MM`)، و`enabled` (القيمة الافتراضية `true`). تُثري استجابات `GET` كل حد بالحقول `tokensUsed` و`remaining` و`windowStart` و`periodStartAt` و`nextResetAt`. هذه نقطة نهاية من فئة الإدارة (تُطبَّق المصادقة مركزيًا بواسطة مسار التفويض). ## معالجة الطلبات 1. يرسل العميل طلبًا إلى `/v1/*` 2. يستدعي معالج المسار `handleChat` أو `handleEmbedding` أو `handleAudioTranscription` أو `handleImageGeneration` 3. يُحدَّد النموذج (مزوّد/نموذج مباشر أو اسم مستعار/تركيبة) 4. تُحدَّد بيانات الاعتماد من قاعدة البيانات المحلية مع التصفية حسب توفر الحساب 5. بالنسبة إلى المحادثة: يتحقق `handleChatCore` من ذاكرة التخزين المؤقت الدلالية/الخاصة بالتوقيع ويحدد إعدادات ضغط التركيبة 6. يُنفَّذ الضغط الاستباقي قبل الترجمة الخاصة بالمزوّد عندما يكون مفعّلًا (`lite` أو Caveman أو RTK أو مكدّسًا) 7. يرسل منفّذ المزوّد الطلب إلى الجهة العليا 8. تُترجم الاستجابة مجددًا إلى تنسيق العميل (للمحادثة) أو تُعاد كما هي (للتضمينات/الصور/الصوت) 9. يُسجَّل الاستخدام وتحليلات الضغط وسجلات الطلبات 10. يُطبَّق البديل عند حدوث أخطاء وفقًا لقواعد التركيبة المرجع الكامل للبنية: [`ARCHITECTURE.md`](../architecture/ARCHITECTURE.md) --- ## إدارة التركيبات يمكن أيضًا ربط تركيبات التوجيه عالية المستوى (الملخّصة سابقًا ضمن `/api/combos*`) بنسبة 1:1 من نمط معرّف نموذج، مما يتيح إعادة توجيه شفافة لمعرّف نموذج بأسلوب OpenAI إلى تركيبة. | الطريقة | المسار | الوصف | | ------- | -------------------------------- | ------------------------------------------------------------------------- | | GET | `/api/model-combo-mappings` | عرض جميع روابط النموذج→التركيبة | | POST | `/api/model-combo-mappings` | إنشاء ربط — النص: `{pattern, comboId, priority?, enabled?, description?}` | | GET | `/api/model-combo-mappings/[id]` | استرداد ربط واحد | | PUT | `/api/model-combo-mappings/[id]` | تحديث حقول ربط موجود | | DELETE | `/api/model-combo-mappings/[id]` | إزالة ربط | **المصادقة:** جلسة إدارة/مفتاح API (`requireManagementAuth`). --- ## خطافات الويب اشتراكات خطافات الويب الصادرة لأحداث OmniRoute (اكتمال الطلب، استنفاد الحصة، تدوير المفتاح، إلخ). | الطريقة | المسار | الوصف | | ------- | ------------------------- | --------------------------------------------------------------------- | | GET | `/api/webhooks` | سرد خطافات الويب (تُحجب الأسرار بصيغة `...`) | | POST | `/api/webhooks` | إنشاء خطاف ويب — النص: `{url, events?: ["*"], secret?, description?}` | | GET | `/api/webhooks/[id]` | استرداد خطاف ويب | | PUT | `/api/webhooks/[id]` | تحديث url/events/secret/description | | DELETE | `/api/webhooks/[id]` | إزالة خطاف ويب | | POST | `/api/webhooks/[id]/test` | إرسال حمولة اختبار إلى عنوان URL لخطاف الويب وإرجاع حالة التسليم | **المصادقة:** جلسة الإدارة/مفتاح API ‏(`requireManagementAuth`). --- ## المفاتيح المسجّلة (الإدارة التلقائية) يستخدمها النظام الفرعي للإدارة التلقائية للمفاتيح لإصدار مفاتيح API وتدويرها لدى موفّر/حساب داعم، مع حصص يومية/ساعية. | الطريقة | المسار | الوصف | | ------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/v1/registered-keys` | سرد المفاتيح المسجّلة (البادئة المقنّعة فقط) | | POST | `/api/v1/registered-keys` | إصدار مفتاح مسجّل جديد — النص: `{name, provider?, accountId?, idempotencyKey?, expiresAt?, dailyBudget?, hourlyBudget?}`. يعيد المفتاح الخام **مرة واحدة**. يعيد `429` عند رفض الحصة. | | GET | `/api/v1/registered-keys/[id]` | استرداد البيانات الوصفية لمفتاح مسجّل (من دون المادة الخام) | | DELETE | `/api/v1/registered-keys/[id]` | إبطال مفتاح مسجّل | | POST | `/api/v1/registered-keys/[id]/revoke` | نقطة نهاية صريحة للإبطال (لها التأثير نفسه الذي يحدثه DELETE) | **المصادقة:** جلسة الإدارة/مفتاح API (`requireManagementAuth`) — آلية الحماية نفسها المستخدمة في `/api/keys`: جلسة لوحة المعلومات، أو رمز CLI المحلي، أو مفتاح API بنطاق `manage`/`admin`؛ تحصل مفاتيح API المخصّصة للاستدلال فقط على `403`. راجع أيضًا `/v1/quotas/check` و`/v1/issues/report`. --- ## بروتوكول الوكلاء مهام الوكلاء السحابيين (Claude Code وCodex Cloud وOpenHands وغيرها) التي تُنفَّذ عن بُعد نيابةً عن مستخدمي OmniRoute. | الطريقة | المسار | الوصف | | ------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/v1/agents/tasks` | سرد المهام — مع معاملات اختيارية `?provider=` و`?status=` و`?limit=` (من 1 إلى 500، والقيمة الافتراضية 50) | | POST | `/api/v1/agents/tasks` | إنشاء مهمة — يجري التحقق من صحة المتن بواسطة `CreateCloudAgentTaskSchema` (`providerId` و`prompt` و`source` و`options?`). يُرجع `201` مع مغلف المهمة | | DELETE | `/api/v1/agents/tasks?id=...` | حذف مهمة | | GET | `/api/v1/agents/tasks/[id]` | قراءة مهمة — يحدّث الحالة تزامنيًا من الوكيل السحابي المصدر عند تعيين `external_id` | | POST | `/api/v1/agents/tasks/[id]` | إجراء مميَّز: `{action: "approve"}` أو `{action: "message", message}` أو `{action: "cancel"}` | | DELETE | `/api/v1/agents/tasks/[id]` | حذف مهمة محددة حسب المعرّف | > **المصادقة:** مصادقة الإدارة مطلوبة لكل طريقة (`requireCloudAgentManagementAuth`). قبل v3.8.0، لم تكن هذه المسارات تتطلب مصادقة — راجع الالتزام `588a0333` لمعرفة التغيير غير المتوافق. ```bash # إنشاء مهمة سحابية في 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":"..."}}' ``` --- ## وكلاء الإدارة وكلاء HTTP(S)/SOCKS الصادرون الذين يمكن تعيينهم لمزوّدي الخدمة أو الحسابات أو على المستوى العام. | الطريقة | المسار | الوصف | | ------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/v1/management/proxies` | سرد الوكلاء (مع `?id=` يُرجع وكيلاً واحدًا؛ ومع `?id=&where_used=1` يُرجع مخطط التعيينات) | | POST | `/api/v1/management/proxies` | إنشاء وكيل — يجري التحقق من صحة المتن بواسطة `createProxyRegistrySchema` | | PATCH | `/api/v1/management/proxies` | تحديث وكيل — يجري التحقق من صحة المتن بواسطة `updateProxyRegistrySchema` (يتطلب `id`) | | DELETE | `/api/v1/management/proxies?id=...&force=1` | حذف وكيل (استخدم `force=1` لفصل التعيينات) | | GET | `/api/v1/management/proxies/assignments` | سرد التعيينات — يمكن تصفيتها حسب `proxy_id` و`scope` و`scope_id`؛ مرّر `resolve_connection_id=` لتحديد الوكيل النشط لاتصال ما | | PUT | `/api/v1/management/proxies/assignments` | تعيين — يجري التحقق من صحة المتن بواسطة `proxyAssignmentSchema` (`{scope, scopeId?, proxyId?}`). يمسح ذاكرة التخزين المؤقت للمُرسِل | | PUT | `/api/v1/management/proxies/bulk-assign` | تعيين جماعي — يجري التحقق من صحة المتن بواسطة `bulkProxyAssignmentSchema` (`{scope, scopeIds[], proxyId?}`) | | GET | `/api/v1/management/proxies/health?hours=24` | تجميع حالة الوكلاء (أعداد النجاح/الفشل وزمن الاستجابة) خلال نافذة زمنية | **المصادقة:** جلسة إدارة/مفتاح API مطلوب لكل مسار (`requireManagementAuth`). > يُخدَم المساران `POST /api/v1/management/proxies/[id]/assignments` و`POST /api/v1/management/proxies/[id]/health` الواردان في وصف المهمة عبر مساري `/assignments` و`/health` المبسّطين الموضحين أعلاه — لا توجد في قاعدة الشفرة مسارات فرعية منفصلة لكل معرّف. --- ## المرونة (موسّع) يوفّر OmniRoute ثلاث آليات مستقلة للتعامل مع الأعطال المؤقتة؛ وتتيح نقاط النهاية الإدارية أدناه للمشغّلين قراءتها وتجاوزها: | النطاق | تخزين الحالة | القراءة | إعادة التعيين / المسح | | ------------------ | -------------------------------------- | ----------------------------------------- | ------------------------------------------------------ | | قاطع المزوّد | `domain_circuit_breakers` + في الذاكرة | `/api/monitoring/health` | `POST /api/resilience/reset` | | فترة تهدئة الاتصال | `rateLimitedUntil` على اتصالات المزوّد | `/api/rate-limits`، `/api/providers/[id]` | (يُعاد تمكينه بشكل كسول؛ يُمسح عبر PUT الخاص بالمزوّد) | | حظر النموذج | سجلّ توفّر النماذج في الذاكرة | `GET /api/resilience/model-cooldowns` | `DELETE /api/resilience/model-cooldowns` | يقبل `PATCH /api/resilience` تجاوزات قاطع المزوّد ضمن `providerBreaker.oauth` و`providerBreaker.apikey`. ويدعم كل ملف تعريف الحقول `degradationThreshold` و`failureThreshold` و`resetTimeoutMs`؛ وتُعرَض الحقول نفسها في لوحة التحكم ← الإعدادات ← المرونة. ```bash # مسح حظر نموذج واحد 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"}' # مسح جميع عمليات الحظر curl -X DELETE http://localhost:20128/api/resilience/model-cooldowns \ -H "Cookie: auth_token=..." \ -d '{"all":true}' ``` للمرجع المفاهيمي الكامل والقيم الافتراضية للقاطع: راجع [`CLAUDE.md`](../../CLAUDE.md) ← "Resilience Runtime State" و[`docs/architecture/RESILIENCE_GUIDE.md`](../architecture/RESILIENCE_GUIDE.md). ### قائمة انتظار حدّ المعدل وشبكة الأمان للتمكين التلقائي - **مسار الكتابة المدعوم**: `POST /api/rate-limits` مع الجسم `{"connectionId": "", "enabled": true|false}` هو نقطة النهاية الإدارية المدعومة لتبديل حماية حدّ المعدل لاتصال معيّن. ولا يقوم `PUT /api/providers/[id]` عمدًا بتعديل أو قلب `rateLimitProtection` (#11278). - **دلالات `enabled: false`**: إن تعيين `enabled: false` يزيل الحماية الصريحة عن الاتصال، لكنه **لا** يستثني اتصال مفتاح API النشط من شبكة الأمان العامة للتمكين التلقائي (`autoEnableApiKeyProviders = true`). ففي `reconcileEnabledConnections` (`open-sse/services/rateLimitManager.ts`)، تتكافأ القيمتان `false` و`undefined`؛ وتبقى اتصالات مفاتيح API النشطة التي لا تملك حماية صريحة محميةً بموجب شبكة الأمان للتمكين التلقائي. - **التعطيل العام**: لتشغيل اتصالات مفاتيح API دون قوائم انتظار حدّ المعدل، عطّل شبكة الأمان عمومًا عبر `RATE_LIMIT_AUTO_ENABLE=false` (متغيّر بيئة) أو `resilienceSettings.requestQueue.autoEnableApiKeyProviders = false` (الإعدادات ← المرونة / `PATCH /api/resilience`). --- ## المهارات إطار عمل للمهارات يتيح توسيع OmniRoute باستخدام معالجات تنفيذية مخصّصة، إلى جانب عمليات التكامل مع الأسواق. | الطريقة | المسار | الوصف | | ------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/skills` | عرض المهارات المثبّتة — قابلة للتصفية باستخدام `?q=` و`?mode=on\|off\|auto` و`?source=skillsmp\|skillssh\|local`، مع تقسيم النتائج إلى صفحات | | GET | `/api/skills/[id]` | استرداد مهارة واحدة | | PUT | `/api/skills/[id]` | تحديث مهارة (الاسم، والوصف، والوضع، والمخطط، والمعالج، والوسوم) | | DELETE | `/api/skills/[id]` | إلغاء تثبيت مهارة | | POST | `/api/skills/install` | تثبيت مهارة من بيان خام — النص: `{name, version, description, schema:{input, output}, handlerCode, apiKeyId?}` | | GET | `/api/skills/executions` | عرض أحدث عمليات تنفيذ المهارات (سجل تدقيق يتضمن المدخلات والمخرجات والمدة) | | GET | `/api/skills/marketplace?q=...` | البحث أو عرض القائمة الشائعة من سوق SkillsMP (يتطلب إعداد `skillsmpApiKey`) | | POST | `/api/skills/marketplace/install` | تثبيت مهارة حسب المعرّف من SkillsMP | | GET | `/api/skills/skillssh?q=&limit=` | البحث في سجل skills.sh | | POST | `/api/skills/skillssh/install` | تثبيت مهارة حسب المعرّف من skills.sh | **المصادقة:** جلسة الإدارة/مفتاح API. تقبل مسارات البحث في السوق إما مصادقة الإدارة أو مفتاح Bearer API ‏(`isAuthenticated`). --- ## الذاكرة مخزن دائم للذاكرة الحوارية/الواقعية، محدد النطاق لكل مفتاح API / جلسة. | الطريقة | المسار | الوصف | | ------- | -------------------- | --------------------------------------------------------------------------------------------------------------------- | | GET | `/api/memory` | سرد الذكريات — `?apiKeyId=`, `?type=`, `?sessionId=`, `?q=`، مع ترقيم الصفحات باستخدام `offset/limit` أو `page/limit` | | POST | `/api/memory` | إنشاء ذاكرة — يتم التحقق من النص بواسطة Zod: `{content, key, type?, sessionId?, apiKeyId?, metadata?, expiresAt?}` | | GET | `/api/memory/[id]` | استرداد ذاكرة واحدة | | DELETE | `/api/memory/[id]` | حذف ذاكرة | | GET | `/api/memory/health` | حالة نظام الذاكرة الفرعي (اتصال قاعدة البيانات، والواجهة الخلفية للتضمينات، وحالة فهرس المتجهات) | **المصادقة:** جلسة إدارة/مفتاح API (`requireManagementAuth`). تعداد `type`:‏ `FACTUAL`, `EPISODIC`, `SEMANTIC`, `PROCEDURAL` (راجع `MemoryType` في `src/lib/memory/types.ts`). --- ## خادم MCP يتضمن OmniRoute خادم Model Context Protocol مضمّنًا مع 3 وسائل نقل (stdio وSSE وstreamable-http) وأدوات محددة النطاق. تقرأ نقاط نهاية لوحة المعلومات أدناه بيانات الحالة/التدقيق، وتعمل كوسيط لوسائل نقل HTTP. | الطريقة | المسار | الوصف | | ------ | ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------- | | GET | `/api/mcp/status` | نبضات الاستمرارية، ووسيلة النقل، وحالة الاتصال، وآخر استدعاء، والأدوات الأكثر استخدامًا، ومعدل النجاح خلال 24 ساعة | | GET | `/api/mcp/tools` | قائمة بأدوات MCP تتضمن `name`، و`description`، و`scopes`، و`phase`، و`auditLevel`، و`sourceEndpoints` | | GET | `/api/mcp/sse` | فتح تدفق SSE لوسيلة نقل SSE (يعيد `503` إذا كان MCP معطّلًا أو كانت وسيلة النقل غير متطابقة) | | POST | `/api/mcp/sse` | إرسال إطار JSON-RPC عبر وسيلة نقل SSE | | GET | `/api/mcp/stream` | فتح جانب SSE من وسيلة نقل Streamable HTTP (رسائل يبدأها الخادم) | | POST | `/api/mcp/stream` | إرسال إطار JSON-RPC عبر وسيلة نقل Streamable HTTP | | DELETE | `/api/mcp/stream` | إنهاء جلسة Streamable HTTP | | GET | `/api/mcp/audit` | الاستعلام عن سجل التدقيق — `?limit=`، و`?offset=`، و`?tool=`، و`?success=true | false`، و`?apiKeyId=` | | GET | `/api/mcp/audit/stats` | إحصاءات تدقيق مجمّعة (الإجماليات، ومعدل النجاح، ومتوسط المدة، والأدوات الأكثر استخدامًا) | **المصادقة:** تراعي وسائل النقل `sse`/`stream` واجهة المصادقة الخاصة بـMCP (مفتاح Bearer API بنطاق `mcp`)؛ ويمكن قراءة مسارات `status`/`tools`/`audit*` من لوحة المعلومات (لا يلزم إجراء مصادقة إضافية بخلاف إمكانية الوصول إلى مضيف لوحة المعلومات). > تخضع وسيلتا نقل HTTP لكل من `settings.mcpEnabled` و`settings.mcpTransport` — يؤدي عدم تطابق وسيلة النقل إلى إرجاع `400`، بينما تؤدي حالة تعطيل MCP إلى إرجاع `503`. --- ## خادم A2A يوفّر OmniRoute نقطة نهاية A2A (من وكيل إلى وكيل) وفق JSON-RPC 2.0، بالإضافة إلى واجهة REST للاستخدام في الفحص/لوحة المعلومات. ### JSON-RPC ```bash POST /a2a Authorization: Bearer your-api-key # اختياري ما لم يتم تعيين OMNIROUTE_API_KEY Content-Type: application/json { "jsonrpc": "2.0", "id": 1, "method": "message/send", "params": { "skill": "smart-routing", "messages": [{"role": "user", "content": "وجّه مهمة البرمجة هذه"}] } } ``` الطرق المدعومة (كلها مشروطة بتفعيل `settings.a2aEnabled`): | الطريقة | الوصف | | ---------------- | -------------------------------------------------------- | | `message/send` | تنفيذ متزامن للمهارة؛ يعيد `{task, artifacts, metadata}` | | `message/stream` | تنفيذ متدفق عبر SSE لمجموعة المهارات نفسها | | `tasks/get` | جلب مهمة باستخدام `taskId` | | `tasks/cancel` | إلغاء مهمة باستخدام `taskId` | المهارات المضمّنة: `smart-routing`، و`quota-management`، و`provider-discovery`، و`cost-analysis`، و`health-report`. ### بطاقة الوكيل ```bash GET /.well-known/agent.json ``` يعيد بطاقة وكيل A2A العامة (الاسم، والوصف، والإمكانات، ودليل المهارات، ونظام المصادقة) — وتُخزّن مؤقتًا بشكل عام لمدة ساعة واحدة. لا تتطلب مصادقة. ### أدوات REST المساعدة | الطريقة | المسار | الوصف | | ------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------ | | GET | `/api/a2a/status` | حالة تفعيل A2A + إحصاءات المهام + ملخص بطاقة الوكيل المخزّنة مؤقتًا | | GET | `/api/a2a/tasks` | سرد المهام — `?state=submitted\|working\|completed\|failed\|cancelled`، و`?skill=`، و`?limit=` (≤200)، و`?offset=` | | POST | `/api/a2a/tasks` | (غير منفّذ كأداة REST مساعدة — أنشئ عبر JSON-RPC باستخدام `message/send`) | | GET | `/api/a2a/tasks/[id]` | استرداد مهمة واحدة | | POST | `/api/a2a/tasks/[id]/cancel` | إلغاء مهمة | **المصادقة:** تعمل أدوات REST المساعدة دون مصادقة إدارية (قابلة للقراءة من لوحة المعلومات)؛ ويستخدم مسار JSON-RPC‏ `/a2a` رمز Bearer‏ `OMNIROUTE_API_KEY` إذا كان مهيّأً. --- ## السحابة والتقييمات والتقدير | الطريقة | المسار | الوصف | | ------ | ------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------- | ----------------------------------- | | POST | `/api/cloud/auth` | التحقق من مفتاح Bearer وإرجاع اتصالات المزوّدين المخفية جزئيًا + الأسماء المستعارة للنماذج لعملاء المزامنة السحابية | | POST | `/api/cloud/credentials/update` | تحديث بيانات الاعتماد المشفّرة لمزوّد متزامن مع السحابة | | POST | `/api/cloud/model/resolve` | تحويل معرّف نموذج منطقي إلى مزوّد/نموذج فعلي باستخدام جدول التوجيه المحلي | | GET | `/api/cloud/models/alias` | سرد الأسماء المستعارة للنماذج كما تُعرض للمزامنة السحابية | | GET | `/api/assess` | قراءة أحدث تصنيفات التقدير (لكل مزوّد/نموذج) | | POST | `/api/assess` | تشغيل تقدير — النص: `{scope: {type:"all"} | {type:"provider", providerId} | {type:"model", modelId}, trigger?}` | | GET | `/api/evals` | سرد حِزم التقييم المضمّنة + أحدث عمليات التشغيل | | POST | `/api/evals` | تشغيل عملية تقييم | | POST | `/api/evals/suites` | إنشاء حزمة تقييم مخصّصة — يتم التحقق من صحة النص بواسطة `evalSuiteSaveSchema` | | GET | `/api/evals/suites/[id]` | استرداد حزمة تقييم مخصّصة | **المصادقة:** يتحقق `/api/cloud/auth` من مفتاح Bearer مباشرةً، ولا يُرجع المفتاح المخفي جزئيًا و`projectId` لكل اتصال إلا لمفتاح ذي نطاق `manage` / `admin`؛ بينما تتطلب مسارات `/api/cloud/*` و`/api/evals/*` و`/api/assess` الأخرى جلسة إدارة/مفتاح API. يستخدم طلب POST إلى `/api/assess` الدالة `validateBody` مع مخطط نطاق لاتحاد مميَّز. --- ## إدارة ACP (بروتوكول عميل الوكيل) كعمليات فرعية. تدير نقاط النهاية هذه اكتشاف وكلاء ACP وتسجيل الوكلاء المخصصين. | الطريقة | المسار | الوصف | | ------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/acp/agents` | سرد جميع وكلاء CLI المعروفين (المدمجين + المخصصين) مع حالة التثبيت والإصدار والملف التنفيذي | | POST | `/api/acp/agents` | تسجيل وكيل ACP مخصص أو تحديث ذاكرة التخزين المؤقت — النص: `{id, name, binary, versionCommand, providerAlias, spawnArgs, protocol}` أو `{action: "refresh"}` | | DELETE | `/api/acp/agents` | إزالة وكيل ACP مخصص — معامل الاستعلام: `?id=` | **مثال على الاستجابة** (`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 } ``` **المصادقة:** تتطلب جلسة إدارة (ملف تعريف ارتباط `auth_token` الخاص بلوحة المعلومات) أو مفتاح API بنطاق الإدارة. راجع [إطار عمل ACP](../frameworks/ACP.md) للاطلاع على التفاصيل الكاملة. --- ## التحليلات وقابلية المراقبة نقاط نهاية للتحليلات في الوقت الفعلي لمراقبة التوجيه والضغط وتنوع المزودين. تُشغّل هذه النقاط صفحات `/dashboard/analytics/*`. ### تحليلات التوجيه التلقائي | الطريقة | المسار | الوصف | | ------- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------- | | GET | `/api/analytics/auto-routing` | إحصاءات مجمّعة للتوجيه التلقائي: إجمالي الاستدعاءات، وتوزيع الاستراتيجيات، وتوزيع المستويات، وأبرز المزودين | | GET | `/api/analytics/auto-routing?days=7` | إحصاءات ضمن نافذة زمنية (الافتراضي 24 ساعة) | **مثال على الاستجابة**: ```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 } ] } ``` ### تحليلات الضغط | الطريقة | المسار | الوصف | | ------- | ---------------------------- | ---------------------------------------------------------------------------------------- | | GET | `/api/analytics/compression` | إحصاءات مجمّعة للضغط: الرموز الموفَّرة، ونسبة التوفير، وتوزيع الأوضاع، واستخدام المحركات | **مثال على الاستجابة**: ```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 } } ``` ### تتبّع تنوع المزودين | الطريقة | المسار | الوصف | | ------- | -------------------------- | ----------------------------------------------------------------------------------------------------------- | | GET | `/api/analytics/diversity` | تتبّع التنوع المستند إلى إنتروبيا شانون: يمنع نقاط الفشل المفردة من خلال قياس انتشار الاستخدام بين المزودين | **مثال على الاستجابة**: ```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"] } ``` **المصادقة:** تتطلب جلسة إدارة أو مفتاح API بنطاق الإدارة. --- ## عمليات الإدارة نقاط نهاية مخصصة للمسؤولين لإدارة العمليات. | الطريقة | المسار | الوصف | | ------- | ------------------------ | ------------------------------------------------------------------------------------ | | GET | `/api/admin/concurrency` | قراءة حدود التزامن الحالية (العامة + الخاصة بكل مزود) | | POST | `/api/admin/concurrency` | تحديث حدود التزامن — النص: `{global?: number, perProvider?: Record}` | **المصادقة:** تتطلب جلسة إدارة بنطاق مسؤول. --- ## إدارة أدوات CLI أدِر أدوات CLI التي تتكامل مع OmniRoute ‏(antigravity وcommandCode و devin-cli وغيرها). راجع [مرجع موفّري الخدمة](./PROVIDER_REFERENCE.md) للاطلاع على القائمة الكاملة. | الطريقة | المسار | الوصف | | ------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/cli-tools/all-statuses` | حالة جميع أدوات CLI (التثبيت، الإصدار، وآخر ظهور) | | GET | `/api/cli-tools/status` | تفاصيل حالة أداة CLI واحدة (استعلام `?tool=`) | | POST | `/api/cli-tools/apply` | كتابة الإعداد المُنشأ لأداة (`dryRun` للمعاينة؛ `422` مع `containerEphemeralTarget` عند التشغيل داخل حاوية؛ وتوضّح `migration` وجود ملف Codex YAML قديم) | | GET | `/api/cli-tools/backups` | سرد النسخ الاحتياطية لإعدادات أدوات CLI | | POST | `/api/cli-tools/backups` | إنشاء نسخة احتياطية من إعدادات جميع أدوات CLI | | POST | `/api/cli-tools/backups` | الاستعادة: تؤدي نقطة النهاية نفسها، مع `{tool, backupId}` في النص، إلى استعادة تلك النسخة الاحتياطية | | GET | `/api/cli-tools/antigravity-mitm` | حالة وكيل MITM لـ Antigravity (أداة CLI المسماة "antigravity-mitm") | | POST | `/api/cli-tools/antigravity-mitm/alias` | إعداد الأسماء المستعارة لـ antigravity-mitm | **المصادقة:** تتطلب جلسة إدارة. --- ## مهارات الوكلاء إدارة مهارات وكلاء الذكاء الاصطناعي (على غرار نماذج GPT المخصصة من OpenAI، ولكن للوكلاء). | الطريقة | المسار | الوصف | | ------- | ---------------------------- | ---------------------------------------------------------------------------------- | | GET | `/api/agent-skills` | سرد جميع مهارات الوكلاء (المدمجة + المخصصة) | | GET | `/api/agent-skills/[id]` | الحصول على مهارة وكيل محددة | | POST | `/api/agent-skills` | إنشاء مهارة وكيل مخصصة — النص: `{name, description, prompt, model?, temperature?}` | | PUT | `/api/agent-skills/[id]` | تحديث مهارة وكيل مخصصة | | DELETE | `/api/agent-skills/[id]` | حذف مهارة وكيل مخصصة | | GET | `/api/agent-skills/[id]/raw` | الحصول على المطالبة الأولية + البيانات الوصفية (من دون تنفيذ) | | POST | `/api/agent-skills/generate` | إنشاء مهارة جديدة باستخدام الذكاء الاصطناعي من وصف بلغة طبيعية | **المصادقة:** تتطلب جلسة إدارة أو مفتاح API بنطاق الإدارة. --- ## إدارة ذاكرة التخزين المؤقت إدارة ذاكرة التخزين المؤقت الدلالية وذاكرة التخزين المؤقت للاستدلال. | الطريقة | المسار | الوصف | | ------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | GET | `/api/cache` | نظرة عامة على ذاكرة التخزين المؤقت: إجمالي الإدخالات، ومعدل الإصابات، والحجم على القرص | | GET | `/api/cache/entries` | عرض إدخالات ذاكرة التخزين المؤقت (مع ترقيم الصفحات) | | DELETE | `/api/cache/entries` | حذف إدخالات ذاكرة التخزين المؤقت (التصفية حسب معاملات الاستعلام) | | GET | `/api/cache/stats` | إحصاءات تفصيلية لذاكرة التخزين المؤقت (لكل موفّر ولكل نموذج) | | GET | `/api/cache/reasoning` | حالة ذاكرة التخزين المؤقت للاستدلال (لإعادة تشغيل الاستدلال) | | DELETE | `/api/cache/reasoning` | مسح ذاكرة التخزين المؤقت للاستدلال — معاملات الاستعلام: `?toolCallId=` (إدخال واحد) أو `?provider=

` أو بلا معاملات (الكل) | **المصادقة:** تتطلب جلسة إدارة. --- ## نظام الذاكرة إدارة الذاكرة الدائمة (FTS5 + تضمينات المتجهات). | الطريقة | المسار | الوصف | | ------- | ------------------ | ------------------------------------------------------------------------- | | GET | `/api/memory` | عرض إدخالات الذاكرة (التصفية حسب النطاق والنوع واستعلام البحث) | | POST | `/api/memory` | إنشاء إدخال ذاكرة جديد — النص: `{scope, type, content, metadata?}` | | GET | `/api/memory/[id]` | الحصول على إدخال ذاكرة محدد | | PUT | `/api/memory/[id]` | تحديث إدخال ذاكرة | | DELETE | `/api/memory/[id]` | حذف إدخال ذاكرة | | GET | `/api/memory?q=` | البحث في الذاكرة (FTS5 + المتجهات) — تُضمَّن الإحصاءات في الاستجابة نفسها | **المصادقة:** تتطلب جلسة إدارة أو مفتاح API بنطاق إدارة. --- ## خطافات الويب إدارة اشتراكات خطافات الويب للأحداث. | الطريقة | المسار | الوصف | | ------- | ------------------------------- | ----------------------------------------------------------------- | | GET | `/api/webhooks` | عرض جميع اشتراكات خطافات الويب | | POST | `/api/webhooks` | إنشاء اشتراك خطاف ويب — النص: `{url, events[], secret?, active?}` | | GET | `/api/webhooks/[id]` | الحصول على اشتراك خطاف ويب محدد | | PUT | `/api/webhooks/[id]` | تحديث اشتراك خطاف ويب | | DELETE | `/api/webhooks/[id]` | حذف اشتراك خطاف ويب | | GET | `/api/webhooks/[id]/deliveries` | عرض سجل التسليم لخطاف ويب (سجل النجاح/الفشل) | | POST | `/api/webhooks/[id]/test` | إرسال حدث اختباري إلى خطاف ويب | **المصادقة:** تتطلب جلسة إدارة. راجع [إطار عمل خطافات الويب](../frameworks/WEBHOOKS.md) للاطلاع على أنواع الأحداث كاملةً. --- ## إطار المهارات إدارة المهارات (إطار الامتدادات الوكيلة). | الطريقة | المسار | الوصف | | ------- | ------------------------ | ------------------------------------------------------------------------------------ | | GET | `/api/skills` | سرد جميع المهارات المثبتة (المدمجة + المخصصة) | | POST | `/api/skills/install` | تثبيت مهارة من مسار محلي أو عنوان URL | | DELETE | `/api/skills/[id]` | إلغاء تثبيت مهارة | | PUT | `/api/skills/[id]` | تمكين مهارة أو تعطيلها — النص: `{enabled?: boolean, mode?: "on" \| "off" \| "auto"}` | | POST | `/api/skills/executions` | تنفيذ مهارة — النص: `{skillName, apiKeyId, input?, sessionId?}` | | GET | `/api/skills/executions` | سرد سجل التنفيذ لجميع المهارات (التصفية باستخدام `?apiKeyId=`) | **المصادقة:** تتطلب جلسة إدارة أو مفتاح API بنطاق إدارة. راجع [إطار المهارات](../frameworks/SKILLS.md) للاطلاع على التفاصيل الكاملة. --- ## الإضافات إدارة إضافات OmniRoute (امتدادات الجهات الخارجية). | الطريقة | المسار | الوصف | | ------- | ---------------------------------- | --------------------------- | | GET | `/api/plugins` | سرد الإضافات المثبتة | | POST | `/api/plugins/marketplace/install` | تثبيت إضافة من سوق الإضافات | | DELETE | `/api/plugins/[name]` | إلغاء تثبيت إضافة | | POST | `/api/plugins/[name]/activate` | تنشيط إضافة | | POST | `/api/plugins/[name]/deactivate` | إلغاء تنشيط إضافة | | GET | `/api/plugins/[name]/config` | الحصول على إعدادات الإضافة | | PUT | `/api/plugins/[name]/config` | تحديث إعدادات الإضافة | **المصادقة:** تتطلب جلسة إدارة. راجع [إطار الإضافات](../frameworks/PLUGIN_SDK.md) للاطلاع على التفاصيل الكاملة. --- ## التوجيه الظلي المقارنة الظلية / أ-ب بين المزوّدين **ليست واجهة REST مستقلة** — بل تُهيّأ من خلال التوجيه المركب (راجع [التركيب التلقائي](../routing/AUTO-COMBO.md)). تُقدَّم مقاييس المقارنة الخاصة بكل تركيبة عبر `GET /api/combos/metrics`. --- ## ضوابط الحماية فحص ضوابط الحماية في وقت التشغيل (اكتشاف معلومات التعريف الشخصية، واكتشاف حقن المطالبات، وربط الرؤية). تعمل ضوابط الحماية مع كل طلب؛ ويمكن إلغاء الاشتراك لكل استدعاء عبر ترويسة الطلب `x-omniroute-disabled-guardrails` — ولا توجد واجهة دائمة للتمكين/التعطيل. | الطريقة | المسار | الوصف | | ------- | ---------------------- | ------------------------------------------------------------------------------------------------- | | GET | `/api/guardrails` | سرد ضوابط الحماية المسجلة وحالتها (الاسم / ممكّنة / الأولوية) | | POST | `/api/guardrails/test` | إجراء تشغيل تجريبي لمسار ما قبل الاستدعاء على إدخال نموذجي — النص: `{input, disabledGuardrails?}` | **المصادقة:** تتطلب جلسة إدارة. راجع [الأمان > ضوابط الحماية](../security/GUARDRAILS.md) للاطلاع على التفاصيل الكاملة. --- --- ## المصادقة راجع [مصادقة الإدارة](../guides/MANAGEMENT-AUTH.md) للتعرّف على عائلات بيانات الاعتماد الأربع (جلسة لوحة المعلومات، ورمز CLI المحلي، وAccess Token بصيغة `oma_live_…`، ومفتاح API ذي نطاق الإدارة) وكيف تختلف عن مفاتيح الاستدلال. - تستخدم مسارات لوحة المعلومات (`/dashboard/*`) ملف تعريف الارتباط `auth_token` - يستخدم تسجيل الدخول تجزئة كلمة المرور المحفوظة؛ مع الرجوع إلى `INITIAL_PASSWORD` كخيار احتياطي - يمكن تبديل `requireLogin` عبر `/api/settings/require-login` - قد تتطلب مسارات `/v1/*` اختياريًا مفتاح API من نوع Bearer عندما تكون `REQUIRE_API_KEY=true` - يُقصد بعبارة "رمز الإدارة" / "مفتاح API ذي نطاق الإدارة" في هذا المرجع إحدى العائلات الواردة في ذلك الدليل — وليس نوعًا إضافيًا غير معرّف من الأسرار > **تغيير غير متوافق (v3.8.0)** — تتطلب الآن `/api/v1/agents/tasks/*` ونقاط نهاية إدارة فترة التهدئة **مصادقة الإدارة** (ملف تعريف الارتباط `auth_token` الخاص بلوحة المعلومات أو مفتاح API ذي نطاق الإدارة). ستتلقى البرامج العميلة التي كانت تستدعي هذه المسارات سابقًا من دون مصادقة الاستجابة `401 Unauthorized`. راجع الالتزام `588a0333` (`fix(auth): require management auth for agent and cooldown APIs`).