# OmniRoute Auto-Combo Engine (فارسی) 🌐 **Languages:** 🇺🇸 [English](../../../../routing/AUTO-COMBO.md) · 🇪🇹 [am](../../../am/docs/routing/AUTO-COMBO.md) · 🇸🇦 [ar](../../../ar/docs/routing/AUTO-COMBO.md) · 🇦🇿 [az](../../../az/docs/routing/AUTO-COMBO.md) · 🇧🇬 [bg](../../../bg/docs/routing/AUTO-COMBO.md) · 🇧🇩 [bn](../../../bn/docs/routing/AUTO-COMBO.md) · 🇧🇦 [bs](../../../bs/docs/routing/AUTO-COMBO.md) · 🇨🇿 [cs](../../../cs/docs/routing/AUTO-COMBO.md) · 🇩🇰 [da](../../../da/docs/routing/AUTO-COMBO.md) · 🇩🇪 [de](../../../de/docs/routing/AUTO-COMBO.md) · 🇬🇷 [el](../../../el/docs/routing/AUTO-COMBO.md) · 🇪🇸 [es](../../../es/docs/routing/AUTO-COMBO.md) · 🇪🇪 [et](../../../et/docs/routing/AUTO-COMBO.md) · 🇫🇮 [fi](../../../fi/docs/routing/AUTO-COMBO.md) · 🇫🇷 [fr](../../../fr/docs/routing/AUTO-COMBO.md) · 🇮🇪 [ga](../../../ga/docs/routing/AUTO-COMBO.md) · 🇮🇳 [gu](../../../gu/docs/routing/AUTO-COMBO.md) · 🇳🇬 [ha](../../../ha/docs/routing/AUTO-COMBO.md) · 🇮🇱 [he](../../../he/docs/routing/AUTO-COMBO.md) · 🇮🇳 [hi](../../../hi/docs/routing/AUTO-COMBO.md) · 🇭🇷 [hr](../../../hr/docs/routing/AUTO-COMBO.md) · 🇭🇺 [hu](../../../hu/docs/routing/AUTO-COMBO.md) · 🇦🇲 [hy](../../../hy/docs/routing/AUTO-COMBO.md) · 🇮🇩 [id](../../../id/docs/routing/AUTO-COMBO.md) · 🇳🇬 [ig](../../../ig/docs/routing/AUTO-COMBO.md) · 🇮🇹 [it](../../../it/docs/routing/AUTO-COMBO.md) · 🇯🇵 [ja](../../../ja/docs/routing/AUTO-COMBO.md) · 🇬🇪 [ka](../../../ka/docs/routing/AUTO-COMBO.md) · 🇰🇭 [km](../../../km/docs/routing/AUTO-COMBO.md) · 🇮🇳 [kn](../../../kn/docs/routing/AUTO-COMBO.md) · 🇰🇷 [ko](../../../ko/docs/routing/AUTO-COMBO.md) · 🇱🇹 [lt](../../../lt/docs/routing/AUTO-COMBO.md) · 🇱🇻 [lv](../../../lv/docs/routing/AUTO-COMBO.md) · 🇮🇳 [ml](../../../ml/docs/routing/AUTO-COMBO.md) · 🇮🇳 [mr](../../../mr/docs/routing/AUTO-COMBO.md) · 🇲🇾 [ms](../../../ms/docs/routing/AUTO-COMBO.md) · 🇲🇹 [mt](../../../mt/docs/routing/AUTO-COMBO.md) · 🇲🇲 [my](../../../my/docs/routing/AUTO-COMBO.md) · 🇳🇵 [ne](../../../ne/docs/routing/AUTO-COMBO.md) · 🇳🇱 [nl](../../../nl/docs/routing/AUTO-COMBO.md) · 🇳🇴 [no](../../../no/docs/routing/AUTO-COMBO.md) · 🇮🇳 [or](../../../or/docs/routing/AUTO-COMBO.md) · 🇮🇳 [pa](../../../pa/docs/routing/AUTO-COMBO.md) · 🇵🇭 [phi](../../../phi/docs/routing/AUTO-COMBO.md) · 🇵🇱 [pl](../../../pl/docs/routing/AUTO-COMBO.md) · 🇵🇹 [pt](../../../pt/docs/routing/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/routing/AUTO-COMBO.md) · 🇷🇴 [ro](../../../ro/docs/routing/AUTO-COMBO.md) · 🇷🇺 [ru](../../../ru/docs/routing/AUTO-COMBO.md) · 🇱🇰 [si](../../../si/docs/routing/AUTO-COMBO.md) · 🇸🇰 [sk](../../../sk/docs/routing/AUTO-COMBO.md) · 🇸🇮 [sl](../../../sl/docs/routing/AUTO-COMBO.md) · 🇷🇸 [sr](../../../sr/docs/routing/AUTO-COMBO.md) · 🇸🇪 [sv](../../../sv/docs/routing/AUTO-COMBO.md) · 🇰🇪 [sw](../../../sw/docs/routing/AUTO-COMBO.md) · 🇮🇳 [ta](../../../ta/docs/routing/AUTO-COMBO.md) · 🇮🇳 [te](../../../te/docs/routing/AUTO-COMBO.md) · 🇹🇭 [th](../../../th/docs/routing/AUTO-COMBO.md) · 🇹🇷 [tr](../../../tr/docs/routing/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/routing/AUTO-COMBO.md) · 🇵🇰 [ur](../../../ur/docs/routing/AUTO-COMBO.md) · 🇺🇿 [uz](../../../uz/docs/routing/AUTO-COMBO.md) · 🇻🇳 [vi](../../../vi/docs/routing/AUTO-COMBO.md) · 🇳🇬 [yo](../../../yo/docs/routing/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/routing/AUTO-COMBO.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/routing/AUTO-COMBO.md) --- > **برای کاربران**: بهدنبال شروعی سریع هستید؟ برای توضیحات و مثالهای ساده، [راهنمای کاربری Auto-Combo](../getting-started/AUTO-COMBO-GUIDE.md) را ببینید. > زنجیرههای مدل خودمدیریتشونده با امتیازدهی تطبیقی + مسیریابی خودکار بدون پیکربندی ## مسیریابی خودکار بدون پیکربندی (پیشوند `auto/`) > **جدید:** نیازی به ایجاد combo نیست. پیشوند `auto/` را مستقیماً در هر کلاینتی استفاده کنید. ### مثالهای سریع | شناسه مدل | گونه | رفتار | | -------------- | ------- | --------------------------------------------------------------- | | `auto` | پیشفرض | همه ارائهدهندگان متصل، راهبرد LKGP، وزنهای متعادل | | `auto/coding` | کدنویسی | وزنهای مبتنی بر اولویت کیفیت، مناسب برای تولید کد | | `auto/fast` | سریع | انتخاب وزندار با تأخیر کم | | `auto/cheap` | ارزان | مسیریابی بهینهشده از نظر هزینه (ابتدا کمترین هزینه) | | `auto/offline` | آفلاین | ارائهدهندگانی با بیشترین سهمیه در دسترس را ترجیح میدهد | | `auto/smart` | هوشمند | اولویت کیفیت + نرخ کاوش بالاتر (10٪) برای کشف بهتر مدلها | | `auto/lkgp` | lkgp | LKGP صریح (همان `auto` پیشفرض) | | `auto/chaos` | آشوب | توزیع موازی درخواستها، یک مدل برای هر ارائهدهنده (نه تزریق خطا) | ### ترکیب دستهبندی × سطح (`auto/:`) پسوندهای سبک OpenRouter، **نوع مسیر** (دستهبندی) را از **نحوه بهینهسازی آن** (سطح) جدا میکنند تا بتوانید آزادانه آنها را ترکیب کنید (#4235 Phase B، `open-sse/services/autoCombo/suffixComposition.ts`): - **دستهبندیها** (مجموعه نامزدها را بر اساس قابلیت فیلتر میکنند): `coding` · `reasoning` · `vision` · `chat` · `multimodal`. گزینههای `vision`/`multimodal` مدلهای دارای قابلیت بینایی را نگه میدارند؛ `reasoning` مدلهای استدلال/تفکر را نگه میدارد. - **سطوح** (وزنهای امتیازدهی / فیلتر مجموعه را انتخاب میکنند): `fast` (عرضه سریع) · `cheap` (نام مستعار `floor`، صرفهجویی در هزینه) · `reliable` (سلامت مدارشکن + پایداری تأخیر) · `free` / `pro` (فیلتر کردن مجموعه بر اساس سطح مدل از طریق `classifyTier` — سطح رایگان در برابر ممتاز). | مثال | نتیجه | | ---------------------- | ---------------------------------------------------------------------- | | `auto/coding:fast` | مجموعه کدنویسی، وزنهای با تأخیر کم | | `auto/coding:cheap` | مجموعه کدنویسی، بهینهشده از نظر هزینه (نام مستعار `auto/coding:floor`) | | `auto/reasoning:pro` | فقط مدلهای استدلال/تفکر، سطح ممتاز | | `auto/vision` | مدلهای دارای قابلیت بینایی (بدون سطح ← وزنهای متعادل) | | `auto/multimodal:free` | مدلهای دارای قابلیت چندوجهی، فقط سطح رایگان | هر الگوی معتبر `auto/[:]` در لحظه تفسیر میشود؛ یک زیرمجموعه منتخب در `/v1/models` و داشبورد اعلام میشود (`AUTO_SUFFIX_VARIANTS` در `open-sse/services/autoCombo/builtinCatalog.ts`). فیلتر کردن بهصورت **fail-open** است — اگر هیچ مدل متصلی با یک محدودیت مطابقت نداشته باشد، از کل مجموعه استفاده میشود تا مسیریابی هرگز مختل نشود. امتیازدهنده اصلی (`combo.ts`) بدون تغییر باقی میماند؛ فیلتر دستهبندی/سطح در `buildAutoCandidates` اعمال میشود. > **هوشمندی زنده مدل:** تناسب مسیریابی خودکار، هنگامی که پرچم `ARENA_ELO_SYNC_ENABLED` روشن باشد، از رتبهبندیهای زنده **Arena ELO** و دادههای سطح **models.dev** استفاده میکند (در غیر این صورت به نگاشت ایستای تناسب بازمیگردد). **نحوه استفاده:** ```bash # هر ابزار IDE یا CLI که از قالب OpenAI پشتیبانی میکند Base URL: http://localhost:20128/v1 API Key: # در کد/پیکربندی خود، مدل را به این صورت تنظیم کنید: model: "auto" # حالت پیشفرض متعادل model: "auto/coding" # بهترین گزینه برای وظایف کدنویسی model: "auto/fast" # سریعترین گزینه موجود model: "auto/cheap" # ارزانترین گزینه بهازای هر توکن ``` **چه اتفاقی میافتد:** 1. OmniRoute پیشوند `auto/` را در `src/sse/handlers/chat.ts` تشخیص میدهد 2. همه **اتصالهای فعال ارائهدهندگان** را از پایگاه داده واکشی میکند 3. مواردی را نگه میدارد که اعتبارنامه معتبر دارند (کلید API یا توکن OAuth) 4. مدل هر اتصال را تعیین میکند (`connection.defaultModel` یا اولین مدل ارائهدهنده) 5. یک **combo مجازی** در حافظه میسازد (در DB ذخیره نمیشود) 6. با استفاده از پروفایل وزن گونه انتخابشده + راهبرد LKGP مسیریابی میکند **ویژگیهای کلیدی:** - ✅ **همیشه فعال:** بدون نیاز به کلید تغییر وضعیت، ایجاد combo یا پیکربندی - ✅ **پویا:** ارائهدهندگان متصل فعلی را بهطور خودکار منعکس میکند - ✅ **چسبندگی نشست:** LKGP تضمین میکند آخرین ارائهدهنده موفق در اولویت قرار گیرد - ✅ **آگاه از چند حساب:** هر اتصال ارائهدهنده به یک نامزد جداگانه تبدیل میشود - ✅ **بدون نوشتن در DB:** combo مجازی فقط برای همان درخواست وجود دارد و سربار ماندگاری آن صفر است ### کنترل نامزدها بهازای هر کلید (#7819، سطح 1+2) `GET /v1/auto-combo/{channel}/candidates` (`{channel}` = پسوند پس از `auto/`، یا مقدار لفظی `auto` برای کانال پایه) یک نقطه پایانی **فقط خواندنی** است که مجموعه نامزدهای فعلی یک کانال `auto/*` را همراه با دسترسپذیری زنده فهرست میکند و خواندنهای موجود تابآوری را مجدداً بهکار میگیرد (و هرگز `state` خام مدارشکن را نمیخواند): - مدارشکن ارائهدهنده — `getCircuitBreaker(provider).getStatus()` / `.canExecute()` - دوره انتظار اتصال — `rateLimitedUntil` / `testStatus` در ردیف تفسیرشده `provider_connections` - قفل مدل — `isModelLocked(provider, connectionId, model)` هر نامزد همچنین پرچم `excluded` مربوط به این کلید API را دربر دارد. استثناها بهازای هر کلید API ذخیره میشوند (جدول `auto_candidate_overrides`، مهاجرت `128`) — OmniRoute تکمستأجری است و جدول `users` ندارد، بنابراین `apiKeyId` نزدیکترین هویت واقعی بهازای هر فراخواننده است — و در گلوگاه مجموعه نامزدها در `open-sse/services/autoCombo/virtualFactory.ts` از طریق تابع خالص و آزمونشده با تست واحد `filterExcludedCandidates()` (`open-sse/services/autoCombo/candidateOverrides.ts`) اعمال میشوند. این فیلتر بهصورت **fail-open** است: تنظیم نبودن apiKeyId/channel یا شکست در جستوجوی DB، هر دو مجموعه را بدون فیلتر باقی میگذارند؛ بنابراین اپراتوری که هیچ نادیدهگیریای برایش پیکربندی نشده باشد، مسیریابیای کاملاً یکسان در سطح بایت با پیش از این قابلیت مشاهده میکند. **به یک ایشوی پیگیری موکول شد:** وزندهی به هر کاندیدا + ترتیبدهی صریح (سطح 3 — به مسیرهای راهبرد وزندار/اولویتدار موجود وارد میشود) و پینکردن یک راهبرد مشخص `combo.ts` برای هر کانال `auto/*` (سطح 4). برای پرسش باز دربارهٔ اینکه با توجه به مدل تکمستأجری، بازنویسیها باید بهازای هر کلید API باقی بمانند یا سراسری شوند، به برنامهٔ #7819 مراجعه کنید. **پشت صحنه:** ```txt درخواست: { model: "auto/coding" } ↓ src/sse/handlers/chat.ts پیشوند را تشخیص میدهد ↓ createVirtualAutoCombo('coding') → candidatePool از اتصالهای فعال ↓ handleComboChat (همان موتور کمبوهای ذخیرهشده) ↓ امتیازدهی خودکار، بهترین ارائهدهنده/مدل را برای هر درخواست انتخاب میکند ``` **فایلهای پیادهسازی:** | فایل | هدف | | --------------------------------------------------------- | -------------------------------------------- | | `open-sse/services/autoCombo/autoPrefix.ts` | تجزیهکنندهٔ پیشوند (`parseAutoPrefix`) | | `open-sse/services/autoCombo/virtualFactory.ts` | اشیای مجازی `AutoComboConfig` را ایجاد میکند | | `open-sse/services/autoCombo/providerRegistryAccessor.ts` | هوک تست برای شبیهسازی رجیستری ارائهدهندگان | | `src/sse/handlers/chat.ts` | یکپارچهسازی: میانبُر پیشوند خودکار | | `src/shared/constants/providers.ts` | ورودی سیستمی `SYSTEM_PROVIDERS.auto` | ## نامهای Combo که با شناسه یک مدل واقعی مطابقت دارند یک combo که `name` آن با شناسه بدون پیشوند یک مدل یکسان است (برای مثال، comboای با نام `gpt-5.5`)، یک **الگوی عمدی و پشتیبانیشده** است، نه یک باگ: این همان سازوکار بازگشت به ارائهدهنده جایگزین برای هر شناسه مدل است که در [#6940](https://github.com/diegosouzapw/OmniRoute/issues/6940) مستند شده است. از آنجا که تفکیک combo پیش از تفکیک شناسه بدون پیشوند مدل بررسی میشود (`getComboForModel()` در `src/sse/services/model.ts`)، درخواست برای شناسه بدون پیشوند `gpt-5.5` بهجای اینکه مستقیماً به یک ارائهدهنده واحد هدایت شود، از طریق مقصدهای combo (برای مثال، `acme-responses/gpt-5.5` و `backup-responses/gpt-5.5`) مسیریابی میشود — این رفتار از اولویت combo پیش از بازنویسی که برای [#3227/#3233](https://github.com/diegosouzapw/OmniRoute/issues/3227) ساخته شده بود دوباره استفاده میکند و در برابر رگرسیون توسط `tests/unit/responses-combo-resolution-3227.test.ts` و `tests/unit/combo-name-codex-responses-rewrite.test.ts` آزمایش میشود. ایجاد یا تغییر نام یک combo به نامی که شناسه یک مدل واقعی را تحتالشعاع قرار میدهد **هرگز رد نمیشود** — انجام این کار گردشکار مستندشده را مختل میکند. در عوض (#8530)، `POST /api/combos` و `PUT /api/combos/[id]` هنگامی که نام (جدید) با شناسه یک مدل واقعی تداخل داشته باشد، یک فیلد غیرمسدودکننده `warning` به پاسخ اضافه میکنند: ```json { "warning": { "code": "COMBO_NAME_SHADOWS_MODEL", "modelId": "gpt-5.5", "providerId": "openai" } } ``` هنگام راهاندازی، `scanComboModelNameCollisionsAtBoot()` (`src/instrumentation-node.ts`) همچنین یک هشدار تکخطی `[STARTUP]` ثبت میکند که تمام comboهای موجودی را که یک شناسه مدل را تحتالشعاع قرار میدهند فهرست میکند؛ در نتیجه، اپراتورهایی که بهطور تصادفی با این وضعیت روبهرو شدهاند (و نه بهصورت عمدی، مطابق #6940)، نشانهای برای تشخیص آن خواهند داشت. تابع کمکی تشخیص در `src/lib/combos/modelNameCollision.ts` قرار دارد. ## فراخوانی یک Combo سفارشی از یک کلاینت comboهای ذخیرهشده (Settings → Combos) فقط زمانی استفاده میشوند که کلاینت **نام دقیق** combo را در فیلد `model` ارسال کند — هیچ تطبیق مبهم یا جزئی برای نام combo انجام نمیشود و پیشوند `auto/` نیز در کار نیست. ترتیب تفکیک (`getComboForModel()` در `src/sse/services/model.ts`): 1. تطبیق دقیق نام combo (`model: "my-combo"`)، 2. پیشوند `combo/` (`model: "combo/my-combo"`)، 3. نگاشتهای glob از مدل به combo (`/api/model-combo-mappings`). ```bash curl -X POST http://localhost:20128/v1/chat/completions \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"model":"my-combo","messages":[{"role":"user","content":"Hello"}]}' ``` دو اشتباه رایج: - **`auto` از comboهای شما استفاده نمیکند.** `auto`/`auto/*` مجموعه کاندیداهای بدون نیاز به پیکربندی خودش را ایجاد میکند و تنها در صورتی comboهای ذخیرهشده را بررسی میکند که یک combo دقیقاً `auto` نام داشته باشد (توصیه نمیشود). برای مسیریابی از طریق یک combo، نام دقیق آن را ارسال کنید — نه `auto`. - **`openrouter/auto` یک محصول واقعی و پولی OpenRouter است** ("Auto Best Available")، نه یک نام مستعار OmniRoute. این مورد، تنها ورودی مدل ایستای رجیستری OpenRouter (`open-sse/config/providers/registry/openrouter/index.ts`) است و هزینه آن جداگانه محاسبه میشود. برای حذف آن از مجموعههای `auto`، از Settings → Routing → Hide paid models استفاده کنید. برای سردرگمی اولیهای که این بخش مستند میکند، به [#7992](https://github.com/diegosouzapw/OmniRoute/issues/7992) و [#7111](https://github.com/diegosouzapw/OmniRoute/issues/7111) مراجعه کنید. ## نحوهٔ عملکرد (ترکیبهای خودکار ماندگار) موتور Auto-Combo با استفاده از یک **تابع امتیازدهی ۱۶عاملی** (تعریفشده در `open-sse/services/autoCombo/scoring.ts` ← `DEFAULT_WEIGHTS`) بهصورت پویا بهترین ارائهدهنده/مدل را برای هر درخواست انتخاب میکند. مجموع وزنهای پیشفرض برابر با `1.0` است؛ وزنهای سفارشی توسط `normalizeScoringWeights()` دوباره نرمالسازی میشوند. دو عامل از این شانزده عامل — `cacheAffinity` و `resetWindowAffinity` — وزن پیشفرض `0` دارند؛ `reliability` در `DEFAULT_WEIGHTS` وزن `0` دارد، اما وزن آن در بستههای عمومی `0.03` و در `reliability-first` برابر با `0.04` است؛ همچنین `quality` در بستهها وزن `0.02` دارد (در `quality-first` برابر با `0.03` است): بااینحال، این عوامل همچنان برای هر نامزد محاسبه میشوند و `cacheAffinity` خارج از امتیاز، حذف موارد تکراری کش پرامپت را کنترل میکند؛ بنابراین عوامل دارای وزن پیشفرض صفر، صرفاً بهطور پیشفرض در رأیگیری مشارکت نمیکنند، درحالیکه بستهها از آنها استفاده میکنند. ![امتیازدهی ۱۶عاملی Auto-Combo](../diagrams/exported/auto-combo-scoring.svg) > منبع: [diagrams/auto-combo-scoring.mmd](../diagrams/auto-combo-scoring.mmd) (بازسازی از طریق `npm run docs:render-diagrams`). نام فایل تاریخی است؛ منبع و نمودار رندرشده، هر ۱۶ عامل تعریفشده در `DEFAULT_WEIGHTS` را نمایش میدهند. | عامل | وزن پیشفرض | توضیحات | | :-------------------- | :--------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `quota` | 0.1429 | سهمیهٔ باقیمانده / ظرفیت آزاد محدودیت نرخ [0..1] | | `health` | 0.1605 | امتیاز سلامت از قطعکنندهٔ مدار (CLOSED=1.0، HALF_OPEN=0.5، OPEN=0.0) | | `costInv` | 0.1429 | معکوس هزینهٔ **ترکیبی** (۶۰٪ قیمت توکن ورودی + ۴۰٪ قیمت توکن خروجی، نرمالشده) — ارزانتر = امتیاز بالاتر | | `latencyInv` | 0.1143 | معکوس تأخیر p95، نرمالشده نسبت به مخزن — سریعتر = امتیاز بالاتر | | `taskFit` | 0.0762 | تناسب با نوع وظیفه (کدنویسی، بازبینی، برنامهریزی، تحلیل، اشکالزدایی، مستندسازی) | | `stability` | 0.0476 | پایداری مبتنی بر واریانس، حاصل از انحراف معیار تأخیر — نامزدی که زمان پاسخگوییاش نوسان دارد، امتیاز کمتری میگیرد | | `tierPriority` | 0.0476 | اولویت سطح حساب — Ultra=1.0، Pro=0.67، Standard=0.33، Free=0.0 | | `tierAffinity` | 0.0476 | میزان همخوانی میان سطح نامزد و سطح توصیهشده در مانیفست | | `specificityMatch` | 0.0476 | میزان تطابق میان میزان اختصاصیبودن درخواست (راهنمای مانیفست) و سطح مدل | | `contextAffinity` | 0.0476 | میزان همخوانی میان نیاز درخواست به پنجرهٔ زمینه و پنجرهٔ زمینهٔ مدل | | `sessionAvailability` | 0.0476 | دسترسپذیری نشست OAuth برای اتصال نامزد در این نشست (`getOAuthSessionAvailability()`؛ اتصالهای غیر OAuth امتیاز 1.0 میگیرند) | | `connectionDensity` | 0.0476 | بار را میان اتصالهای متعلق به یک ارائهدهنده توزیع میکند (ضد تمرکز) | | `cacheAffinity` | 0.00 | همخوانی هش rendezvous با اتصالی که بهاحتمال زیاد پیشوند کش پرامپت این درخواست را از قبل در اختیار دارد (`open-sse/services/combo/promptCacheAffinity.ts`)؛ بهطور پیشفرض غیرفعال است (#8008) | | `resetWindowAffinity` | 0.00 | گرایش به اتصالهایی که بازهٔ بازنشانی سهمیهٔ مطلوبی دارند (بهطور پیشفرض غیرفعال است) | | `quality` | 0.03 | سیگنال کیفیت خروجی مبتنی بر بازخورد از ردیاب کیفیت رویدادهای مسیریابی؛ نامزدهای فاقد مشاهده، مقدار خنثی 0.5 دریافت میکنند | | `reliability` | 0.00 | سهم موفقیت مشاهدهشده، `1 - failureRate`، بر اساس ۲۴ ساعت سابقهٔ استفاده و مشروط به حداقل ده نمونه (در غیر این صورت، معیارهای بلادرنگ)؛ نامزدهای فاقد مشاهده، مقدار 1.0 میگیرند. بهطور پیشفرض غیرفعال است | `quality` (`open-sse/services/routing/quality.ts`): `cold restart → ∅`; `observations = 0 → score 0.5`. **مجموع:** `0.1429 + 0.1605 + 0.1429 + 0.1143 + 0.0762 + (7 × 0.0476) + 0.00 + 0.00 + 0.03 + 0.00 = 1.0`، همانگونه که در `DEFAULT_WEIGHTS` اعلام شده است؛ وزنهای پیکربندیشده توسط کاربر، پیش از امتیازدهی و بهوسیلهٔ `normalizeScoringWeights()` مجدداً به یک توزیع نرمالسازی میشوند. ## بستههای حالت ۶ پروفایل وزن از پیش تعریفشده در `open-sse/services/autoCombo/modePacks.ts` وجود دارد. هر بسته، وزنهای پیشفرض را بهطور کامل جایگزین میکند تا انتخاب را بهسمت یک هدف خاص سوق دهد. مجموع وزنهای هر بسته از قبل برابر با `1.0` است (در نمایش با چهار رقم اعشار، `0.9999`)، بنابراین وقتی بستهای فعال است، `normalizeScoringWeights()` عملاً مقدار معناداری برای اصلاح ندارد — مقادیر زیر، با در نظر گرفتن گرد کردن، همان مقادیری هستند که امتیازدهنده اعمال میکند. | عامل | ship-fast | cost-saver | quality-first | offline-friendly | reliability-first | chaos-mode | | :-------------------- | :--------- | :--------- | :------------ | :--------------- | :---------------- | :--------- | | `quota` | 0.1133 | 0.1133 | 0.0752 | **0.3324** | 0.1133 | 0.0376 | | `health` | 0.2667 | 0.1810 | 0.1714 | 0.2667 | **0.3524** | **0.4000** | | `costInv` | 0.0276 | **0.3324** | 0.0276 | 0.0752 | 0.0181 | 0.0140 | | `latencyInv` | **0.3048** | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0186 | | `taskFit` | 0.0952 | 0.0952 | **0.3524** | 0.0000 | 0.0952 | 0.1905 | | `stability` | 0.0000 | 0.0476 | 0.1429 | 0.0952 | 0.1905 | 0.1714 | | `tierPriority` | 0.0376 | 0.0376 | 0.0276 | 0.0376 | 0.0276 | 0.0040 | | `tierAffinity` | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | | `specificityMatch` | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | | `contextAffinity` | 0.0095 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0186 | | `sessionAvailability` | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | | `resetWindowAffinity` | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | | `connectionDensity` | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | | `quality` | 0.02 | 0.02 | **0.03** | 0.02 | 0.02 | 0.02 | | `reliability` | 0.03 | 0.03 | 0.03 | 0.03 | **0.04** | 0.03 | نکات: - **بستهها شامل `quality` و `reliability` هستند** (`quality 0.02`، در `quality-first` برابر با `0.03`؛ `reliability 0.03`، در `reliability-first` برابر با `0.04`) و کل نگاشت وزنها را جایگزین میکنند (`weights = pack`، نه ادغام). `DEFAULT_WEIGHTS` شامل `quality 0.03 / reliability 0` است؛ انتخاب `balanced`/`default` این مقادیر پیشفرض را حفظ میکند و انتخاب یک بسته از مقادیر همان بسته در بالا استفاده میکند. در یک مخزن سرد (هنوز هیچ مشاهدهای وجود ندارد، بنابراین `quality 0.5` و `reliability 1` است)، این دو عامل در یک بسته عمومی مقدار `+0.04` (`0.03 + 0.01`)، در `quality-first` مقدار `+0.045` و در `reliability-first` مقدار `+0.05` اضافه میکنند. - مقادیر `tierAffinity`، `specificityMatch` و `resetWindowAffinity` در تمام بستهها صراحتاً برابر با `0` هستند. - تأکید هر بسته در یک نگاه: - **ship-fast** → latencyInv 0.3048 + health 0.2667 (اتصالهای سالم با تأخیر کم) - **cost-saver** → costInv 0.3324 (ارزانترین توکنها برنده میشوند) - **quality-first** → taskFit 0.3524 + stability 0.1429 + quality 0.03، بالاترین مقدار در میان همه بستهها (بهترین مدل برای وظیفه، با عملکرد پایدار) - **offline-friendly** → quota 0.3324 + health 0.2667 (بیشترین ظرفیت آزاد، بدون توجه به سرعت/هزینه) - **reliability-first** → health 0.3524 + stability 0.1905 + reliability 0.04، بالاترین مقدار در میان همه بستهها (کمترین رفتار غیرمنتظره) - **chaos-mode** → health 0.4000 + taskFit 0.1905 (بسته وزنی که `auto/chaos` به اعضای پنل خود اختصاص میدهد؛ توزیع موازی درخواستها این وزنها را نمیخواند و این یک پروفایل تزریق خطا نیست؛ [CHAOS-MODE.md](../guides/CHAOS-MODE.md#autochaos-parallel-fan-out) را ببینید) ### کنترلهای هر درخواست (هدرها) — #6023 / #6024 / #6025 / #3470 یک ترکیب `auto` را میتوان **برای هر درخواست** از طریق سه هدر هدایت کرد، بدون اینکه پیکربندی ذخیرهشده ترکیب تغییر کند. این موارد فقط برای استراتژی `auto` و تنها برای درخواستی اعمال میشوند که آنها را همراه دارد؛ وقتی هدر وجود نداشته باشد، از `modePack`/`budgetCap`/`budgetFallback` ذخیرهشده ترکیب استفاده میشود. | هدر | مقادیر پذیرفتهشده | اثر | | :---------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `X-OmniRoute-Mode` | یک نام مستعار از پیش تعیینشده (`fast`، `balanced`، `quality`، `cheap`، `reliable`، `offline`) یا نام خام یک بسته (`ship-fast`، `cost-saver`، `quality-first`، `offline-friendly`، `reliability-first`) | وزنهای امتیازدهی را برای این درخواست بازنویسی میکند. `balanced`/`default` وزنهای پیشفرض را اعمال میکنند (بدون بسته). مقادیر ناشناخته نادیده گرفته میشوند (پیکربندی حفظ میشود). | | `X-OmniRoute-Budget` | یک عدد مثبت (حداکثر دلار آمریکا بهازای هر درخواست) | سقف قطعی هزینه: گزینههایی که هزینهٔ تخمینی آنها از این مقدار بیشتر باشد، پیش از انتخاب فیلتر میشوند. وقتی **همهٔ** گزینهها از این مقدار فراتر بروند، رفتار سیستم توسط `X-OmniRoute-Budget-Fallback` در ادامه تعیین میشود. | | `X-OmniRoute-Budget-Fallback` | `cheapest` (پیشفرض، نامهای مستعار: `cheapest-viable`، `soft`) یا `strict` (نامهای مستعار: `block`، `hard`) | `cheapest`: حتی اگر گزینه همچنان از سقف هزینه فراتر برود، به ارزانترین گزینه در کل بازمیگردد (رفتار قدیمی). `strict`: از انتخاب خودداری میکند — درخواست بهجای هزینهکرد بیسروصدا و بیشازحد، بلافاصله با `HTTP 402` شکست میخورد. مقادیر ناشناخته نادیده گرفته میشوند. | | `X-OmniRoute-Effort` | `auto` (سایر مقادیر رزرو شدهاند) | بودجهٔ تفکر تطبیقی: وقتی درخواست **هیچ** فیلد استدلالی با هیچ ساختاری (`reasoning_effort`، `reasoning`، `thinking`) نداشته باشد، درگاه مقدار `auto` را بر اساس سیگنالهای قطعیِ ساختار درخواست (طول آخرین پیام کاربر، اندازهٔ زمینه تا آخرین پیام کاربر، نتایج قبلی ابزارها، عمق حلقهٔ ابزار) به `low`/`medium`/`high` تبدیل میکند. سیگنالها به نوبت جاری محدود میشوند — هر چیزی پس از آخرین پیام کاربر نادیده گرفته میشود — بنابراین هر درخواست در یک حلقهٔ ابزار به سطح یکسانی تبدیل میشود (تثبیت بدونحالت در هر نوبت، بدون وضعیت نشست و بدون افزایش سطح در میانهٔ حلقه که پیشوندهای کش پرامپت بالادستی را مختل کند). فیلد استدلال صریح کلاینت همیشه اولویت دارد. این رفتار محدود به درخواستهایی است که ارسال بالادستی آنها به ساختار OpenAI Chat Completions تبدیل میشود (`targetFormat === FORMATS.OPENAI`) — `reasoning_effort` فیلدی با ساختار OpenAI است، بنابراین این هدر در درخواستهای مقصد Claude یا Gemini هیچ اثری ندارد (به `open-sse/handlers/chatCore/adaptiveEffortWiring.ts` مراجعه کنید). | ```bash # سریعترین پروفایل را اعمال کن، هزینهٔ این درخواست را به $0.05 محدود کن و بهجای هزینهکرد بیشازحد، آن را بهطور کامل مسدود کن curl -sS http://localhost:20128/v1/chat/completions \ -H "Content-Type: application/json" \ -H "X-OmniRoute-Mode: fast" \ -H "X-OmniRoute-Budget: 0.05" \ -H "X-OmniRoute-Budget-Fallback: strict" \ -d '{"model":"auto","messages":[{"role":"user","content":"hi"}]}' ``` تفکیک مقادیر یک تابع خالص است (`open-sse/services/autoCombo/requestControls.ts`)؛ مقادیر تفکیکشده به ورودیهای موجود `config.modePack` / `config.budgetCap` / `config.budgetFallback` موتور داده میشوند. مقدار ذخیرهشدهٔ `config.budgetFallback` در یک ترکیب ("strict" | "cheapest") خطمشی پایدار را تعیین میکند؛ هدر آن را برای یک درخواست منفرد بازنویسی میکند. ## همهٔ راهبردهای مسیریابی موتور ترکیبی OmniRoute از **20 راهبرد مسیریابی** پشتیبانی میکند (تعریفشده در `src/shared/constants/routingStrategies.ts` ← `ROUTING_STRATEGY_VALUES`). خود موتور Auto Combo تحت راهبرد `auto` ارائه میشود؛ سایر راهبردها برای ترکیبهای ذخیرهشده در دسترس هستند. | راهبرد | توضیحات | | :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `priority` | فهرست مرتبشده بر اساس هدف نخست، با اولویت صریح | | `weighted` | انتخاب تصادفی وزندار بر اساس وزن هر هدف | | `round-robin` | گردش میان هدفها بهترتیب (بهصورت دستهای؛ پایین را ببینید) | | `context-relay` | انتقال زمینه میان هدفها (برای گفتگوهای طولانی) | | `fill-first` | تکمیل سهمیهٔ هر هدف پیش از رفتن به هدف بعدی | | `p2c` | متعادلسازی بار تصادفی با روش توانِ انتخاب از میان ۲ گزینه | | `random` | انتخاب تصادفی یکنواخت | | `least-used` | انتخاب هدفی با کمترین بار فعلی | | `cost-optimized` | کمینهسازی هزینهٔ دلاری هر درخواست با توجه به قیمتگذاری کاتالوگ | | `reset-aware` ⭐ | اولویتبندی بر اساس زمان بازنشانی سهمیه — پنجرههای بازنشانی کوتاهتر در رتبهٔ بالاتر قرار میگیرند | | `reset-window` | ترجیح هدفهایی که پنجرهٔ سهمیهشان زودتر بازنشانی میشود | | `headroom` | انتخاب هدفی که بیشترین ظرفیت باقیمانده در سهمیه را دارد | | `quota-weighted` | صرفنظر از حسابهای دارای سهمیهٔ تمامشده، سپس انتخاب از میان بقیه متناسب با سهمیهٔ باقیمانده تقسیم بر بارِ در حال پردازش؛ گفتگوهای موجود به هدف خود متصل میمانند | | `strict-random` | انتخاب تصادفی بدون حذف موارد تکراری | | `auto` | استفاده از امتیازدهی Auto Combo (با 16 عامل) — **توصیهشده** | | `lkgp` | آخرین مسیر سالم شناختهشده (اتصال به آخرین ارائهدهندهٔ موفق و سپس بازگشت به قواعد در صورت شکست) | | `context-optimized` | انتخاب هدفی که بهترین تناسب را با اندازهٔ فعلی زمینه دارد | | `cache-optimized` | مرتبسازی مجدد هدفها بر اساس نزدیکی به کش پرامپت — اتصالی که بهاحتمال زیاد پیشوند کششدهٔ این درخواست را در اختیار دارد، ابتدا امتحان میشود (`open-sse/services/combo/promptCacheAffinity.ts`، #8008) | | `fusion` 🧬 | ارسال همزمان درخواست به مجموعهای از مدلها، سپس ترکیب پاسخها در یک پاسخ واحد توسط یک داور (پایین را ببینید) | | `pipeline` | اجرای متوالی هدفها و انتقال خروجی هر مرحله به ورودی مرحلهٔ بعد؛ فقط پاسخ نهایی بازگردانده میشود (#6396) | ⭐ = جدید در v3.8.0 · 🧬 = جدید در v3.8.36 ### معناشناسی `weighted` `weighted` یک **قرعهکشی تصادفی متناسب برای هر درخواست** است (`open-sse/services/combo/targetSorters.ts` ← `selectWeightedTarget`)، نه یک همترازکننده: - هر درخواست **یک** مرحله را با احتمال `weight / totalWeight` انتخاب میکند؛ مراحل باقیمانده بر اساس وزن نزولی بهعنوان زنجیرهٔ جایگزین آن درخواست مرتب میشوند. - مرحلهای که وزن آن `0` است (یا وزنی ندارد)، تا زمانی که مرحلهٔ دیگری وزن > 0 داشته باشد، **هرگز انتخاب نمیشود** — این مرحله فقط پس از شکست مرحلهٔ انتخابشده میتواند بهعنوان جایگزین عمل کند. تنها زمانی که **همهٔ** وزنها 0 باشند، انتخاب یکنواخت میشود. - مراحلی که همهٔ هدفهایشان در دسترس نیستند — مدارشکن ارائهدهنده در وضعیت `OPEN`، دورهٔ انتظار اتصال، قفلشدن مدل — پیش از انجام قرعهکشی حذف میشوند (`open-sse/services/combo/targetResolution.ts`)، بنابراین یک مرحلهٔ سالم میتواند موقتاً در همهٔ درخواستها انتخاب شود. - `stickyWeightedLimit` (پیکربندی ترکیب، مقدار پیشفرض `1` = غیرفعال) مرحلهٔ انتخابشده را برای همین تعداد موفقیت متوالی ثابت نگه میدارد و سپس دوباره قرعهکشی میکند. برای چرخش سختگیرانه از `round-robin` استفاده کنید؛ وزنهای برابر در `weighted` توازنی آماری — و نه سختگیرانه — ایجاد میکنند. ### حالت خط لوله عاملمحور یک ترکیب `pipeline` با حداقل دو مدل میتواند با استفاده از `config.agenticOrchestration.enabled` مسیریابی برنامهریز/اجراکننده را فعال کند. هدف نخست مالک برنامهریزی و پاسخهای نهایی است؛ هدف دوم فراخوانیهای ابزار را در قالب بومی کلاینت تولید میکند. OmniRoute ادامههای نتیجه ابزار را از پروتکل درخواست تشخیص میدهد، از برنامهریز میپرسد آیا دور دیگری از ابزار لازم است یا خیر، و بهصورت پویا اجراکننده یا برنامهریز را بهعنوان مرحله نهایی روبهروی کلاینت انتخاب میکند. مدلهای اضافی پس از هدف دوم، پشتیبانهای اجراکننده هستند و بهترتیب استفاده میشوند. یک پاسخ HTTP ناموفق یا استثنای انتقال باعث رفتن به اجراکننده بعدی میشود، درحالیکه همان تصمیم برنامهریز و ابزارهای بومی حفظ میشوند، اما اعلان مرحله و اتصال حلشده خود آن اجراکننده به کار میروند. نخستین پاسخ موفق بدون تغییر بازگردانده میشود، از جمله جریان SSE؛ خرابیهای پس از شروع یک جریان موفق را نمیتوان در اینجا دوباره امتحان کرد. اگر همه اجراکنندهها ناموفق باشند، آخرین خطا بازگردانده میشود. لغو توسط کلاینت، ارسال را متوقف میکند. ```json { "strategy": "pipeline", "models": [{ "model": "provider/planner" }, { "model": "provider/executor" }], "config": { "agenticOrchestration": { "enabled": true, "maxToolRounds": 8 } } } ``` اجراکننده میتواند در یک پاسخ، چند فراخوانی مستقل تولید کند. فراخوانیهای وابسته در نوبتهای بعدی نتیجه ابزار کلاینت مدیریت میشوند و برنامهریز هر نتیجه را بررسی میکند. مقدار پیشفرض `maxToolRounds` برابر با `8` است و مقادیر `1` تا `32` را میپذیرد؛ پس از رسیدن به این حد، برنامهریز باید بهترین پاسخ نهایی موجود را تولید کند. تصمیمهای داخلی برنامهریز در بافر نگهداری میشوند، درحالیکه پاسخ انتخابشده روبهروی کلاینت، ترجیح اصلی جریانسازی را حفظ میکند. ### دستهبندی چسبنده `round-robin` و گسترش حساب روش نوبتگردشی بهصورت دستهای عمل میکند، نه یک درخواست در هر مرحله: - `stickyRoundRobinLimit` (ابتدا پیکربندی ترکیب، سپس `comboStickyRoundRobinLimit`، سپس `settings.stickyRoundRobinLimit`، با مقدار پیشفرض **3**) همان هدف را برای این تعداد موفقیت متوالی حفظ میکند و سپس میچرخد. برای چرخش بهازای هر درخواست، بازنویسی ترکیب را روی `1` تنظیم کنید. ویرایشگر ترکیب، مقدار مؤثر و لایهای را که مقدار از آن آمده است نمایش میدهد. - `connectionAwareExpansion` (ابتدا پیکربندی ترکیب، سپس تنظیمات، با مقدار پیشفرض **false**)، هر مرحله در سطح ارائهدهنده را پیش از چرخش به هدفهای جداگانه برای هر حساب گسترش میدهد. راهبردهای گروه B (اولویت، وزندار، نوبتگردشی، تصادفی، p2c، کماستفادهترین، بهینهشده برای هزینه، lkgp، پرکردن اولین، تصادفی سختگیرانه، بهینهشده برای بافت، بهینهشده برای کش، رله بافت، ادغام، خط لوله) تا زمانی که این گزینه فعال نشود، نمای سطح ارائهدهنده را حفظ میکنند. ویرایشگر ترکیب گزینههای ارثبری / روشن / خاموش را ارائه میدهد؛ ارثبری از مقدار پیشفرض سراسری (خاموش) استفاده میکند. - مسیریابی بر اساس نزدیکی کش اعلان (`promptCacheAffinityEnabled`، با مقدار پیشفرض **true**) ترتیب اتصالهای سنجاقشده را تغییر میدهد تا کلیدهای کش منطبق روی یک حساب باقی بمانند. این قابلیت بر چرخش نوبتگردشی و وزندار میان مراحل سنجاقشده هر حساب اولویت دارد. اگر به چرخش سختگیرانه نیاز دارید، آن را در Settings → Combo defaults خاموش کنید. هیچ بازنویسی جداگانهای برای هر ترکیب وجود ندارد. برای چرخش چندحسابی روی یک مدل، **یک مرحله حساب پویا** (`connectionId` خالی، کل مجموعه) با حد چسبندگی `1` را به سه `connectionId` سنجاقشده ترجیح دهید. مراحل سنجاقشده همراه با نزدیکی، حتی زمانی که شمارنده RR جلو میرود، همگی روی یک حساب متمرکز میشوند. ## راهبرد Fusion `fusion` تنها راهبردی است که یک مقصد واحد را انتخاب **نمیکند**. این راهبرد پرامپت را بهصورت موازی به **تمام مدلهای پنل** ارسال میکند و سپس یک **مدل داور** قابلپیکربندی، از همه پاسخهای پنل یک پاسخ نهایی واحد میسازد. این قابلیت از `decolua/9router` بالادستی (طراحی Fusion متعلق به OpenRouter) منتقل شده است؛ پیادهسازی آن در `open-sse/services/fusion.ts` قرار دارد. نحوه کار: 0. **عبور مستقیم درخواستهای دارای ابزار** — درخواستی که یک آرایه غیرخالی `tools` داشته باشد و مقدار `tool_choice` آن صراحتاً `"none"` نباشد، پنل را کاملاً کنار میگذارد: درخواست مستقیماً به یک مدل واحد (داور پیکربندیشده یا `panel[0]`) هدایت میشود و `tools`/`tool_choice` بدون تغییر عبور داده میشوند. اعضای پنل به ابزارها دسترسی ندارند و دستورالعمل ترکیب پاسخِ داور، تولید فراخوانی ابزار را منع میکند؛ بنابراین کلاینتهای عاملی/فراخواننده ابزار بهجای متن ترکیبشده، یک تصمیم واقعی برای فراخوانی ابزار دریافت میکنند (#6771). 1. **ارسال همزمان** (فقط برای درخواستهای بدون ابزار) — پرامپت بهطور همزمان به همه مدلهای پنل ارسال میشود؛ حالت غیرجریانی بهاجبار فعال و ابزارها حذف میشوند (داور برای ترکیب پاسخ به متن کامل نیاز دارد). 2. **گردآوری با حد نصاب و مهلت** — بهمحض رسیدن `minPanel` پاسخ، یک زمانسنج کوتاه برای مدلهای عقبمانده آغاز میشود؛ سپس Fusion با هر تعداد پاسخی که گردآوری شده است ادامه میدهد. این کار تأثیر کندترین مدل بر زمان سپریشده را محدود میکند و یک مهلت نهایی سخت نیز آن را کراندار نگه میدارد. 3. **ترکیب توسط داور** — پاسخهای پنل ناشناسسازی میشوند (`Source 1`، `Source 2`، … — تا داور محتوا را بسنجد، نه برند مدل) و در اختیار داور قرار میگیرند. داور توافقها / تناقضها / پوشش ناقص / بینشهای منحصربهفرد / نقاط کور را تحلیل میکند و سپس **یک** پاسخ معتبر مینویسد. فراخوانی داور، پرچم اصلی `stream` کلاینت و ابزارها را حفظ میکند؛ بنابراین پخش جریانی و استفاده پاییندستی از ابزارها همچنان کار میکنند. 4. **افت تدریجی و کنترلشده** — ۰ پاسخ پنل ← `503`؛ دقیقاً ۱ پاسخ باقیمانده ← همان پاسخ مستقیماً برگردانده میشود (چیزی برای ترکیب وجود ندارد)؛ پنلی با یک مدل نیز مستقیماً پاسخ میدهد. یکی از اعضای پنل میتواند یک مرحله `combo-ref` نیز باشد (`{kind: "combo-ref", comboName: "..."}`) که به ترکیب دیگری ارجاع میدهد — این مرحله بهعنوان **یک صدای مستقل و جعبهسیاه در پنل** حل میشود (یک ارسال بازگشتی کامل به ترکیب مورد ارجاع، نه ارسال همزمان به مقصدهای خود آن ترکیب)، با همان محافظت در برابر عمق/چرخه که همه راهبردهای دیگرِ مصرفکننده combo-ref از آن استفاده میکنند (#6764). ### پیکربندی پیکربندی در داده `config` ترکیب انجام میشود (بدون مهاجرت طرحواره — از جدول موجود `combos` دوباره استفاده میکند): | فیلد | نوع | پیشفرض | هدف | | :--------------------------------------- | :------- | :------------ | :------------------------------------------------------------------------------ | | `config.judgeModel` | `string` | اولین مدل پنل | مدلی که پاسخ نهایی را ترکیب میکند | | `config.fusionTuning.minPanel` | `number` | `2` | تعداد پاسخهای موفق لازم پیش از شروع زمانسنج مهلت (محدودشده به `[2, panelSize]`) | | `config.fusionTuning.stragglerGraceMs` | `number` | `8000` | مدت انتظار برای مدلهای عقبمانده پس از رسیدن به حد نصاب | | `config.fusionTuning.panelHardTimeoutMs` | `number` | `90000` | سقف مطلق برای جلوگیری از اینکه یک مدل متوقفشده، درخواست را معطل کند | مقادیر پیشفرض در `FUSION_DEFAULTS` (`open-sse/services/fusion.ts`) قرار دارند. ### مثال ```bash curl -X POST http://localhost:20128/api/combos \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "fusion-panel", "strategy": "fusion", "targets": [ { "model": "cc/claude-opus-4-7" }, { "model": "cx/gpt-5.5" }, { "model": "glm/glm-5.1" } ], "config": { "judgeModel": "cc/claude-opus-4-7", "fusionTuning": { "minPanel": 2, "stragglerGraceMs": 8000, "panelHardTimeoutMs": 90000 } } }' ``` سپس آن را مانند هر ترکیب دیگری فراخوانی کنید: `{"model":"fusion-panel","messages":[...]}`. ## کارخانهٔ مجازی Auto-Combo موتور Auto Combo به کمبوهای ازپیشتعریفشده نیازی ندارد. در عوض، `open-sse/services/autoCombo/virtualFactory.ts` کاندیداها را بهصورت پویا میسازد: 1. `getProviderConnections({ isActive: true })` را دریافت میکند (همهٔ اتصالهای فعال) 2. مواردی را که اعتبارنامهٔ معتبر دارند فیلتر میکند (کلید API یا توکن OAuth منقضینشده از طریق `hasUsableOAuthToken()`) 3. برای بررسی دسترسپذیری مدل و قیمتگذاری، آنها را با `getProviderRegistry()` تطبیق میدهد 4. برای هر سهتایی `(provider, model, connection)`، یک `VirtualAutoComboCandidate` میسازد 5. `connection.defaultModel` (یا اولین مدل رجیستری) را بهعنوان مقصد ارسال انتخاب میکند 6. هر کاندیدا را با استفاده از `scorePool()` شانزدهعاملی و بستهٔ وزن آن واریانت امتیازدهی میکند 7. `AutoComboConfig` حاصل را که در حافظه قرار دارد، برای `handleComboChat()` برمیگرداند — و هرگز آن را در DB ذخیره نمیکند این یعنی **افزودن یک ارائهدهندهٔ جدید که `auto/*` برای آن فعال است، بهطور خودکار مجموعهٔ کاندیداها را گسترش میدهد** — و نیازی به ویرایش دستی کمبو نیست. کمبوی مجازی برای هر درخواست از نو ساخته میشود، بنابراین اتصالهایی که بهتازگی اضافه شدهاند یا دوباره سالم شدهاند، بلافاصله در نظر گرفته میشوند. ## خودترمیمی - **حذف موقت**: امتیاز < 0.2 ← حذف بهمدت ۵ دقیقه (عقبنشینی تدریجی، حداکثر ۳۰ دقیقه) - **آگاهی از قطعکنندهٔ مدار**: OPEN ← حذف خودکار؛ HALF_OPEN ← درخواستهای آزمایشی - **حالت رخداد**: بیش از ۵۰٪ OPEN ← غیرفعالکردن کاوش و بهحداکثررساندن پایداری - **بازیابی پس از دورهٔ انتظار**: پس از پایان حذف، اولین درخواست یک «آزمایش» با زمانانتظار کاهشیافته است ## کاوش Bandit ۵٪ از درخواستها (قابل پیکربندی) برای کاوش به ارائهدهندگان تصادفی هدایت میشوند. این قابلیت در حالت رخداد غیرفعال است. ## API هیچ **اندپوینت اختصاصی `POST /api/combos/auto` وجود ندارد** — Auto-Combo به دو روش استفاده میشود: 1. **بدون پیکربندی (پیشنهادی):** هر درخواست تکمیل چت را با `model: "auto"` یا `model: "auto/"` ارسال کنید. کارخانهٔ مجازی برای هر درخواست، کمبو را میسازد — نیازی به ماندگاری یا فراخوانی API نیست. 2. **کمبوی ماندگار با `strategy: "auto"`:** از طریق `POST /api/combos` یک کمبوی معمولی ایجاد کنید و `strategy: "auto"` را بههمراه `config.auto.weights` / `config.auto.candidatePool` تنظیم کنید. همان موتور امتیازدهی استفاده میشود؛ کمبو در `combos` ذخیره شده و از طریق شناسه قابل استفادهٔ مجدد است. برای کشف، `GET /api/combos/auto` همهٔ گونهها را همراه با مجموعهٔ کاندیداهای نهاییشان و نیز `context_length` / `max_output_tokens` فهرست میکند — یعنی مقدار MAX در میان پنجرههای مجموعهٔ کاندیداها. کلاینتها (برای مثال افزونهٔ opencode) باید این مقادیر را بهجای `0` اعلام کنند: کانتکست صفر، فشردهسازی خودکار opencode را بهطور کامل غیرفعال میکند و اجازه میدهد نشستها آنقدر رشد کنند تا پاکسازی تاریخچه توسط درگاه، کانتکست را از بین ببرد. اعلام MAX ایمن است، زیرا پیشفیلتر کانتکست Auto-Combo درخواستهای بیشازحد بزرگ را به کاندیداهایی با پنجرهٔ بزرگ هدایت میکند. ```bash # استفاده بدون پیکربندی (بدون ایجاد کمبو) curl -X POST http://localhost:20128/v1/chat/completions \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"model":"auto/coding","messages":[{"role":"user","content":"Hello"}]}' # کمبوی خودکار ماندگار از طریق اندپوینت معمولی کمبوها curl -X POST http://localhost:20128/api/combos \ -H "Content-Type: application/json" \ -d '{"id":"my-auto","name":"Auto Coder","strategy":"auto","config":{"auto":{"candidatePool":["anthropic","google","openai"],"weights":{"quota":0.15,"health":0.3,"costInv":0.05,"latencyInv":0.35,"taskFit":0.1,"stability":0,"tierPriority":0.05}}}}' ``` ### راهبردهای مسیریاب خودکار کمبوهای ماندگار با `strategy: "auto"` میتوانند `config.routerStrategy` (یا شکل قدیمی `config.auto.routerStrategy`) را روی یکی از موارد زیر تنظیم کنند: - `rules` — امتیازدهی وزنی پیشفرض - `score` — بالاترین امتیاز وزنی پیکربندیشده را انتخاب میکند. در تساویهای دقیق، ترتیب پیکربندیشدهٔ کاندیداها حفظ میشود؛ `explorationRate` موجود از کل مجموعهٔ رتبهبندیشده نمونهبرداری میکند. - `cost` / `eco` — ارزانترین ارائهدهندهٔ سالم - `latency` / `fast` — کمترین تأخیر p95 با جریمهٔ قابلیت اطمینان - `sla-aware` / `sla` — کاندیداهایی را ترجیح میدهد که SLOهای تأخیر p95، نرخ خطا و در صورت وجود هزینه را برآورده کنند - `lkgp` — ابتدا آخرین ارائهدهندهٔ سالم شناختهشده - `nadir` — از API تصمیمگیری [Nadir](https://getnadir.com) میپرسد پرامپت به کدام مدل در مجموعه نیاز دارد؛ بهصورت انتخابی فعال میشود و در صورت شکست به `rules` بازمیگردد ### جزئیات راهبردهای مسیریاب موتور Auto-Combo هفت پیادهسازی قابلتعویض **RouterStrategy** را ارائه میکند که میتوانید از طریق `config.routerStrategy` (یا شکل قدیمی `config.auto.routerStrategy`) آنها را تعویض کنید. هر راهبرد با توجه به یک `RoutingContext`، یک ارائهدهنده را از مجموعهٔ کاندیداها انتخاب میکند (نوع وظیفه، نشانههای ابزار/بینایی، تخمین توکن، سیاست اختیاری SLA و ارائهدهندهٔ اختیاری آخرینبار-سالم). #### 1. `rules` (پیشفرض) — امتیازدهی وزنی ۱۶ عاملی موتور امتیازدهی موجود را دربر میگیرد. ابتدا کاندیداهایی با مدارشکن `OPEN` را حذف میکند، سپس `scorePool()` را با نوع وظیفهٔ فعلی و `getTaskFitness()` اجرا کرده و ارائهدهندهای با بالاترین امتیاز را انتخاب میکند. ```ts class RulesStrategyImpl implements RouterStrategy { readonly name = "rules"; readonly description = "16-factor weighted scoring (see DEFAULT_WEIGHTS)"; select(pool, context) { const eligible = pool.filter((c) => c.circuitBreakerState !== "OPEN"); const ranked = scorePool( eligible.length > 0 ? eligible : pool, context.taskType, undefined, getTaskFitness ); return { provider: ranked[0].provider /* ... */ }; } } ``` **زمان استفاده**: حالت پیشفرض. زمانی استفاده کنید که به موازنهای متعادل میان همهٔ سیگنالها نیاز دارید. **نام مستعار**: `rules` (بدون نام مستعار) --- #### 2. `cost` / `eco` — ارزانترین ارائهدهندهٔ سالم مجموعهٔ کاندیداها را بر اساس `costPer1MTokens` (بهصورت صعودی) مرتب کرده و ارزانترین مورد را انتخاب میکند. ابتدا کاندیداهای `OPEN` را حذف میکند. ```ts class CostStrategyImpl implements RouterStrategy { readonly name = "cost"; readonly description = "Always selects cheapest available provider"; select(pool, context) { const healthy = pool.filter((c) => c.circuitBreakerState !== "OPEN"); const sorted = [...healthy].sort((a, b) => a.costPer1MTokens - b.costPer1MTokens); return { provider: sorted[0].provider /* ... */ }; } } ``` **زمان استفاده**: بارهای کاری حساس به هزینه، پردازش دستهای یا کارهای پسزمینه. **نامهای مستعار**: `cost`، `eco` --- #### 3. `latency` / `fast` — کمترین تأخیر p95 با جریمهٔ قابلیت اطمینان بر اساس `p95LatencyMs + (errorRate * 1000)` مرتبسازی میکند. جریمهٔ نرخ خطا تضمین میکند ارائهدهندگان غیرقابلاعتماد، حتی اگر تأخیر اسمی پایینی داشته باشند، در رتبهٔ پایینتری قرار گیرند. ```ts class LatencyStrategyImpl implements RouterStrategy { readonly name = "latency"; readonly description = "Prioritizes lowest p95 latency with reliability weighting"; select(pool, context) { const healthy = pool.filter((c) => c.circuitBreakerState !== "OPEN"); const sorted = [...healthy].sort( (a, b) => a.p95LatencyMs + a.errorRate * 1000 - (b.p95LatencyMs + b.errorRate * 1000) ); return { provider: sorted[0].provider /* ... */ }; } } ``` **زمان استفاده**: بارهای کاری حساس به تأخیر، مانند چت بلادرنگ، تکمیل خودکار یا دستیارهای تعاملی کدنویسی. **نامهای مستعار**: `latency`، `fast` --- #### 4. `sla-aware` / `sla` — انطباق با SLO تأخیر/خطا/هزینه هر کاندیدا را بر اساس میزان انطباق آن با سیاست SLO پیکربندیشده امتیازدهی میکند: | عامل | وزن | فرمول | | -------------- | --- | ------------------------------------------------- | | امتیاز تأخیر | 35% | `threshold / max(value, ε)` | | امتیاز خطا | 35% | `threshold / max(value, ε)` | | امتیاز سلامت | 15% | `1.0` (CLOSED) / `0.5` (HALF_OPEN) / `0.0` (OPEN) | | امتیاز هزینه | 10% | `threshold / max(value, ε)` یا نرمالسازی معکوس | | امتیاز پایداری | 5% | انحراف معیار نرمالشده معکوسِ تأخیر | وقتی `hardConstraints: true` باشد، نامزدها ابتدا بر اساس **امتیاز نقض** (میزان عبور آنها از هر SLO) و سپس بر اساس امتیاز ترکیبی مرتب میشوند. در غیر این صورت، فقط امتیاز ترکیبی ملاک است. ```ts class SLAStrategyImpl implements RouterStrategy { readonly name = "sla-aware"; readonly description = "Selects the provider most likely to satisfy latency, error-rate, and cost SLOs"; select(pool, context) { // ... هر نامزد را بر اساس خطمشی امتیازدهی میکند: { targetP95Ms, maxErrorRate, maxCostPer1MTokens, hardConstraints } } } ``` **فیلدهای SLA** (در پیکربندی ترکیبی تنظیم میشوند): ```json { "strategy": "auto", "config": { "routerStrategy": "sla-aware", "slaTargetP95Ms": 1500, "slaMaxErrorRate": 0.05, "slaMaxCostPer1MTokens": 5, "slaHardConstraints": true } } ``` **زمان استفاده**: بارهای کاری عملیاتی با محدودیتهای سختگیرانه برای تأخیر، نرخ خطا یا بودجه هزینه. **نامهای مستعار**: `sla-aware`، `sla` --- #### 5. `lkgp` — ابتدا آخرین ارائهدهنده معتبر شناختهشده ابتدا **آخرین ارائهدهنده معتبر شناختهشده** را (در صورت تنظیم بودن) امتحان میکند و سپس به استراتژی `rules` برمیگردد. این روش برای چسبندگی نشست مفید است — همان ارائهدهنده درخواستهای بعدی یک مکالمه را مدیریت میکند. ```ts class LKGPStrategyImpl implements RouterStrategy { readonly name = "lkgp"; readonly description = "Tries last known good provider first, then falls back to rules"; select(pool, context) { if (context.lkgpEnabled === false) { return getStrategy("rules").select(pool, context); } if (context.lastKnownGoodProvider) { const candidates = pool.filter( (c) => c.provider === context.lastKnownGoodProvider && c.circuitBreakerState !== "OPEN" ); if (candidates.length > 0) { return { provider: candidates[0].provider /* ... */ }; } } // بازگشت به استراتژی rules return getStrategy("rules").select(pool, context); } } ``` **زمان استفاده**: مکالمات چندمرحلهای که میخواهید همان ارائهدهنده درخواستهای بعدی را مدیریت کند (برای مثال، جهت کشکردن، تداوم زمینه یا ثبات قیمتگذاری). **نام مستعار**: `lkgp` (بدون نام مستعار) --- #### 6. `nadir` — انتخاب مدل آگاه از پرامپت از طریق Nadir هر یک از استراتژیهای بالا، نامزدها را بر اساس دادههای تلهمتری خود رتبهبندی میکند؛ هیچکدام درخواست را نمیخوانند. `nadir` آخرین نوبت کاربر را همراه با شناسههای مدلِ استخر به API تصمیمگیری [Nadir](https://getnadir.com) (`POST /v1/bucket`) ارسال میکند و درخواست را به مدلی هدایت میکند که Nadir از آن فهرست انتخاب کرده است (`simple` ← ارزانترین مدل توانمند، `complex` ← مدل پیشرو). اتصال سرویسدهنده آن مدل همچنان توسط `rules` انتخاب میشود؛ بنابراین سهمیه، سلامت و هزینه همچنان تعیین میکنند که کدام حساب استفاده شود. ```json { "strategy": "auto", "config": { "routerStrategy": "nadir", "nadir": { "apiKey": "ndr_...", "baseUrl": "https://api.getnadir.com", "timeoutMs": 2000 } } } ``` `OMNIROUTE_NADIR_API_KEY` و `OMNIROUTE_NADIR_BASE_URL` مقادیر جایگزین محیطی برای این دو رشته هستند. `baseUrl` فقط برای Nadir خودمیزبان لازم است (وجود `/v1` در انتهای آن پذیرفته میشود). فراخوانیهای بدون کلید به سطح ناشناس Nadir هدایت میشوند که نرخ آن بهازای هر IP محدود شده است. دادههایی که از سیستم خارج میشوند: متن آخرین پیام کاربر (حداکثر 16k نویسه)، شناسههای مدل نامزد و یک برچسب کانال `source: "omniroute"`. هیچ پرامپت سیستمی، تاریخچه، ابزار یا سرآیندی ارسال نمیشود. رفتار در زمان خرابی بهصورت fail-open است: پایان مهلت (بهطور پیشفرض 2000 ms)، پاسخ غیر 2xx، میزبان غیرقابلدسترسی، پاسخ ناقص یا انتخابی خارج از استخر، همگی به تصمیم `rules` منتهی میشوند و پیشوند `NadirStrategy: fallback (…)` به دلیل افزوده میشود. پس از یک فراخوانی ناموفق، استراتژی بهمدت 30 s از شبکه صرفنظر میکند؛ بنابراین هزینه یک قطعی، بهجای یک پایان مهلت برای هر درخواست، یک پایان مهلت در هر 30 s خواهد بود. رویدادهای مسیریابی فقط زمانی `strategy: "nadir"` را گزارش میکنند که Nadir واقعاً انتخاب را انجام داده باشد. **زمان استفاده**: ترافیک با سطح دشواری متفاوت در استخری که چند سطح مدل را پوشش میدهد (یک مدل کوچک، یک مدل میانی و یک مدل پیشرو)، وقتی میخواهید هزینه استفاده همیشگی از مدل پیشرو را کاهش دهید. **نام مستعار**: `nadir` (بدون نام مستعار) --- ### استراتژیهای سفارشی مسیریاب میتوانید پیادهسازی `RouterStrategy` خود را از طریق API عمومی ثبت کنید: ```ts import { registerStrategy, type RouterStrategy, } from "@omniroute/open-sse/services/autoCombo/routerStrategy"; class MyCustomStrategy implements RouterStrategy { readonly name = "my-custom"; readonly description = "My custom routing strategy"; select(pool, context) { // منطق مسیریابی شما در اینجا return { provider: pool[0].provider, model: pool[0].model, strategy: this.name, reason: "MyCustomStrategy: ...", candidatesConsidered: pool.length, finalScore: 1.0, }; } } registerStrategy("my-custom", new MyCustomStrategy()); ``` سپس از آن استفاده کنید: ```json { "strategy": "auto", "config": { "routerStrategy": "my-custom" } } ``` --- ### راهنمای انتخاب استراتژی مسیریاب | مورد استفاده | استراتژی | دلیل | | ------------------ | ----------- | ---------------------------------------------- | | بار کاری متوازن | `rules` | پیشفرض — همه عوامل را در نظر میگیرد | | کمینهکردن هزینه | `cost` | همیشه ارزانترین گزینه را انتخاب میکند | | کمینهکردن تأخیر | `latency` | سریعترین ارائهدهنده قابلاعتماد را انتخاب میکند | | SLOهای سختگیرانه | `sla-aware` | بر اساس آستانههای p95/خطا/هزینه فیلتر میکند | | گفتوگوی چندمرحلهای | `lkgp` | چسبندگی نشست | | دشواری متفاوت | `nadir` | سطح مدل را برای هر پرامپت انتخاب میکند | فیلدهای آگاه از SLA: ```json { "strategy": "auto", "config": { "routerStrategy": "sla-aware", "slaTargetP95Ms": 1500, "slaMaxErrorRate": 0.05, "slaMaxCostPer1MTokens": 5, "slaHardConstraints": true } } ``` ## تناسب وظیفه بیش از ۳۰ مدل در ۶ نوع وظیفه (`coding`، `review`، `planning`، `analysis`، `debugging`، `documentation`) امتیازدهی شدهاند. از الگوهای wildcard پشتیبانی میشود (برای مثال، `*-coder` → امتیاز بالای کدنویسی). ## مرور گونههای Auto با احتساب `auto` ساده (پیشفرض) بهعلاوهٔ ۶ مقدار `AutoVariant` تعریفشده در `autoPrefix.ts`، در مجموع **۷ شناسهٔ مدل قابل فراخوانی** وجود دارد: `auto`، `auto/coding`، `auto/fast`، `auto/cheap`، `auto/offline`، `auto/smart`، `auto/lkgp` (`AutoVariant` خود شامل ۶ مقدار است؛ گزینهٔ هفتم «بدون گونه» — یعنی `auto` ساده — است که توسط `parseAutoPrefix()` بهشکل `variant: undefined` مدیریت میشود.) ## جایگاه سطوح در Auto-Combo تابع امتیازدهی ۱۶عاملی (`open-sse/services/autoCombo/scoring.ts`) عضویت در سطح را بهعنوان دو سیگنال در نظر میگیرد: `tierPriority` (0.0476) و `tierAffinity` (0.0476). برای مشاهده مجموعه کامل `DEFAULT_WEIGHTS`، جدول مرجع [عوامل امتیازدهی](#how-it-works-persisted-auto-combos) در بالا را ببینید — مقادیر بازنویسیشده برای هر بسته (ship-fast/cost-saver/quality-first/ offline-friendly) در جدول «پروفایلهای وزن برای هر بسته» فهرست شدهاند. سطح بهتنهایی **باعث نمیشود** سطح ۱ در اولویت قرار گیرد — اگر تأخیر سطح ۱ نامطلوب باشد یا نسبت هزینه به کیفیت بهینه نباشد، سطح ۲ انتخاب میشود. برای اجبار ترتیب سطوح، از استراتژی `priority` برای ترکیب استفاده کنید و ارائهدهندگان را بر اساس سطح مرتب کنید. برای ترجیح قوی سطح ۱ (اشتراکی)، وزن `tierPriority` را افزایش دهید: ```json { "strategy": "auto", "config": { "auto": { "weights": { "tierPriority": 0.3, "costInv": 0.05 } } } } ``` برای تعاریف سطوح و دستهبندی ارائهدهندگان، به [`docs/guides/TIERS.md`](../guides/TIERS.md) مراجعه کنید. ## آزمون و پوشش ### ماتریس قطعی تصمیمگیری مسیریابی (`npm run test:combo:matrix`) `tests/integration/combo-matrix/*.test.ts` **تصمیم** مسیریابی هر ۱۹ راهبرد عمومی را بهصورت سرتاسری، از طریق خط لولهٔ واقعی combo و با upstream شبیهسازیشده، اثبات میکند. پوشش شامل موارد زیر است: - هر ۱۹ راهبرد `ROUTING_STRATEGY_VALUES` (ordered، weighted، cost، context، fusion، …). - `quota-share` (داخلی) بهصورت سرتاسری: عدالت DRR + کاهش اولویت هنگام اشباع، از طریق نقطهٔ اتصال واقعی `selectQuotaShareTarget` (`registerQuotaFetcher` / `setLKGP` / `__setHeadroomSaturationFetcherForTests`). - پوشش واگذاری همگانی `context-relay` برای تمام تعدادهای ممکن هدف. این مجموعه در CI (کار `test:integration`) با `--test-concurrency=1` و `--test-force-exit` اجرا میشود؛ بنابراین قطعی است و به اعتبارنامههای زنده نیاز ندارد. ### آزمون دود زندهٔ مشروط (در CI نیست — ارائهدهندگان واقعی) | فرمان | کاری که انجام میدهد | | :------------------------------------- | :-------------------------------------------------------------------------------------------------- | | `npm run test:combo:live` | مسیریابی واقعی درونفرایندی با `RUN_COMBO_LIVE=1`؛ از یک پایگاه دادهٔ زندهٔ OmniRoute اسنپشات میگیرد | | `npm run test:combo:live:vps` | فراخوانیهای HTTP علیه یک سرور زندهٔ OmniRoute (`COMBO_LIVE_BASE_URL` را تنظیم کنید) | | `npm run test:combo:live:vps:failover` | همان مورد، همراه با سناریوهای failover عمدی | این آزمونهای دود مسیر واقعی ارتباط را آزمایش میکنند (combo → ارائهدهنده → تکمیل). آنها عمداً از CI کنار گذاشته شدهاند، زیرا به اعتبارنامههای زنده و دسترسی VPS نیاز دارند. --- ## فایلها | فایل | هدف | | :-------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- | | `open-sse/services/autoCombo/scoring.ts` | تابع امتیازدهی ۱۶ عاملی، `DEFAULT_WEIGHTS`، نرمالسازی مجموعه | | `open-sse/services/autoCombo/taskFitness.ts` | جدول جستوجوی تناسب مدل × وظیفه | | `open-sse/services/autoCombo/engine.ts` | منطق انتخاب، بندیت، سقف بودجه | | `open-sse/services/autoCombo/selfHealing.ts` | حذف، کاوشها، حالت رخداد | | `open-sse/services/autoCombo/modePacks.ts` | ۶ پروفایل وزندهی (ارسال سریع، صرفهجویی در هزینه، اولویت کیفیت، مناسب آفلاین، اولویت قابلیت اطمینان، حالت آشوب) | | `open-sse/services/autoCombo/autoPrefix.ts` | تجزیهکننده پیشوند `auto/` + ۶ گونه | | `open-sse/services/autoCombo/virtualFactory.ts` | ساخت `AutoComboConfig` درونحافظهای از اتصالهای فعال | | `open-sse/services/autoCombo/providerRegistryAccessor.ts` | قلاب آزمایش برای شبیهسازی رجیستری ارائهدهنده | | `src/shared/constants/routingStrategies.ts` | `ROUTING_STRATEGY_VALUES` (۲۰ راهبرد) | | `src/sse/handlers/chat.ts` | یکپارچهسازی: اتصال کوتاه پیشوند خودکار |