# 📦 @goodandready/dsh-key-rotation

Прозрачная ротация API-ключей, предиктивный контроль лимитов и межпровайдерный каскадный failover для DeepSeek Harness

npm version license DSH Plugin Node version

GoodAndReady Showcase

🇬🇧 English🇷🇺 Русский🇨🇳 中文说明

Если вам нравится этот плагин, поставьте ему звезду на GitHub — это покажет мне, что плагин вам полезен, и будет мотивировать меня развивать его дальше.

🐛 Если вы нашли баг или хотите предложить новый функционал, создайте issue на GitHub на любом языке — я рассмотрю ваше предложение и реализую полезные идеи в одной из следующих версий плагина.
--- ## ⚡ Обзор и решаемая проблема ### 🚀 Что нового в версии 0.8.10 (Надёжность стриминга и очистка памяти) - **Устранение утечек счётчика соединений**: Гарантированное освобождение слота конкурентности в `try ... finally`, исключающее блокировку ключей при успешном завершении стрима или прерывании клиентом. - **Повтор при сетевых сбоях проверки**: 1 автоматический повтор при кратковременных сокетных ошибках в `probeModels` перед дисквалификацией ключа. - **Очистка устаревших ключей**: Периодическая автоматическая очистка удалённых ключей из внутренних карт состояния пула при регулярном цикле `sweep`. ### 🚀 Что нового в версии 0.8.9 (Развитие маршрутизации и UI) - **Превентивная защита от лимитов (Proactive Rate-Limit Guard)**: Автоматическая пауза ключей по заголовкам `x-ratelimit-remaining-*` и `Retry-After` до наступления ошибки 429. - **Авто-восстановление (Self-Healing / Auto-Unbreak)**: Периодический фоновый опрос эндпоинта `/models` для автоматического снятия статуса `broken` без расхода чат-токенов. - **Маршрутизация по задержке (Latency-Aware Routing)**: Выбор стратегии балансировки: `round-robin`, `least-loaded` (по активным запросам) и `lowest-latency` (по p95 задержки). - **Обновление интерфейса в стиле `dsh-clinebot`**: Пакетное тестирование всех ключей («Test All Keys») с прогрессом, аккордеон живого потока событий ротации (`.krot-event-stream`) и таймер обратного отсчета сброса квот. - **Встроенная поддержка двух языков**: Готовые словари интерфейса на английском (`en`) и китайском (`zh`). ### 🛠️ Что нового в версии 0.8.0 (Стабильность) - **🔌 Автомат выключения провайдера**: после N подряд ошибок контур открывается, запросы быстро завершаются (`CIRCUIT_OPEN`); half-open пробы восстанавливают сервис. - **🕒 Монотонные часы**: cooldown/breaker считаются по процессным часам, NTP не ломает оставшееся время. - **📮 Неблокирующие webhook**: очередь с backoff — `rotate()` не ждёт HTTP. - **🧱 Атомарная запись файлов**: повреждённый JSON не затирает прежнее состояние. - **🧹 GC clone-маршрутов**: осиротевшие авто-роуты убираются из runtime-набора. - **🧭 Таксономия ошибок**: явная классификация switch/surface/soft (408/425/429/5xx, сокеты, gRPC). - **📡 Status**: `circuit` у провайдера + `meta.expectedClones` / `meta.notifyQueue`. - **🧪 Smoke**: сценарий 429 → следующий ключ → успех. ### 🛠️ Что нового в версии 0.7.33 (Хотфикс и повышение стабильности) - **🔍 Исправление проверки ключей**: Функция `resolveBaseUrl` теперь сопоставляет ref ключа с его пулом, восстанавливая работу живого тестирования моделей. - **🛡️ Защита от зацикливания каскада**: Устранена возможность переполнения стека при взаимных кольцевых цепочках failover. - **🕒 Точный сброс квот по PST**: Исправлен знак часового смещения UTC-8 для корректного сброса лимитов в полночь по тихоокеанскому времени. - **🧹 Очистка таймеров в жизненном цикле**: Таймеры `canaryTimer` и `selfHealTimer` переведены на эффекты Cordis, исключая утечки при горячей перезагрузке. - **⚡ Сброс зависших блокировок**: Алгоритм `pickLeastLoaded` теперь учитывает протухшие блокировки при выборе наименее нагруженного ключа. - **🌐 Полная китайская локализация**: Добавлен словарь `zh` в веб-интерфейс настроек для соблюдения стандарта трёх языков (EN/RU/ZH). ### 🚀 Что нового в версии 0.7.31 - **⚡ $O(1)$ Накопитель TokenBucket**: Оптимизация математики лимитов до $O(1)$ по времени и без аллокаций памяти с адаптивной синхронизацией по заголовкам. - **🛡️ Разделение Soft / Hard сбоев**: Кратковременные сетевые сбои (502/503/таймауты) получают короткий 10-секундный кулдаун без штрафного удвоения. - **⏳ Затухание штрафов (Penalty Decay)**: Стабильно работающие ключи автоматически снижают штрафной множитель 1 раз в час. - **🎲 Джиттер кулдауна**: Случайный разброс $\pm 12.5\%$ времени разблокировки предотвращает наплыв запросов на апстрим. - **🎯 Адресное зондирование модели**: Опция целевого микро-пробинга моделей в Canary Prober. - **📊 Перцентили задержки TTFT (p50 / p95 / p99)**: Расчет высокоточных перцентилей задержки первого токена в метриках здоровья. - **🔔 Дайджест вебхук-алертов**: Группировка серии быстрых сбоев за 5-секундное окно в единый сводный отчет для Telegram, Discord и Slack. - **🧹 30-дневная компактизация**: Автоматическая очистка истории старше 30 дней для защиты от утечек памяти. - **✨ Оптимистичный UI и фильтры**: Мгновенный отклик кнопок сброса и статус-пилюли (`Все`, `Готовы`, `В кулдауне`, `С ошибками`) над списком ключей. При активной работе автономных агентов, параллельном запуске субагентов и циклических вызовах инструментов запросы неизбежно упираются в ограничения провайдеров (ошибки HTTP 429 Too Many Requests, исчерпание суточных квот или временные сбои на стороне апстрима). В стандартной конфигурации DeepSeek Harness исчерпание одного API-ключа полностью блокирует цепочку рассуждений агента, ломает сохранённое состояние диалога (Replay State) и требует ручного вмешательства администратора. **`dsh-key-rotation`** реализует отказоустойчивую корпоративную архитектуру **пулов API-ключей с предиктивным контролем лимитов (Token Bucket) и каскадным переключением на резервных провайдеров**, нативно интегрированную в микроядро Cordis. В отличие от внешних прокси-маршрутизаторов, подменяющих идентификаторы моделей, `dsh-key-rotation` работает на уровне перехвата `ctx.credentials.resolve` и хука `llm/stream`: * **Идентичность провайдера остаётся неизменной**: Внутреннее Replay-состояние агента `pi-ai` и контекст инструментов остаются на 100% консистентными. * **Предиктивный Token Bucket**: Перегруженные ключи пропускаются **до** выполнения сетевого запроса, устраняя задержку на сетевой ретрай. * **Балансировка Least-Connections**: Запросы равномерно распределяются по свободным ключам с контролем параллелизма (`maxConcurrency`). * **Автономное самовосстановление и каскад**: Просроченные кулдауны простаивающих ключей снимаются автоматически, а при полном исчерпании пула запрос бесшовно передаётся запасному провайдеру. --- ## 🏗️ Архитектура и жизненный цикл запроса ```mermaid graph LR subgraph ClientLayer ["Уровень клиента и агента"] UserMsg["Сообщение агента / пользователя"] --> Adapter["Адаптер модели pi-ai"] end subgraph RotationEngine ["Ядро dsh-key-rotation"] Adapter --> StreamHook["Перехватчик llm/stream"] StreamHook --> BucketCheck{"Token Bucket\nПроверка RPM / TPM"} BucketCheck -->|В пределах нормы| ConcurrencyCheck{"Трекер параллелизма\nLeast-Connections"} BucketCheck -->|Лимит исчерпан| NextKey1["Выбор следующего здорового ключа"] ConcurrencyCheck -->|Слот свободен| KeyResolver["ctx.credentials.resolve"] ConcurrencyCheck -->|Слот занят| NextKey1 KeyResolver --> ActiveKey["Активный ключ (в работе)"] ActiveKey -.->|HTTP 429 / Quota / Ошибка| Failover["Мгновенный failover"] Failover --> BackoffCalc["Экспоненциальный бэкофф и карантин"] Failover --> NextKey2["Повтор со следующим ключом (без потери токенов)"] Failover -.->|Все ключи в кулдауне| CascadeEngine["Межпровайдерный каскад"] BackoffCalc --> QuotaWindow["Календарный сброс / Полночь UTC/PST"] BackoffCalc --> SelfHeal["Self-Heal sweep простаивания"] SelfHeal -->|Кулдаун истёк| PoolReady["Возврат в пул готовых ключей"] end subgraph UpstreamLayer ["Эндпоинты провайдеров"] ActiveKey --> UpstreamAPI["Основной API провайдера"] CascadeEngine --> FallbackAPI["Резервный API провайдера"] end style ClientLayer fill:#1e1e2e,stroke:#89b4fa,stroke-width:2px,color:#cdd6f4 style RotationEngine fill:#181825,stroke:#cba6f7,stroke-width:2px,color:#cdd6f4 style UpstreamLayer fill:#11111b,stroke:#a6e3a1,stroke-width:2px,color:#cdd6f4 ``` --- ## ✨ Исчерпывающий разбор возможностей ### 🔄 1. Прозрачная ротация и мгновенный Failover * **Сохранение сессии агента**: Ротация подменяет только физический API-токен, оставляя неизменным ID провайдера. Исключает падения `INVALID_REPLAY_STATE` в мульти-инструментальных сценариях. * **Бесшовный повтор до отдачи чанков**: Если ключ падает с ошибкой до начала генерации первого токена, запрос прозрачно перенаправляется на следующий доступный ключ. * **Полный спектр кодов переключения**: Авто-переключение при ошибках `QUOTA`, `RATE_LIMIT`, `SERVER`, `TIMEOUT`, `TRANSPORT`, `EMPTY_RESPONSE`, `UNKNOWN_MODEL`, `AUTH` и `INVALID`. * **Интеллектуальный парсер текста ошибок**: Регулярные выражения (`SWITCHABLE_MESSAGE_PATTERN`) распознают текстовые сообщения об исчерпании лимитов, которые SDK провайдеров выбрасывают как неструктурированные исключения. * **Защита нестриминговых вызовов**: Синхронные операции (эмбеддинги, батч-оценки) защищены хуком `agent/request-error`. ### ⏱️ 2. Предиктивный Token Bucket и контроль параллелизма * **Token Bucket / Leaky Bucket (`lib/bucket.js`)**: Скользящее минутное окно отслеживания запросов (`rpmLimit`) и токенов (`tpmLimit`). Блокирует исчерпанный ключ **до** отправки запроса в сеть, исключая потерю времени на сетевой 429. * **Балансировщик Least-Connections (`lib/concurrency.js`)**: Отслеживает активные in-flight соединения на каждом ключе (`inFlight`). Равномерно распределяет параллельную нагрузку и соблюдает лимит `maxConcurrency`. * **Авто-очистка зависших блокировок**: При аварийном разрыве сетевых соединений счетчики соединений автоматически очищаются через 5 минут. ### 🛡️ 3. Автономное самовосстановление и каскадный Failover * **Межпровайдерный каскад (`lib/cascade.js`)**: При исчерпании всех ключей выбранного провайдера запрос автоматически каскадируется на настроенного резервного провайдера (`cascade: [{ provider, model }]`). * **Sandbox-пробы ключей (`lib/sandbox.js`)**: По запросу выполняется `/models`-проба ключа перед возвратом в ротацию; простаивающие кулдауны снимаются self-heal sweep. * **Календарный сброс квот (`lib/quota-window.js`)**: Учитывает окна сброса суточных квот провайдеров (`midnight_utc`, `midnight_pst`, `rolling_24h`), снимая карантин ровно в момент обновления лимитов у апстрима. * **Экспоненциальный бэкофф (`lib/pool.js`)**: Повторные сбои на ключе прогрессивно увеличивают время кулдауна (базовое → ×2 → ×4 → максимум ×8). ### 🎯 4. Маршрутизация по моделям * **Модельные подпулы (`lib/pool.js`)**: Назначение выделенных ключей под конкретные модели (например, отдельные ключи для тяжелых reasoning-моделей и дешевые ключи для утилит). * **Тегирование ключей**: Метки приоритета (`production`, `background`, `eval`) для разделения квот между интерактивными и фоновыми задачами. ### 📊 5. Телеметрия, аналитика и интерактивные вебхуки * **Интерактивные вебхуки (`lib/webhook.js`)**: Отправка форматированных алертов с кнопками действий в **Telegram** (Inline Keyboards), **Discord** (Action Rows) и **Slack** (Block Kit). Администратор может сбросить кулдаун или отключить провайдер прямо из мессенджера. * **Отчеты об использовании и расходах (`lib/usage-report.js`)**: Учет суточного числа запросов и расчетной стоимости по каждому ключу с экспортом в CSV/JSON (`GET /dsh-key-rotation/usage-report`). * **Гистограмма задержек SLO (`lib/histogram.js`)**: Измерение времени до первого токена (TTFT) и расчет индекса здоровья пула (`0..100`). --- ## 🖥️ Панель управления в Web GUI Управление доступно в разделе **Настройки → Ротация ключей** или через быстрый виджет в шапке. | Элемент интерфейса | Описание | |---|---| | **Виджет в шапке / статусбаре** | Компактный статус: 🟢 `Все в норме` \| 🟡 `Есть ключи в кулдауне` \| 🔴 `Пул исчерпан` с быстрым всплывающим меню. | | **Матрица здоровья (1-Click Matrix)** | Интерактивная таблица "Health Matrix" с параллельным зондированием всех ключей, моделей и отображением задержки TTFT. | | **Быстрое добавление ключей** | Добавление ключа в 1 клик с автогенерацией имени (`_API_KEY`, `_2`, `_3`) и маскировкой. | | **Живые бейджи статуса** | Индикаторы: `Используется`, `Готов`, `Остывает` (с живым таймером обратного отсчета) и `Не найден`. | | **Приоритет ключей** | Кнопки и для настройки точного порядка перебора в пуле. | | **Чекбоксы кодов ошибок** | Наглядные переключатели условий срабатывания ротации. | | **Детектор утечек секретов** | Валидация форматов токенов (`lib/keycheck.js`) и защита от случайной вставки приватных SSH/RSA-ключей. | | **Импорт из `.env`** | Массовая загрузка пар `KEY=value` из файлов конфигурации. | | **Отмена действий (5 сек)** | Всплывающая плашка отмены при случайном удалении ключа или пула. | | **График активности** | Наглядная статистика запросов и динамики использования ключей. | --- ## 🔒 Безопасность и хранение секретов * **Никаких открытых секретов в конфигурации**: В настройках плагина хранятся только имена переменных окружения (например, `PROVIDER_API_KEY`). * **Защищённое хранилище хоста**: Реальные значения ключей сохраняются в `$DSH_HOME/.credentials.yaml` сервисом `Credentials`. * **Маскировка в браузере (5 символов)**: Браузер получает только последние 5 символов ключа для визуального отличия. * **Ограничение Loopback**: Все управляющие маршруты (`GET /status`, `PUT /key`, `POST /reset`, `POST /test-matrix`) строго проверяют loopback-происхождение запроса (`isTrustedBridgeRequest`). --- ## 📦 Установка ```bash # Установка через менеджер плагинов DSH (профиль web): dsh plugin --profile web add @goodandready/dsh-key-rotation # Или напрямую из GitHub: dsh plugin --profile web add github:GooDAnDReaDY/dsh-key-rotation ``` > [!IMPORTANT] > После установки перезапустите веб-сервис DeepSeek Harness и обновите вкладку браузера: > ```bash > systemctl --user restart dsh-web > ``` --- ## ⚙️ Пример конфигурации (`settings.yaml`) ```yaml dsh-key-rotation: switchCodes: - QUOTA - RATE_LIMIT - SERVER - TIMEOUT - TRANSPORT - EMPTY_RESPONSE - UNKNOWN_MODEL - AUTH cooldownMs: 60000 circuitBreakerEnabled: true circuitBreakerThreshold: 5 circuitBreakerOpenMs: 30000 circuitBreakerHalfOpenProbes: 1 concurrencyLimit: 5 quotaResetWindow: type: midnight_utc hour: 0 cascade: - provider: backup-provider-id model: your-backup-model-id webhookUrl: "https://api.telegram.org/bot/sendMessage?chat_id=" providers: - provider: your-primary-provider rpmLimit: 60 tpmLimit: 100000 keys: - PRIMARY_API_KEY - PRIMARY_API_KEY_2 - PRIMARY_API_KEY_BACKUP - provider: secondary-provider keys: - SECONDARY_API_KEY - SECONDARY_API_KEY_2 ``` ### Таблица параметров | Параметр | Тип | По умолчанию | Описание | |---|---|---|---| | `switchCodes` | `string[]` | `[QUOTA, RATE_LIMIT, ...]` | Список кодов ошибок, инициирующих немедленный переход на следующий ключ. | | `cooldownMs` | `number` | `60000` (1 мин) | Базовая длительность нахождения ключа в карантине (в мс). | | `concurrencyLimit` | `number` | `0` (отключено) | Лимит одновременных активных запросов на ключ (0 = без ограничений). | | `quotaResetWindow` | `object` | `null` | Календарное расписание сброса квот (`midnight_utc`, `midnight_pst`, `rolling_24h`). | | `cascade` | `array` | `[]` | Цепочка резервных провайдеров при исчерпании всех ключей основного пула. | | `webhookUrl` | `string` | `""` | URL вебхука для интерактивных алертов в Telegram, Discord или Slack. | | `providers` | `array` | `[]` | Список определений пулов `{ provider, keys, rpmLimit, tpmLimit, modelPools }`. | --- ## 🔌 Справочник HTTP Bridge API Все служебные маршруты требуют локальной авторизации (`127.0.0.1` / `::1`) и проверки Same-Origin: | Маршрут | Метод | Описание | |---|---|---| | `/dsh-key-rotation/status` | `GET` | Текущий снимок состояния здоровья, активных ключей и кулдаунов. | | `/dsh-key-rotation/config` | `GET` / `PUT` | Чтение и изменение активных параметров ротации и пулов провайдеров. | | `/dsh-key-rotation/key` | `PUT` / `DELETE` | Добавление, обновление или удаление ключей в хранилище и пуле. | | `/dsh-key-rotation/reset` | `POST` | Мгновенный сброс всех кулдаунов и возврат ключей в статус `ready`. | | `/dsh-key-rotation/test-matrix` | `POST` | Запуск параллельного тестирования всей матрицы ключей и моделей. | | `/dsh-key-rotation/usage-report` | `GET` | Получение сводного отчета использования в формате JSON или CSV (`?format=csv`). | | `/dsh-key-rotation/webhook-callback`| `POST` | Обработка интерактивных действий от кнопок в Telegram/Slack. | --- ## 📄 Лицензия MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY) ### v0.7.39 - **Самоисцеление ключей и фиксация lastUsedAt**: Исправлено чтение меток времени в `healIdleCooldowns`, использующее теперь карту `pool.state.lastUsedAt`. В `credentials.resolve` добавлено сохранение точного времени каждого обращения к ключу, что активирует вывод времени использования в панели мониторинга и корректное самоисцеление ключей после простоя. - **Оптимизация обращений к buildRuntime**: Устранены повторные вызовы `buildRuntime()` в процедурах периодической очистки, маршруте `/status` и блоке обработки исчерпания пула. - **Стабилизация CI и устранение утечек таймеров**: Фоновые таймеры дебаунса и очистки теперь отвязываются (`unref`) от цикла событий Node.js, предотвращая зависание раннера. Удалены тесты устаревшего модуля инцидентов. ### v0.7.38 - **Оптимизация горячего пути стриминга**: Устранены 4 избыточных вызова `buildRuntime()` при обработке завершающего чанка в `rotate()` за счёт повторного использования снимка `runtime0`. - **Парсинг заголовков лимитов без лишних аллокаций**: Оптимизирована функция `extractRateLimit()` — однократный проход по объекту с проверкой длины ключей без постоянных аллокаций строк `.toLowerCase()` и `.toUpperCase()`. - **Мемоизация строки даты ISO**: Дата текущего дня (`todayIso`) теперь вычисляется ровно один раз на запрос, исключая создание нескольких дублирующих объектов `Date` для `costDays` и `usageDays`. - **Итеративный подсчет totalUsage**: В эндпоинте статуса `/dsh-key-rotation/status` расчёт суммарного потребления переведён на прямой цикл без аллокации промежуточного массива `[...values()]`. - **Очистка устаревших записей уведомлений**: При удалении пулов провайдеров из конфигурации автоматически вычищаются связанные ключи из карт троттлинга уведомлений (`budgetNotifiedAt`, `lowHealthNotifiedAt`). ### v0.7.37 - **Изоляция контекста запросов через AsyncLocalStorage**: Полная привязка активного ключа (`pickedRef`), времени старта и попыток к асинхронному контексту вызова через `node:async_hooks`. Устранена гонка, при которой параллельные запросы могли ошибочно штрафовать здоровый ключ соседа. - **Failover при исключениях в потоке до первого чанка**: Устранено аварийное прерывание потока при транспортных сбоях (например, выброс HTTP 429 до отправки заголовков). Теперь блок перехвата проверяет `isSwitchableError` и прозрачно переключает поток на запасной ключ, если клиенту ещё не было отдано полезных данных. - **Чистый локальный список кандидатов в rotate()**: Устранена прямая мутация разделяемого массива `pool.weightedRefs` во время выполнения ротации. - **Автоматический вывод из карантина при успехе проверки**: Успешная проверка ключа через песочницу в настройках (`/dsh-key-rotation/test`) моментально сбрасывает флаги карантина (`failedUntil` и `brokenUntil`). - **Регулярная компактизация памяти**: Функция `compactUsage(pool, 30, now)` подключена в 30-секундный фоновый таймер пула, предотвращая утечки памяти при непрерывной многомесячной работе. - **Точные метрики задержки при параллельных вызовах**: Переход с глобальной переменной времени старта на контекстный замер `startMs` гарантирует достоверность p50/p95 latency под нагрузкой. ### v0.7.36 - **Глубокий рефакторинг и деблоатинг**: Удалены 6 неиспользуемых модулей оверинжиниринга (`shadow`, `incident`, `agent-budget`, `region`, `canary`, `maintenance`) и сопутствующие устаревшие эндпоинты. - **Мемоизация buildRuntime**: Устранено глубокое клонирование и повторный парсинг схемы на каждом токене/чанге стрима. - **Атомарная ротация указателя**: Устранено состояние гонки при параллельных вызовах инструментов — указатель смещается сразу при выборе кандидата. - **Точная детекция ошибок**: Прямая проверка кодов HTTP (`429`, `401`, `403`, `5xx`) и gRPC (`RESOURCE_EXHAUSTED`, `UNAVAILABLE`) с фоллбеком на регулярные выражения. - **Понятные сообщения при исчерпании пула**: Информативное уведомление с таймером восстановления ближайшего ключа. - **Энергоэффективный опрос (Smart Polling)**: Автоматическая приостановка фонового опроса при неактивной вкладке браузера (`document.visibilityState`). ### v0.7.35 - **Очистка жизненного цикла**: Патч `credentials.resolve` и слушатели событий `ctx.on` (`llm/stream`, `agent/request-error`) переведены в скоупы `ctx.effect` с автоматическим восстановлением функций и отпиской при выгрузке плагина (#238, #239). - **Роли секретов в схеме**: Полям `incidentGitHubToken` и `webhookActionToken` в схеме `Config` присвоена роль `.role('secret')` для маскирования в UI (#237). - **Архитектура настроек**: Добавлена нативная интеграция со снимками `settingsScope` в карточке настроек с безопасным фоллбеком на HTTP-мост (#235). - **Распределение нагрузки и модальные окна (Changed in v0.8.5)**: Диаграмма распределения нагрузки (.krot-load-chart), модальные подтверждения (.krot-modal) и джиттер кулдаунов при 429/5xx (#283, #284). - **Нативная дизайн-система (Changed in v0.8.3)**: Унификация со стилем `dsh-clinebot`: модульные карточки секций, плитки оперативной телеметрии пулов, капсульные бейджи и системные CSS-токены DSH (#281). - **Локализация (Changed in v0.8.2)**: Исходные строки только на английском (`en`). Русский и китайский приходят через core `props.t` / translation-плагины. Фолбек активной локали: snapshot → первый `navigator.languages` → `en`. Свой `settings.section` и встроенные `ru`/`zh`-таблицы удалены (#236, #275, #277). - **Удаление мёртвого кода**: Удалена неиспользуемая функция `mountDashboard` после перехода на header chip (#240). ### Параметры circuit breaker (Changed in v0.8.0) | Параметр | Тип | По умолчанию | Описание | |---|---|---|---| | `circuitBreakerEnabled` | boolean | `true` | Включить/выключить breaker | | `circuitBreakerThreshold` | number | `5` | Число подряд ошибок до открытия | | `circuitBreakerOpenMs` | number | `30000` | Длительность open, мс | | `circuitBreakerHalfOpenProbes` | number | `1` | Проб в half-open | | `verboseLogging` | boolean | `false` | Подробные логи rotation (шумно) | Status API (v0.8.0): у каждого провайдера `circuit`, в корне ответа `meta.expectedClones` и `meta.notifyQueue`.