diff --git a/docs/uk/channels/telegram.md b/docs/uk/channels/telegram.md
index b81c20ae6..b368a4b4e 100644
--- a/docs/uk/channels/telegram.md
+++ b/docs/uk/channels/telegram.md
@@ -1,29 +1,27 @@
---
read_when:
- - Робота над функціями Telegram або Webhookами
-summary: Статус підтримки бота Telegram, можливості та налаштування
+ - Робота над функціями Telegram або Webhook
+summary: Статус підтримки, можливості та конфігурація бота Telegram
title: Telegram
x-i18n:
- generated_at: "2026-04-23T08:40:45Z"
+ generated_at: "2026-04-23T19:48:38Z"
model: gpt-5.4
provider: openai
- source_hash: 024b76c3c71537995fc4efc26887eae516846d3f845d135b263d4d7f270afbb7
+ source_hash: 68ba2426447401f999346c794f5935bf545d42ab25c9b4218b4f4a772d6d9f78
source_path: channels/telegram.md
workflow: 15
---
-# Telegram (Bot API)
-
-Статус: готовий до використання в production для DM ботів і груп через grammY. Режим long polling є типовим; режим webhook є необов’язковим.
+Готово для production для DM і груп бота через grammY. Long polling — режим за замовчуванням; режим Webhook — необов’язковий.
-
- Типова політика DM для Telegram — підключення.
+
+ Політика DM за замовчуванням для Telegram — пейринг.
-
- Міжканальна діагностика та сценарії відновлення.
+
+ Міжканальна діагностика та інструкції з відновлення.
-
+
Повні шаблони та приклади конфігурації каналів.
@@ -32,9 +30,9 @@ x-i18n:
- Відкрийте Telegram і почніть чат із **@BotFather** (переконайтеся, що хендл точно `@BotFather`).
+ Відкрийте Telegram і почніть чат із **@BotFather** (переконайтеся, що ім’я користувача точно `@BotFather`).
- Виконайте `/newbot`, дотримуйтеся підказок і збережіть токен.
+ Виконайте `/newbot`, дотримуйтесь підказок і збережіть токен.
@@ -53,7 +51,7 @@ x-i18n:
}
```
- Резервний варіант через env: `TELEGRAM_BOT_TOKEN=...` (лише для типового облікового запису).
+ Резервний варіант через env: `TELEGRAM_BOT_TOKEN=...` (лише для облікового запису за замовчуванням).
Telegram **не** використовує `openclaw channels login telegram`; налаштуйте токен у config/env, а потім запустіть gateway.
@@ -66,7 +64,7 @@ openclaw pairing list telegram
openclaw pairing approve telegram
```
- Коди підключення діють 1 годину.
+ Коди пейрингу дійсні протягом 1 години.
@@ -76,21 +74,21 @@ openclaw pairing approve telegram
-Порядок визначення токена враховує обліковий запис. На практиці значення з config мають пріоритет над резервним варіантом через env, а `TELEGRAM_BOT_TOKEN` застосовується лише до типового облікового запису.
+Порядок визначення токена залежить від облікового запису. На практиці значення з config мають пріоритет над резервним варіантом через env, а `TELEGRAM_BOT_TOKEN` застосовується лише до облікового запису за замовчуванням.
## Налаштування на боці Telegram
- Для ботів Telegram типовим є **Privacy Mode**, який обмежує, які повідомлення в групах вони отримують.
+ Для ботів Telegram за замовчуванням увімкнено **Privacy Mode**, що обмежує, які повідомлення з груп вони отримують.
- Якщо бот має бачити всі повідомлення в групі, зробіть одне з такого:
+ Якщо бот має бачити всі повідомлення в групі, виконайте одну з дій:
- вимкніть режим конфіденційності через `/setprivacy`, або
- зробіть бота адміністратором групи.
- Після перемикання режиму конфіденційності видаліть бота з кожної групи та додайте його знову, щоб Telegram застосував зміну.
+ Після перемикання режиму конфіденційності видаліть і знову додайте бота в кожну групу, щоб Telegram застосував зміну.
@@ -103,34 +101,34 @@ openclaw pairing approve telegram
- - `/setjoingroups` — дозволити або заборонити додавання до груп
- - `/setprivacy` — поведінка видимості в групах
+ - `/setjoingroups`, щоб дозволити/заборонити додавання до груп
+ - `/setprivacy` для керування видимістю в групах
-## Контроль доступу та активація
+## Керування доступом і активація
`channels.telegram.dmPolicy` керує доступом до прямих повідомлень:
- - `pairing` (типово)
- - `allowlist` (потрібен принаймні один ID відправника в `allowFrom`)
+ - `pairing` (за замовчуванням)
+ - `allowlist` (потрібен щонайменше один ID відправника в `allowFrom`)
- `open` (потрібно, щоб `allowFrom` містив `"*"`)
- `disabled`
- `channels.telegram.allowFrom` приймає числові ID користувачів Telegram. Префікси `telegram:` / `tg:` підтримуються та нормалізуються.
- `dmPolicy: "allowlist"` з порожнім `allowFrom` блокує всі DM і відхиляється перевіркою config.
+ `channels.telegram.allowFrom` приймає числові ID користувачів Telegram. Префікси `telegram:` / `tg:` приймаються й нормалізуються.
+ `dmPolicy: "allowlist"` із порожнім `allowFrom` блокує всі DM і відхиляється валідацією config.
Під час налаштування запитуються лише числові ID користувачів.
- Якщо ви оновилися і ваш config містить записи allowlist у вигляді `@username`, виконайте `openclaw doctor --fix`, щоб розв’язати їх (best-effort; потрібен токен Telegram-бота).
- Якщо раніше ви покладалися на файли allowlist у pairing-store, `openclaw doctor --fix` може відновити записи до `channels.telegram.allowFrom` у сценаріях allowlist (наприклад, коли `dmPolicy: "allowlist"` ще не має явних ID).
+ Якщо ви оновилися і ваша config містить записи allowlist у форматі `@username`, виконайте `openclaw doctor --fix`, щоб їх розв’язати (у режимі best-effort; потрібен токен Telegram-бота).
+ Якщо ви раніше покладалися на файли allowlist зі сховища пейрингу, `openclaw doctor --fix` може відновити записи до `channels.telegram.allowFrom` у сценаріях allowlist (наприклад, коли `dmPolicy: "allowlist"` ще не має явних ID).
- Для ботів з одним власником віддавайте перевагу `dmPolicy: "allowlist"` із явними числовими ID в `allowFrom`, щоб політика доступу надійно зберігалася в config (замість залежності від попередніх схвалень підключення).
+ Для ботів з одним власником віддавайте перевагу `dmPolicy: "allowlist"` з явними числовими ID в `allowFrom`, щоб політика доступу надійно зберігалася в config (замість залежності від попередніх схвалень пейрингу).
- Поширена плутанина: схвалення підключення DM не означає, що «цей відправник авторизований всюди».
- Підключення надає доступ лише до DM. Авторизація відправника в групах і надалі визначається лише явними allowlist у config.
- Якщо ви хочете, щоб «я авторизований один раз і працюють і DM, і команди в групах», додайте свій числовий ID користувача Telegram до `channels.telegram.allowFrom`.
+ Поширена плутанина: схвалення DM-пейрингу не означає, що «цей відправник авторизований усюди».
+ Пейринг надає доступ лише до DM. Авторизація відправника в групах, як і раніше, походить лише з явних allowlist у config.
+ Якщо ви хочете, щоб «я один раз авторизувався і працювали і DM, і команди в групах», додайте свій числовий ID користувача Telegram у `channels.telegram.allowFrom`.
### Як знайти свій ID користувача Telegram
@@ -140,39 +138,39 @@ openclaw pairing approve telegram
2. Виконайте `openclaw logs --follow`.
3. Прочитайте `from.id`.
- Офіційний метод Bot API:
+ Офіційний метод через Bot API:
```bash
curl "https://api.telegram.org/bot/getUpdates"
```
- Сторонній спосіб (менш приватний): `@userinfobot` або `@getidsbot`.
+ Сторонній метод (менш приватний): `@userinfobot` або `@getidsbot`.
- Разом застосовуються два механізми керування:
+ Разом застосовуються два механізми:
1. **Які групи дозволені** (`channels.telegram.groups`)
- - немає config `groups`:
+ - без config `groups`:
- з `groupPolicy: "open"`: будь-яка група може пройти перевірки ID групи
- - з `groupPolicy: "allowlist"` (типово): групи блокуються, доки ви не додасте записи до `groups` (або `"*"`)
+ - з `groupPolicy: "allowlist"` (за замовчуванням): групи блокуються, доки ви не додасте записи в `groups` (або `"*"`)
- `groups` налаштовано: працює як allowlist (явні ID або `"*"`)
2. **Які відправники дозволені в групах** (`channels.telegram.groupPolicy`)
- `open`
- - `allowlist` (типово)
+ - `allowlist` (за замовчуванням)
- `disabled`
- `groupAllowFrom` використовується для фільтрації відправників у групах. Якщо він не заданий, Telegram повертається до `allowFrom`.
- Записи `groupAllowFrom` мають бути числовими ID користувачів Telegram (`telegram:` / `tg:` префікси нормалізуються).
- Не вказуйте ID груп або супергруп Telegram у `groupAllowFrom`. Від’ємні ID чатів слід розміщувати в `channels.telegram.groups`.
- Нечислові записи ігноруються для авторизації відправників.
- Межа безпеки (`2026.2.25+`): авторизація відправника в групах **не** успадковує схвалення з DM pairing-store.
- Підключення залишається лише для DM. Для груп задавайте `groupAllowFrom` або `allowFrom` для конкретної групи/теми.
- Якщо `groupAllowFrom` не задано, Telegram повертається до config `allowFrom`, а не до pairing store.
- Практичний шаблон для ботів з одним власником: задайте свій ID користувача в `channels.telegram.allowFrom`, залиште `groupAllowFrom` незаданим і дозвольте потрібні групи через `channels.telegram.groups`.
- Примітка щодо runtime: якщо `channels.telegram` повністю відсутній, runtime типово працює в режимі fail-closed з `groupPolicy="allowlist"`, якщо явно не задано `channels.defaults.groupPolicy`.
+ `groupAllowFrom` використовується для фільтрації відправників у групах. Якщо не задано, Telegram використовує резервне значення з `allowFrom`.
+ Записи `groupAllowFrom` мають бути числовими ID користувачів Telegram (префікси `telegram:` / `tg:` нормалізуються).
+ Не вказуйте ID чатів Telegram group або supergroup у `groupAllowFrom`. Від’ємні ID чатів належать до `channels.telegram.groups`.
+ Нечислові записи ігноруються для авторизації відправника.
+ Межа безпеки (`2026.2.25+`): авторизація відправника в групі **не** успадковує схвалення зі сховища DM-пейрингу.
+ Пейринг залишається лише для DM. Для груп налаштуйте `groupAllowFrom` або `allowFrom` для конкретної групи/теми.
+ Якщо `groupAllowFrom` не задано, Telegram використовує резервне значення з config `allowFrom`, а не зі сховища пейрингу.
+ Практичний шаблон для ботів з одним власником: задайте свій ID користувача в `channels.telegram.allowFrom`, залиште `groupAllowFrom` незаданим і дозвольте цільові групи в `channels.telegram.groups`.
+ Примітка щодо runtime: якщо `channels.telegram` повністю відсутній, runtime за замовчуванням використовує fail-closed `groupPolicy="allowlist"`, якщо тільки явно не задано `channels.defaults.groupPolicy`.
Приклад: дозволити будь-якого учасника в одній конкретній групі:
@@ -211,20 +209,20 @@ curl "https://api.telegram.org/bot/getUpdates"
Поширена помилка: `groupAllowFrom` — це не allowlist груп Telegram.
- - Розміщуйте від’ємні ID груп або супергруп Telegram, як-от `-1001234567890`, у `channels.telegram.groups`.
- - Розміщуйте ID користувачів Telegram, як-от `8734062810`, у `groupAllowFrom`, якщо хочете обмежити, які люди всередині дозволеної групи можуть викликати бота.
- - Використовуйте `groupAllowFrom: ["*"]` лише тоді, коли хочете, щоб будь-який учасник дозволеної групи міг звертатися до бота.
+ - Вказуйте від’ємні ID груп або супергруп Telegram, наприклад `-1001234567890`, у `channels.telegram.groups`.
+ - Вказуйте ID користувачів Telegram, наприклад `8734062810`, у `groupAllowFrom`, якщо хочете обмежити, хто саме всередині дозволеної групи може викликати бота.
+ - Використовуйте `groupAllowFrom: ["*"]` лише якщо хочете, щоб будь-який учасник дозволеної групи міг спілкуватися з ботом.
-
- Відповіді в групах типово вимагають згадування.
+
+ Відповіді в групах за замовчуванням потребують згадки.
- Згадування може надходити з:
+ Згадка може надходити з:
- - нативного згадування `@botusername`, або
- - шаблонів згадування в:
+ - нативної згадки `@botusername`, або
+ - шаблонів згадок у:
- `agents.list[].groupChat.mentionPatterns`
- `messages.groupChat.mentionPatterns`
@@ -235,7 +233,7 @@ curl "https://api.telegram.org/bot/getUpdates"
Вони оновлюють лише стан сесії. Для збереження використовуйте config.
- Приклад постійної конфігурації:
+ Приклад постійної config:
```json5
{
@@ -249,11 +247,11 @@ curl "https://api.telegram.org/bot/getUpdates"
}
```
- Як отримати ID чату групи:
+ Як отримати ID групового чату:
- перешліть повідомлення з групи до `@userinfobot` / `@getidsbot`
- або прочитайте `chat.id` з `openclaw logs --follow`
- - або перевірте Bot API `getUpdates`
+ - або перегляньте Bot API `getUpdates`
@@ -261,40 +259,40 @@ curl "https://api.telegram.org/bot/getUpdates"
## Поведінка runtime
- Telegram належить процесу gateway.
-- Маршрутизація детермінована: вхідні відповіді Telegram повертаються в Telegram (модель не вибирає канали).
-- Вхідні повідомлення нормалізуються в спільну оболонку каналу з метаданими відповіді та заповнювачами медіа.
-- Групові сесії ізольовані за ID групи. Теми форуму додають `:topic:`, щоб зберігати ізоляцію тем.
+- Маршрутизація детермінована: вхідні відповіді з Telegram повертаються в Telegram (модель не вибирає канали).
+- Вхідні повідомлення нормалізуються до спільного конверта каналу з метаданими відповіді та заповнювачами медіа.
+- Сесії груп ізольовані за ID групи. Теми форуму додають `:topic:`, щоб теми залишалися ізольованими.
- DM-повідомлення можуть містити `message_thread_id`; OpenClaw маршрутизує їх за ключами сесій з урахуванням тредів і зберігає ID треду для відповідей.
-- Long polling використовує grammY runner із послідовною обробкою для кожного чату/треду. Загальна конкурентність sink у runner використовує `agents.defaults.maxConcurrent`.
-- Перезапуски watchdog для long polling спрацьовують типово після 120 секунд без завершеного сигналу живості `getUpdates`. Збільшуйте `channels.telegram.pollingStallThresholdMs` лише якщо у вашому розгортанні все ще виникають хибні перезапуски через зупинку polling під час довготривалої роботи. Значення задається в мілісекундах і може бути від `30000` до `600000`; підтримуються перевизначення для окремих облікових записів.
+- Long polling використовує grammY runner із послідовною обробкою для кожного чату/треду. Загальна конкурентність sink runner використовує `agents.defaults.maxConcurrent`.
+- Перезапуски наглядача long polling спрацьовують після 120 секунд без завершеної ознаки активності `getUpdates` за замовчуванням. Збільшуйте `channels.telegram.pollingStallThresholdMs` лише якщо у вашому розгортанні все ще трапляються хибні перезапуски через зависання polling під час довготривалої роботи. Значення задається в мілісекундах і допускається в діапазоні від `30000` до `600000`; підтримуються перевизначення для окремих облікових записів.
- Telegram Bot API не підтримує підтвердження прочитання (`sendReadReceipts` не застосовується).
-## Довідник функцій
+## Довідка з функцій
-
- OpenClaw може передавати часткові відповіді в реальному часі:
+
+ OpenClaw може транслювати часткові відповіді в реальному часі:
- - прямі чати: повідомлення попереднього перегляду + `editMessageText`
- - групи/теми: повідомлення попереднього перегляду + `editMessageText`
+ - прямі чати: попереднє повідомлення + `editMessageText`
+ - групи/теми: попереднє повідомлення + `editMessageText`
Вимога:
- - `channels.telegram.streaming` має значення `off | partial | block | progress` (типово: `partial`)
- - `progress` у Telegram відповідає `partial` (сумісність із міжканальним найменуванням)
- - `streaming.preview.toolProgress` керує тим, чи повторно використовуються оновлення інструментів/прогресу в тому самому відредагованому повідомленні попереднього перегляду (типово: `true`). Установіть `false`, щоб зберігати окремі повідомлення інструментів/прогресу.
- - застарілі `channels.telegram.streamMode` і булеві значення `streaming` зіставляються автоматично
+ - `channels.telegram.streaming` має значення `off | partial | block | progress` (за замовчуванням: `partial`)
+ - `progress` у Telegram відображається як `partial` (сумісність із міжканальним найменуванням)
+ - `streaming.preview.toolProgress` керує тим, чи оновлення інструментів/прогресу повторно використовують те саме відредаговане попереднє повідомлення (за замовчуванням: `true`). Установіть `false`, щоб зберегти окремі повідомлення для інструментів/прогресу.
+ - застарілі `channels.telegram.streamMode` і булеві значення `streaming` автоматично зіставляються
Для відповідей лише з текстом:
- - DM: OpenClaw зберігає те саме повідомлення попереднього перегляду та виконує фінальне редагування на місці (без другого повідомлення)
- - група/тема: OpenClaw зберігає те саме повідомлення попереднього перегляду та виконує фінальне редагування на місці (без другого повідомлення)
+ - DM: OpenClaw зберігає те саме попереднє повідомлення й виконує фінальне редагування на місці (без другого повідомлення)
+ - група/тема: OpenClaw зберігає те саме попереднє повідомлення й виконує фінальне редагування на місці (без другого повідомлення)
- Для складних відповідей (наприклад, медіаповідомлень) OpenClaw повертається до звичайної фінальної доставки, а потім прибирає повідомлення попереднього перегляду.
+ Для складних відповідей (наприклад, із медіавмістом) OpenClaw повертається до звичайної фінальної доставки, а потім прибирає попереднє повідомлення.
- Потокова передача попереднього перегляду відокремлена від block streaming. Коли для Telegram явно ввімкнено block streaming, OpenClaw пропускає потік попереднього перегляду, щоб уникнути подвійної потокової передачі.
+ Потокове попереднє відображення відокремлене від block streaming. Коли для Telegram явно ввімкнено block streaming, OpenClaw пропускає preview stream, щоб уникнути подвійного стримінгу.
- Якщо нативний транспорт чернеток недоступний або відхиляється, OpenClaw автоматично повертається до `sendMessage` + `editMessageText`.
+ Якщо нативний транспорт чернетки недоступний або відхиляється, OpenClaw автоматично повертається до `sendMessage` + `editMessageText`.
Потік reasoning лише для Telegram:
@@ -304,24 +302,24 @@ curl "https://api.telegram.org/bot/getUpdates"
- Вихідний текст використовує Telegram `parse_mode: "HTML"`.
+ Для вихідного тексту використовується Telegram `parse_mode: "HTML"`.
- Текст у стилі Markdown рендериться в безпечний для Telegram HTML.
- - Сирий HTML моделі екранується, щоб зменшити кількість помилок розбору Telegram.
- - Якщо Telegram відхиляє розібраний HTML, OpenClaw повторює спробу як звичайний текст.
+ - Сирий HTML моделі екранується, щоб зменшити кількість помилок розбору в Telegram.
+ - Якщо Telegram відхиляє оброблений HTML, OpenClaw повторює спробу як звичайний текст.
- Попередній перегляд посилань увімкнено типово, його можна вимкнути через `channels.telegram.linkPreview: false`.
+ Попередній перегляд посилань увімкнено за замовчуванням і його можна вимкнути через `channels.telegram.linkPreview: false`.
Реєстрація меню команд Telegram виконується під час запуску через `setMyCommands`.
- Типові значення нативних команд:
+ Нативні команди за замовчуванням:
- `commands.native: "auto"` вмикає нативні команди для Telegram
- Додайте користувацькі записи меню команд:
+ Додайте власні записи до меню команд:
```json5
{
@@ -338,45 +336,45 @@ curl "https://api.telegram.org/bot/getUpdates"
Правила:
- - назви нормалізуються (забирається початковий `/`, нижній регістр)
+ - імена нормалізуються (прибирається початковий `/`, переводяться в нижній регістр)
- допустимий шаблон: `a-z`, `0-9`, `_`, довжина `1..32`
- користувацькі команди не можуть перевизначати нативні команди
- - конфлікти/дублікати пропускаються та журналюються
+ - конфлікти/дублікати пропускаються й записуються в журнал
Примітки:
- користувацькі команди — це лише записи меню; вони не реалізують поведінку автоматично
- - команди plugin/skill усе одно можуть працювати при введенні вручну, навіть якщо вони не показані в меню Telegram
+ - команди plugin/skills все одно можуть працювати під час ручного введення, навіть якщо вони не показані в меню Telegram
- Якщо нативні команди вимкнено, вбудовані команди видаляються. Користувацькі команди/команди plugin все одно можуть реєструватися, якщо це налаштовано.
+ Якщо нативні команди вимкнено, вбудовані команди видаляються. Користувацькі команди/команди plugin все ще можуть реєструватися, якщо це налаштовано.
- Поширені збої налаштування:
+ Поширені збої під час налаштування:
- - `setMyCommands failed` з `BOT_COMMANDS_TOO_MUCH` означає, що меню Telegram усе ще переповнене навіть після скорочення; зменште кількість команд plugin/skill/користувацьких команд або вимкніть `channels.telegram.commands.native`.
- - `setMyCommands failed` з помилками network/fetch зазвичай означає, що вихідний DNS/HTTPS доступ до `api.telegram.org` заблокований.
+ - `setMyCommands failed` із `BOT_COMMANDS_TOO_MUCH` означає, що меню Telegram все ще переповнене навіть після скорочення; зменште кількість команд plugin/skills/користувацьких команд або вимкніть `channels.telegram.commands.native`.
+ - `setMyCommands failed` із помилками network/fetch зазвичай означає, що вихідні DNS/HTTPS-з’єднання до `api.telegram.org` заблоковані.
- ### Команди підключення пристрою (`device-pair` plugin)
+ ### Команди пейрингу пристрою (plugin `device-pair`)
Коли встановлено plugin `device-pair`:
1. `/pair` генерує код налаштування
2. вставте код у застосунок iOS
- 3. `/pair pending` показує список запитів, що очікують підтвердження (включно з роллю/областями доступу)
+ 3. `/pair pending` показує список запитів, що очікують на розгляд (включно з role/scopes)
4. схваліть запит:
- `/pair approve ` для явного схвалення
- - `/pair approve`, коли є лише один запит, що очікує
+ - `/pair approve`, коли є лише один запит, що очікує на розгляд
- `/pair approve latest` для найновішого
- Код налаштування містить короткоживучий bootstrap token. Вбудована передача bootstrap зберігає токен primary node на рівні `scopes: []`; будь-який переданий operator token залишається обмеженим `operator.approvals`, `operator.read`, `operator.talk.secrets` і `operator.write`. Перевірки bootstrap scopes мають префікс ролі, тому цей allowlist для operator задовольняє лише запити operator; для ролей, що не є operator, усе ще потрібні scopes під власним префіксом ролі.
+ Код налаштування містить короткоживучий bootstrap-токен. Вбудована передача bootstrap зберігає токен primary node на `scopes: []`; будь-який переданий токен оператора залишається обмеженим `operator.approvals`, `operator.read`, `operator.talk.secrets` і `operator.write`. Перевірки bootstrap-scopes мають префікс role, тому цей allowlist оператора задовольняє лише запити оператора; ролям, що не є оператором, як і раніше потрібні scopes під префіксом їхньої власної role.
- Якщо пристрій повторює спробу зі зміненими даними auth (наприклад, role/scopes/public key), попередній запит, що очікує, замінюється, а новий запит використовує інший `requestId`. Перед схваленням знову виконайте `/pair pending`.
+ Якщо пристрій повторює запит зі зміненими даними auth (наприклад, role/scopes/public key), попередній запит, що очікував на розгляд, замінюється, а новий запит використовує інший `requestId`. Перед схваленням знову виконайте `/pair pending`.
- Докладніше: [Підключення](/uk/channels/pairing#pair-via-telegram-recommended-for-ios).
+ Докладніше: [Пейринг](/uk/channels/pairing#pair-via-telegram-recommended-for-ios).
-
- Налаштуйте область дії вбудованої клавіатури:
+
+ Налаштуйте область дії inline-клавіатури:
```json5
{
@@ -414,7 +412,7 @@ curl "https://api.telegram.org/bot/getUpdates"
- `dm`
- `group`
- `all`
- - `allowlist` (типово)
+ - `allowlist` (за замовчуванням)
Застаріле `capabilities: ["inlineButtons"]` зіставляється з `inlineButtons: "all"`.
@@ -425,13 +423,13 @@ curl "https://api.telegram.org/bot/getUpdates"
action: "send",
channel: "telegram",
to: "123456789",
- message: "Choose an option:",
+ message: "Виберіть варіант:",
buttons: [
[
- { text: "Yes", callback_data: "yes" },
- { text: "No", callback_data: "no" },
+ { text: "Так", callback_data: "yes" },
+ { text: "Ні", callback_data: "no" },
],
- [{ text: "Cancel", callback_data: "cancel" }],
+ [{ text: "Скасувати", callback_data: "cancel" }],
],
}
```
@@ -441,64 +439,64 @@ curl "https://api.telegram.org/bot/getUpdates"
-
+
Дії інструментів Telegram включають:
- - `sendMessage` (`to`, `content`, необов’язково `mediaUrl`, `replyToMessageId`, `messageThreadId`)
+ - `sendMessage` (`to`, `content`, необов’язкові `mediaUrl`, `replyToMessageId`, `messageThreadId`)
- `react` (`chatId`, `messageId`, `emoji`)
- `deleteMessage` (`chatId`, `messageId`)
- `editMessage` (`chatId`, `messageId`, `content`)
- - `createForumTopic` (`chatId`, `name`, необов’язково `iconColor`, `iconCustomEmojiId`)
+ - `createForumTopic` (`chatId`, `name`, необов’язкові `iconColor`, `iconCustomEmojiId`)
Дії повідомлень каналу надають зручні псевдоніми (`send`, `react`, `delete`, `edit`, `sticker`, `sticker-search`, `topic-create`).
- Керування доступом:
+ Елементи керування доступом:
- `channels.telegram.actions.sendMessage`
- `channels.telegram.actions.deleteMessage`
- `channels.telegram.actions.reactions`
- - `channels.telegram.actions.sticker` (типово: вимкнено)
+ - `channels.telegram.actions.sticker` (за замовчуванням: вимкнено)
- Примітка: `edit` і `topic-create` наразі типово увімкнені й не мають окремих перемикачів `channels.telegram.actions.*`.
- Надсилання під час runtime використовує активний знімок config/secrets (startup/reload), тому шляхи дій не виконують ad-hoc повторного визначення SecretRef для кожного надсилання.
+ Примітка: `edit` і `topic-create` наразі ввімкнені за замовчуванням і не мають окремих перемикачів `channels.telegram.actions.*`.
+ Надсилання під час runtime використовує активний знімок config/secrets (startup/reload), тому шляхи дій не виконують спеціального повторного розв’язання SecretRef для кожного надсилання.
Семантика видалення реакцій: [/tools/reactions](/uk/tools/reactions)
-
- Telegram підтримує явні теги тредингу відповідей у згенерованому виводі:
+
+ Telegram підтримує явні теги тредів відповіді у згенерованому виводі:
- - `[[reply_to_current]]` відповідає на повідомлення, яке ініціювало дію
+ - `[[reply_to_current]]` відповідає на повідомлення, що ініціювало дію
- `[[reply_to:]]` відповідає на конкретний ID повідомлення Telegram
`channels.telegram.replyToMode` керує обробкою:
- - `off` (типово)
+ - `off` (за замовчуванням)
- `first`
- `all`
- Примітка: `off` вимикає неявний threading відповідей. Явні теги `[[reply_to_*]]` усе одно враховуються.
+ Примітка: `off` вимикає неявні треди відповіді. Явні теги `[[reply_to_*]]` усе одно враховуються.
- Супергрупи форумів:
+ Супергрупи форуму:
- ключі сесій тем додають `:topic:`
- відповіді та індикатор набору тексту спрямовуються в тред теми
- - шлях config для тем:
+ - шлях config теми:
`channels.telegram.groups..topics.`
- Спеціальний випадок для загальної теми (`threadId=1`):
+ Особливий випадок загальної теми (`threadId=1`):
- надсилання повідомлень пропускає `message_thread_id` (Telegram відхиляє `sendMessage(...thread_id=1)`)
- - дії набору тексту все одно включають `message_thread_id`
+ - дії індикатора набору тексту все одно включають `message_thread_id`
- Успадкування тем: записи тем успадковують налаштування групи, якщо їх не перевизначено (`requireMention`, `allowFrom`, `skills`, `systemPrompt`, `enabled`, `groupPolicy`).
- `agentId` призначений лише для тем і не успадковується з типових значень групи.
+ Успадкування тем: записи тем успадковують налаштування групи, якщо не перевизначено (`requireMention`, `allowFrom`, `skills`, `systemPrompt`, `enabled`, `groupPolicy`).
+ `agentId` належить лише до теми й не успадковується з налаштувань групи за замовчуванням.
- **Маршрутизація агентів для окремих тем**: Кожна тема може спрямовуватися до іншого агента через встановлення `agentId` у config теми. Це надає кожній темі власний ізольований workspace, пам’ять і сесію. Приклад:
+ **Маршрутизація агентів для окремих тем**: Кожна тема може маршрутизуватися до іншого агента через налаштування `agentId` у config теми. Це надає кожній темі власний ізольований workspace, пам’ять і сесію. Приклад:
```json5
{
@@ -509,7 +507,7 @@ curl "https://api.telegram.org/bot/getUpdates"
topics: {
"1": { agentId: "main" }, // Загальна тема → агент main
"3": { agentId: "zu" }, // Тема розробки → агент zu
- "5": { agentId: "coder" } // Рев’ю коду → агент coder
+ "5": { agentId: "coder" } // Перевірка коду → агент coder
}
}
}
@@ -520,21 +518,21 @@ curl "https://api.telegram.org/bot/getUpdates"
Тоді кожна тема має власний ключ сесії: `agent:zu:telegram:group:-1001234567890:topic:3`
- **Постійне прив’язування тем ACP**: Теми форуму можуть закріплювати сесії ACP harness через типізовані ACP bindings верхнього рівня (`bindings[]` з `type: "acp"` і `match.channel: "telegram"`, `peer.kind: "group"` та ID з указанням теми на кшталт `-1001234567890:topic:42`). Наразі це обмежено темами форумів у групах/супергрупах. Див. [ACP Agents](/uk/tools/acp-agents).
+ **Постійне прив’язування тем ACP**: Теми форуму можуть закріплювати сесії harness ACP через типізовані прив’язки ACP верхнього рівня (`bindings[]` з `type: "acp"` і `match.channel: "telegram"`, `peer.kind: "group"` та ID з кваліфікацією теми, наприклад `-1001234567890:topic:42`). Наразі це обмежено темами форумів у group/supergroup. Див. [ACP Agents](/uk/tools/acp-agents).
- **Прив’язаний до треду запуск ACP із чату**: `/acp spawn --thread here|auto` прив’язує поточну тему до нової сесії ACP; подальші повідомлення маршрутизуються туди напряму. OpenClaw закріплює підтвердження запуску в самій темі. Потрібно `channels.telegram.threadBindings.spawnAcpSessions=true`.
+ **Створення ACP, прив’язаного до треду, з чату**: `/acp spawn --thread here|auto` прив’язує поточну тему до нової сесії ACP; подальші запити маршрутизуються туди безпосередньо. OpenClaw закріплює підтвердження створення в межах теми. Потрібно `channels.telegram.threadBindings.spawnAcpSessions=true`.
- Контекст шаблонів надає `MessageThreadId` і `IsForum`. DM-чати з `message_thread_id` зберігають DM-маршрутизацію, але використовують ключі сесій з урахуванням тредів.
+ Контекст шаблону надає `MessageThreadId` і `IsForum`. DM-чати з `message_thread_id` зберігають маршрутизацію DM, але використовують ключі сесій з урахуванням тредів.
### Аудіоповідомлення
- Telegram розрізняє голосові нотатки та аудіофайли.
+ Telegram розрізняє голосові повідомлення та аудіофайли.
- - типово: поведінка аудіофайлу
- - тег `[[audio_as_voice]]` у відповіді агента примусово надсилає як голосову нотатку
+ - за замовчуванням: поведінка аудіофайлу
+ - тег `[[audio_as_voice]]` у відповіді агента, щоб примусово надсилати як голосове повідомлення
Приклад дії повідомлення:
@@ -550,7 +548,7 @@ curl "https://api.telegram.org/bot/getUpdates"
### Відеоповідомлення
- Telegram розрізняє відеофайли та video notes.
+ Telegram розрізняє відеофайли та відеозамітки.
Приклад дії повідомлення:
@@ -564,15 +562,15 @@ curl "https://api.telegram.org/bot/getUpdates"
}
```
- Video notes не підтримують підписи; наданий текст повідомлення надсилається окремо.
+ Відеозамітки не підтримують підписи; наданий текст повідомлення надсилається окремо.
### Стікери
Обробка вхідних стікерів:
- - статичні WEBP: завантажуються та обробляються (заповнювач ``)
- - анімовані TGS: пропускаються
- - відео WEBM: пропускаються
+ - статичний WEBP: завантажується й обробляється (заповнювач ``)
+ - анімований TGS: пропускається
+ - відео WEBM: пропускається
Поля контексту стікера:
@@ -588,7 +586,7 @@ curl "https://api.telegram.org/bot/getUpdates"
Стікери описуються один раз (коли це можливо) і кешуються, щоб зменшити кількість повторних викликів vision.
- Увімкніть дії для стікерів:
+ Увімкніть дії зі стікерами:
```json5
{
@@ -627,52 +625,52 @@ curl "https://api.telegram.org/bot/getUpdates"
- Реакції Telegram надходять як оновлення `message_reaction` (окремо від payload повідомлень).
+ Реакції Telegram надходять як оновлення `message_reaction` (окремо від корисного навантаження повідомлень).
- Коли цю функцію ввімкнено, OpenClaw ставить у чергу системні події на кшталт:
+ Коли це ввімкнено, OpenClaw ставить у чергу системні події на кшталт:
- `Telegram reaction added: 👍 by Alice (@alice) on msg 42`
Config:
- - `channels.telegram.reactionNotifications`: `off | own | all` (типово: `own`)
- - `channels.telegram.reactionLevel`: `off | ack | minimal | extensive` (типово: `minimal`)
+ - `channels.telegram.reactionNotifications`: `off | own | all` (за замовчуванням: `own`)
+ - `channels.telegram.reactionLevel`: `off | ack | minimal | extensive` (за замовчуванням: `minimal`)
Примітки:
- - `own` означає лише реакції користувачів на повідомлення, надіслані ботом (best-effort через кеш надісланих повідомлень).
- - Події реакцій усе одно поважають механізми контролю доступу Telegram (`dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`); неавторизовані відправники відкидаються.
+ - `own` означає лише реакції користувачів на повідомлення, надіслані ботом (у режимі best-effort через кеш надісланих повідомлень).
+ - Події реакцій усе одно поважають елементи керування доступом Telegram (`dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`); неавторизовані відправники відкидаються.
- Telegram не надає ID тредів в оновленнях реакцій.
- групи без форуму маршрутизуються до сесії групового чату
- - групи форуму маршрутизуються до сесії загальної теми групи (`:topic:1`), а не до точної початкової теми
+ - групи форуму маршрутизуються до сесії загальної теми групи (`:topic:1`), а не до точної вихідної теми
`allowed_updates` для polling/webhook автоматично включають `message_reaction`.
- `ackReaction` надсилає emoji підтвердження, поки OpenClaw обробляє вхідне повідомлення.
+ `ackReaction` надсилає emoji-підтвердження, поки OpenClaw обробляє вхідне повідомлення.
Порядок визначення:
- `channels.telegram.accounts..ackReaction`
- `channels.telegram.ackReaction`
- `messages.ackReaction`
- - резервний emoji з identity агента (`agents.list[].identity.emoji`, інакше "👀")
+ - резервний emoji ідентичності агента (`agents.list[].identity.emoji`, інакше "👀")
Примітки:
- - Telegram очікує Unicode emoji (наприклад, "👀").
+ - Telegram очікує unicode-emoji (наприклад, "👀").
- Використовуйте `""`, щоб вимкнути реакцію для каналу або облікового запису.
- Записи в config каналу типово увімкнені (`configWrites !== false`).
+ Записи config каналу ввімкнені за замовчуванням (`configWrites !== false`).
Записи, ініційовані Telegram, включають:
- - події міграції груп (`migrate_to_chat_id`) для оновлення `channels.telegram.groups`
+ - події міграції групи (`migrate_to_chat_id`) для оновлення `channels.telegram.groups`
- `/config set` і `/config unset` (потрібне ввімкнення команд)
Вимкнення:
@@ -689,35 +687,35 @@ curl "https://api.telegram.org/bot/getUpdates"
-
- Типово використовується long polling. Для режиму webhook задайте `channels.telegram.webhookUrl` і `channels.telegram.webhookSecret`; також необов’язково `webhookPath`, `webhookHost`, `webhookPort` (типові значення: `/telegram-webhook`, `127.0.0.1`, `8787`).
+
+ За замовчуванням використовується long polling. Для режиму webhook задайте `channels.telegram.webhookUrl` і `channels.telegram.webhookSecret`; необов’язково `webhookPath`, `webhookHost`, `webhookPort` (за замовчуванням `/telegram-webhook`, `127.0.0.1`, `8787`).
- Локальний listener прив’язується до `127.0.0.1:8787`. Для публічного ingress або поставте reverse proxy перед локальним портом, або свідомо задайте `webhookHost: "0.0.0.0"`.
+ Локальний слухач прив’язується до `127.0.0.1:8787`. Для публічного ingress або розмістіть reverse proxy перед локальним портом, або свідомо задайте `webhookHost: "0.0.0.0"`.
- - Типове значення `channels.telegram.textChunkLimit` — 4000.
- - `channels.telegram.chunkMode="newline"` надає перевагу межам абзаців (порожнім рядкам) перед поділом за довжиною.
- - `channels.telegram.mediaMaxMb` (типово 100) обмежує розмір вхідних і вихідних медіа Telegram.
- - `channels.telegram.timeoutSeconds` перевизначає timeout клієнта Telegram API (якщо не задано, застосовується типове значення grammY).
- - `channels.telegram.pollingStallThresholdMs` типово дорівнює `120000`; налаштовуйте в межах `30000`–`600000` лише для хибнопозитивних перезапусків через зупинку polling.
- - Історія контексту групи використовує `channels.telegram.historyLimit` або `messages.groupChat.historyLimit` (типово 50); `0` вимикає цю функцію.
- - Додатковий контекст reply/quote/forward наразі передається як отримано.
- - Telegram allowlist здебільшого визначають, хто може викликати агента, а не є повною межею редагування додаткового контексту.
- - Керування історією DM:
+ - значення `channels.telegram.textChunkLimit` за замовчуванням — 4000.
+ - `channels.telegram.chunkMode="newline"` надає перевагу межам абзаців (порожнім рядкам) перед розбиттям за довжиною.
+ - `channels.telegram.mediaMaxMb` (за замовчуванням 100) обмежує максимальний розмір вхідних і вихідних медіафайлів Telegram.
+ - `channels.telegram.timeoutSeconds` перевизначає тайм-аут клієнта Telegram API (якщо не задано, застосовується значення grammY за замовчуванням).
+ - `channels.telegram.pollingStallThresholdMs` за замовчуванням дорівнює `120000`; налаштовуйте в межах від `30000` до `600000` лише для хибнопозитивних перезапусків через зависання polling.
+ - історія контексту групи використовує `channels.telegram.historyLimit` або `messages.groupChat.historyLimit` (за замовчуванням 50); `0` вимикає.
+ - додатковий контекст reply/quote/forward наразі передається як отримано.
+ - allowlist у Telegram насамперед обмежують, хто може викликати агента, а не є повною межею редагування додаткового контексту.
+ - елементи керування історією DM:
- `channels.telegram.dmHistoryLimit`
- `channels.telegram.dms[""].historyLimit`
- - Config `channels.telegram.retry` застосовується до допоміжних функцій надсилання Telegram (CLI/tools/actions) для відновлюваних вихідних помилок API.
+ - config `channels.telegram.retry` застосовується до допоміжних функцій надсилання Telegram (CLI/tools/actions) для відновлюваних вихідних помилок API.
- Ціль надсилання CLI може бути числовим ID чату або username:
+ Ціллю надсилання в CLI може бути числовий ID чату або ім’я користувача:
```bash
openclaw message send --channel telegram --target 123456789 --message "hi"
openclaw message send --channel telegram --target @name --message "hi"
```
- Telegram polls використовують `openclaw message poll` і підтримують теми форуму:
+ Для опитувань Telegram використовується `openclaw message poll`, також підтримуються теми форумів:
```bash
openclaw message poll --channel telegram --target 123456789 \
@@ -727,55 +725,55 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \
--poll-duration-seconds 300 --poll-public
```
- Прапорці poll лише для Telegram:
+ Прапорці опитувань лише для Telegram:
- `--poll-duration-seconds` (5-600)
- `--poll-anonymous`
- `--poll-public`
- `--thread-id` для тем форуму (або використовуйте ціль `:topic:`)
- Надсилання Telegram також підтримує:
+ Надсилання в Telegram також підтримує:
- - `--presentation` з блоками `buttons` для вбудованих клавіатур, коли це дозволяє `channels.telegram.capabilities.inlineButtons`
- - `--pin` або `--delivery '{"pin":true}'`, щоб запитати закріплену доставку, коли бот може закріплювати повідомлення в цьому чаті
- - `--force-document`, щоб надсилати вихідні зображення та GIF як документи замість стислих фото або завантажень анімованих медіа
+ - `--presentation` з блоками `buttons` для inline-клавіатур, якщо це дозволяє `channels.telegram.capabilities.inlineButtons`
+ - `--pin` або `--delivery '{"pin":true}'` для запиту закріпленої доставки, коли бот може закріплювати в цьому чаті
+ - `--force-document`, щоб надсилати вихідні зображення та GIF як документи, а не як стислі фото або завантаження анімованих медіа
- Керування діями:
+ Керування доступом до дій:
- - `channels.telegram.actions.sendMessage=false` вимикає вихідні повідомлення Telegram, включно з polls
- - `channels.telegram.actions.poll=false` вимикає створення polls у Telegram, залишаючи звичайне надсилання увімкненим
+ - `channels.telegram.actions.sendMessage=false` вимикає вихідні повідомлення Telegram, включно з опитуваннями
+ - `channels.telegram.actions.poll=false` вимикає створення опитувань Telegram, залишаючи звичайні надсилання ввімкненими
- Telegram підтримує погодження exec у DM затверджувачів і за бажанням може публікувати запити у вихідному чаті або темі. Затверджувачі мають бути числовими ID користувачів Telegram.
+ Telegram підтримує погодження exec у DM користувачів, які погоджують, і за бажанням може публікувати запити у вихідному чаті або темі. Користувачі, які погоджують, мають бути вказані як числові ID користувачів Telegram.
Шлях config:
- - `channels.telegram.execApprovals.enabled` (вмикається автоматично, коли вдається визначити принаймні одного затверджувача)
- - `channels.telegram.execApprovals.approvers` (використовує як резервний варіант числові ID власників із `allowFrom` / `defaultTo`)
- - `channels.telegram.execApprovals.target`: `dm` (типово) | `channel` | `both`
+ - `channels.telegram.execApprovals.enabled` (автоматично вмикається, коли можна визначити принаймні одного користувача, який погоджує)
+ - `channels.telegram.execApprovals.approvers` (резервно використовує числові ID власників з `allowFrom` / `defaultTo`)
+ - `channels.telegram.execApprovals.target`: `dm` (за замовчуванням) | `channel` | `both`
- `agentFilter`, `sessionFilter`
- Доставка в канал показує текст команди в чаті; вмикайте `channel` або `both` лише в довірених групах/темах. Коли запит потрапляє в тему форуму, OpenClaw зберігає тему для запиту на погодження та подальшої взаємодії. Погодження exec типово спливають через 30 хвилин.
+ Доставка в канал показує текст команди в чаті; вмикайте `channel` або `both` лише в довірених групах/темах. Коли запит потрапляє в тему форуму, OpenClaw зберігає тему для запиту на погодження і подальшої взаємодії. За замовчуванням термін дії погоджень exec спливає через 30 хвилин.
- Вбудовані кнопки погодження також вимагають, щоб `channels.telegram.capabilities.inlineButtons` дозволяв цільову поверхню (`dm`, `group` або `all`). ID погоджень із префіксом `plugin:` визначаються через погодження plugin; інші спочатку визначаються через погодження exec.
+ Inline-кнопки погодження також вимагають, щоб `channels.telegram.capabilities.inlineButtons` дозволяв цільову поверхню (`dm`, `group` або `all`). ID погоджень із префіксом `plugin:` обробляються через погодження plugin; інші спочатку обробляються через погодження exec.
- Див. [Exec approvals](/uk/tools/exec-approvals).
+ Див. [Погодження exec](/uk/tools/exec-approvals).
-## Керування відповідями на помилки
+## Елементи керування відповідями про помилки
-Коли агент стикається з помилкою доставки або помилкою провайдера, Telegram може або відповісти текстом помилки, або приглушити її. Цю поведінку керують два ключі config:
+Коли агент стикається з помилкою доставки або провайдера, Telegram може або відповісти текстом помилки, або приховати її. Цю поведінку керують два ключі config:
| Key | Values | Default | Description |
| ----------------------------------- | ----------------- | ------- | ----------------------------------------------------------------------------------------------- |
-| `channels.telegram.errorPolicy` | `reply`, `silent` | `reply` | `reply` надсилає до чату зрозуміле повідомлення про помилку. `silent` повністю приглушує відповіді з помилками. |
-| `channels.telegram.errorCooldownMs` | number (ms) | `60000` | Мінімальний час між відповідями з помилками в тому самому чаті. Запобігає спаму помилками під час збоїв. |
+| `channels.telegram.errorPolicy` | `reply`, `silent` | `reply` | `reply` надсилає дружнє повідомлення про помилку в чат. `silent` повністю приглушує відповіді про помилки. |
+| `channels.telegram.errorCooldownMs` | number (ms) | `60000` | Мінімальний час між відповідями про помилки в тому самому чаті. Запобігає спаму помилок під час збоїв. |
-Підтримуються перевизначення для окремого облікового запису, групи та теми (таке саме успадкування, як і для інших ключів config Telegram).
+Підтримуються перевизначення для окремих облікових записів, груп і тем (те саме успадкування, що й для інших ключів config Telegram).
```json5
{
@@ -793,45 +791,45 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \
}
```
-## Усунення проблем
+## Усунення неполадок
-
+
- Якщо `requireMention=false`, режим конфіденційності Telegram має дозволяти повну видимість.
- BotFather: `/setprivacy` -> Disable
- - потім видаліть бота з групи та додайте його знову
- - `openclaw channels status` попереджає, коли config очікує повідомлення групи без згадування.
- - `openclaw channels status --probe` може перевіряти явні числові ID груп; wildcard `"*"` не можна перевірити через probe членства.
+ - потім видаліть і знову додайте бота в групу
+ - `openclaw channels status` попереджає, коли config очікує повідомлення в групі без згадки.
+ - `openclaw channels status --probe` може перевіряти явні числові ID груп; для шаблону `"*"` перевірка членства недоступна.
- швидкий тест сесії: `/activation always`.
-
+
- - коли існує `channels.telegram.groups`, група має бути вказана в списку (або має бути `"*"`)
+ - коли існує `channels.telegram.groups`, група має бути вказана в списку (або включати `"*"`)
- перевірте, що бот є учасником групи
- - перегляньте логи: `openclaw logs --follow`, щоб знайти причини пропуску
+ - перегляньте журнали: `openclaw logs --follow`, щоб побачити причини пропуску
-
+
- - авторизуйте свою ідентичність відправника (pairing та/або числовий `allowFrom`)
- - авторизація команд усе одно застосовується, навіть коли політика групи `open`
- - `setMyCommands failed` з `BOT_COMMANDS_TOO_MUCH` означає, що нативне меню має забагато записів; зменште кількість команд plugin/skill/користувацьких команд або вимкніть нативні меню
- - `setMyCommands failed` з помилками network/fetch зазвичай вказує на проблеми доступності DNS/HTTPS до `api.telegram.org`
+ - авторизуйте свою ідентичність відправника (пейринг та/або числовий `allowFrom`)
+ - авторизація команд усе одно застосовується, навіть коли політика групи — `open`
+ - `setMyCommands failed` із `BOT_COMMANDS_TOO_MUCH` означає, що нативне меню має забагато записів; зменште кількість команд plugin/skills/користувацьких команд або вимкніть нативні меню
+ - `setMyCommands failed` з помилками network/fetch зазвичай вказує на проблеми з доступністю DNS/HTTPS до `api.telegram.org`
- - Node 22+ + custom fetch/proxy можуть спричиняти негайне переривання, якщо типи AbortSignal не збігаються.
- - Деякі хости спочатку визначають `api.telegram.org` в IPv6; несправний вихід через IPv6 може спричиняти переривчасті збої Telegram API.
- - Якщо логи містять `TypeError: fetch failed` або `Network request for 'getUpdates' failed!`, OpenClaw тепер повторює такі спроби як відновлювані мережеві помилки.
- - Якщо логи містять `Polling stall detected`, OpenClaw перезапускає polling і перебудовує транспорт Telegram після 120 секунд без завершеного сигналу живості long poll за замовчуванням.
- - Збільшуйте `channels.telegram.pollingStallThresholdMs` лише тоді, коли довготривалі виклики `getUpdates` є здоровими, але ваш хост усе ще повідомляє про хибні перезапуски через зупинку polling. Постійні зупинки зазвичай вказують на проблеми proxy, DNS, IPv6 або TLS-виходу між хостом і `api.telegram.org`.
- - На VPS-хостах із нестабільним прямим виходом/TLS спрямовуйте виклики Telegram API через `channels.telegram.proxy`:
+ - Node 22+ + користувацький fetch/proxy можуть спричиняти негайне переривання, якщо типи AbortSignal не збігаються.
+ - Деякі хости спочатку визначають `api.telegram.org` у IPv6; несправний вихід через IPv6 може спричиняти періодичні збої Telegram API.
+ - Якщо журнали містять `TypeError: fetch failed` або `Network request for 'getUpdates' failed!`, OpenClaw тепер повторює такі запити як відновлювані мережеві помилки.
+ - Якщо журнали містять `Polling stall detected`, OpenClaw перезапускає polling і перебудовує транспорт Telegram після 120 секунд без завершеної ознаки активності long-poll за замовчуванням.
+ - Збільшуйте `channels.telegram.pollingStallThresholdMs` лише тоді, коли довготривалі виклики `getUpdates` працюють нормально, але ваш хост усе одно повідомляє про хибні перезапуски через зависання polling. Постійні зависання зазвичай вказують на проблеми з proxy, DNS, IPv6 або TLS-виходом між хостом і `api.telegram.org`.
+ - На VPS-хостах із нестабільним прямим виходом/TLS маршрутизуйте виклики Telegram API через `channels.telegram.proxy`:
```yaml
channels:
@@ -839,8 +837,8 @@ channels:
proxy: socks5://:@proxy-host:1080
```
- - Node 22+ типово використовує `autoSelectFamily=true` (крім WSL2) і `dnsResultOrder=ipv4first`.
- - Якщо ваш хост — WSL2 або явно краще працює лише з IPv4, примусово задайте вибір сімейства:
+ - Node 22+ за замовчуванням використовує `autoSelectFamily=true` (крім WSL2) і `dnsResultOrder=ipv4first`.
+ - Якщо ваш хост працює під WSL2 або явно краще працює в режимі лише IPv4, примусово задайте вибір сімейства:
```yaml
channels:
@@ -849,10 +847,10 @@ channels:
autoSelectFamily: false
```
- - Відповіді з діапазону benchmark RFC 2544 (`198.18.0.0/15`) уже типово дозволені
- для завантажень медіа Telegram. Якщо довірений fake-IP або
+ - Відповіді з діапазону тестування RFC 2544 (`198.18.0.0/15`) уже дозволені
+ за замовчуванням для завантаження медіа Telegram. Якщо довірений fake-IP або
transparent proxy переписує `api.telegram.org` на якусь іншу
- приватну/внутрішню/special-use адресу під час завантаження медіа, ви можете
+ приватну/внутрішню/спеціальну адресу під час завантаження медіа, ви можете
явно ввімкнути обхід лише для Telegram:
```yaml
@@ -865,22 +863,23 @@ channels:
- Те саме явне ввімкнення доступне для окремого облікового запису в
`channels.telegram.accounts..network.dangerouslyAllowPrivateNetwork`.
- Якщо ваш proxy визначає медіахости Telegram у `198.18.x.x`, спочатку залиште
- dangerous flag вимкненим. Медіа Telegram уже типово дозволяє діапазон
- benchmark RFC 2544.
+ небезпечний прапорець вимкненим. Медіа Telegram уже за замовчуванням дозволяє
+ діапазон тестування RFC 2544.
`channels.telegram.network.dangerouslyAllowPrivateNetwork` послаблює захист
- Telegram media SSRF. Використовуйте його лише в довірених, контрольованих оператором proxy-середовищах,
- таких як fake-IP-маршрутизація Clash, Mihomo або Surge, коли вони
- синтезують приватні або special-use відповіді поза діапазоном
- benchmark RFC 2544. Для звичайного публічного доступу Telegram через інтернет залишайте це вимкненим.
+ медіа Telegram від SSRF. Використовуйте це лише в довірених середовищах proxy,
+ контрольованих оператором, таких як Clash, Mihomo або маршрутизація Surge fake-IP,
+ коли вони синтезують приватні або спеціальні відповіді поза діапазоном
+ тестування RFC 2544. Для звичайного публічного доступу до Telegram через інтернет
+ залишайте цей параметр вимкненим.
- - Перевизначення через середовище (тимчасові):
+ - Перевизначення через середовище (тимчасово):
- `OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1`
- `OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1`
- `OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first`
- - Перевірка відповідей DNS:
+ - Перевірте відповіді DNS:
```bash
dig +short api.telegram.org A
@@ -890,84 +889,19 @@ dig +short api.telegram.org AAAA
-Більше допомоги: [Усунення проблем каналу](/uk/channels/troubleshooting).
+Більше допомоги: [Усунення неполадок каналу](/uk/channels/troubleshooting).
-## Вказівники на довідник config Telegram
+## Довідник конфігурації
-Основний довідник:
+Основний довідник: [Довідник конфігурації - Telegram](/uk/gateway/configuration-reference#telegram).
-- `channels.telegram.enabled`: увімкнути/вимкнути запуск каналу.
-- `channels.telegram.botToken`: токен бота (BotFather).
-- `channels.telegram.tokenFile`: зчитувати токен зі шляху до звичайного файлу. Символічні посилання відхиляються.
-- `channels.telegram.dmPolicy`: `pairing | allowlist | open | disabled` (типово: pairing).
-- `channels.telegram.allowFrom`: allowlist для DM (числові ID користувачів Telegram). `allowlist` вимагає принаймні один ID відправника. `open` вимагає `"*"`. `openclaw doctor --fix` може перетворити застарілі записи `@username` на ID і може відновити записи allowlist з файлів pairing-store у сценаріях міграції allowlist.
-- `channels.telegram.actions.poll`: увімкнути або вимкнути створення polls у Telegram (типово: увімкнено; все одно потрібен `sendMessage`).
-- `channels.telegram.defaultTo`: типова ціль Telegram, яку використовує CLI `--deliver`, коли не вказано явний `--reply-to`.
-- `channels.telegram.groupPolicy`: `open | allowlist | disabled` (типово: allowlist).
-- `channels.telegram.groupAllowFrom`: allowlist відправників у групах (числові ID користувачів Telegram). `openclaw doctor --fix` може перетворити застарілі записи `@username` на ID. Нечислові записи ігноруються під час auth. Auth груп не використовує резервний варіант DM pairing-store (`2026.2.25+`).
-- Пріоритет для кількох облікових записів:
- - Коли налаштовано два або більше ID облікових записів, задайте `channels.telegram.defaultAccount` (або додайте `channels.telegram.accounts.default`), щоб явно визначити типову маршрутизацію.
- - Якщо не задано жодного з них, OpenClaw повертається до першого нормалізованого ID облікового запису, а `openclaw doctor` показує попередження.
- - `channels.telegram.accounts.default.allowFrom` і `channels.telegram.accounts.default.groupAllowFrom` застосовуються лише до облікового запису `default`.
- - Іменовані облікові записи успадковують `channels.telegram.allowFrom` і `channels.telegram.groupAllowFrom`, коли значення на рівні облікового запису не задані.
- - Іменовані облікові записи не успадковують `channels.telegram.accounts.default.allowFrom` / `groupAllowFrom`.
-- `channels.telegram.groups`: типові значення для кожної групи + allowlist (використовуйте `"*"` для глобальних типових значень).
- - `channels.telegram.groups..groupPolicy`: перевизначення groupPolicy для конкретної групи (`open | allowlist | disabled`).
- - `channels.telegram.groups..requireMention`: типове керування вимогою згадування.
- - `channels.telegram.groups..skills`: фільтр Skills (пропущено = усі Skills, порожньо = жодного).
- - `channels.telegram.groups..allowFrom`: перевизначення allowlist відправників для конкретної групи.
- - `channels.telegram.groups..systemPrompt`: додатковий системний prompt для групи.
- - `channels.telegram.groups..enabled`: вимикає групу, якщо `false`.
- - `channels.telegram.groups..topics..*`: перевизначення для кожної теми (поля групи + `agentId`, який доступний лише для тем).
- - `channels.telegram.groups..topics..agentId`: спрямувати цю тему до конкретного агента (перевизначає маршрутизацію на рівні групи та bindings).
-- `channels.telegram.groups..topics..groupPolicy`: перевизначення groupPolicy для конкретної теми (`open | allowlist | disabled`).
-- `channels.telegram.groups..topics..requireMention`: перевизначення вимоги згадування для конкретної теми.
-- `bindings[]` верхнього рівня з `type: "acp"` і канонічним ID теми `chatId:topic:topicId` у `match.peer.id`: поля постійного прив’язування тем ACP (див. [ACP Agents](/uk/tools/acp-agents#channel-specific-settings)).
-- `channels.telegram.direct..topics..agentId`: спрямувати теми DM до конкретного агента (така сама поведінка, як для тем форуму).
-- `channels.telegram.execApprovals.enabled`: увімкнути Telegram як клієнт погодження exec на основі чату для цього облікового запису.
-- `channels.telegram.execApprovals.approvers`: ID користувачів Telegram, яким дозволено погоджувати або відхиляти запити exec. Необов’язково, якщо `channels.telegram.allowFrom` або прямий `channels.telegram.defaultTo` уже визначає власника.
-- `channels.telegram.execApprovals.target`: `dm | channel | both` (типово: `dm`). `channel` і `both` зберігають вихідну тему Telegram, якщо вона є.
-- `channels.telegram.execApprovals.agentFilter`: необов’язковий фільтр ID агента для пересланих запитів на погодження.
-- `channels.telegram.execApprovals.sessionFilter`: необов’язковий фільтр ключа сесії (підрядок або regex) для пересланих запитів на погодження.
-- `channels.telegram.accounts..execApprovals`: перевизначення маршрутизації погоджень exec у Telegram і авторизації затверджувачів для конкретного облікового запису.
-- `channels.telegram.capabilities.inlineButtons`: `off | dm | group | all | allowlist` (типово: allowlist).
-- `channels.telegram.accounts..capabilities.inlineButtons`: перевизначення для конкретного облікового запису.
-- `channels.telegram.commands.nativeSkills`: увімкнути/вимкнути нативні команди Skills у Telegram.
-- `channels.telegram.replyToMode`: `off | first | all` (типово: `off`).
-- `channels.telegram.textChunkLimit`: розмір вихідних фрагментів (символи).
-- `channels.telegram.chunkMode`: `length` (типово) або `newline`, щоб ділити за порожніми рядками (межами абзаців) перед поділом за довжиною.
-- `channels.telegram.linkPreview`: перемикач попереднього перегляду посилань для вихідних повідомлень (типово: true).
-- `channels.telegram.streaming`: `off | partial | block | progress` (попередній перегляд live stream; типово: `partial`; `progress` зіставляється з `partial`; `block` — сумісність із застарілим режимом preview). Потоковий preview у Telegram використовує одне повідомлення preview, яке редагується на місці.
-- `channels.telegram.streaming.preview.toolProgress`: повторно використовувати повідомлення live preview для оновлень tool/progress, коли активний потоковий preview (типово: `true`). Установіть `false`, щоб зберігати окремі повідомлення tool/progress.
-- `channels.telegram.mediaMaxMb`: обмеження вхідних/вихідних медіа Telegram (МБ, типово: 100).
-- `channels.telegram.retry`: політика повторних спроб для допоміжних функцій надсилання Telegram (CLI/tools/actions) у разі відновлюваних вихідних помилок API (attempts, minDelayMs, maxDelayMs, jitter).
-- `channels.telegram.network.autoSelectFamily`: перевизначити Node autoSelectFamily (true=увімкнути, false=вимкнути). Типово увімкнено в Node 22+, а у WSL2 типово вимкнено.
-- `channels.telegram.network.dnsResultOrder`: перевизначити порядок результатів DNS (`ipv4first` або `verbatim`). Типово `ipv4first` у Node 22+.
-- `channels.telegram.network.dangerouslyAllowPrivateNetwork`: небезпечне явне ввімкнення для довірених середовищ із fake-IP або transparent proxy, де завантаження медіа Telegram визначають `api.telegram.org` як приватні/внутрішні/special-use адреси поза типово дозволеним діапазоном benchmark RFC 2544.
-- `channels.telegram.proxy`: URL proxy для викликів Bot API (SOCKS/HTTP).
-- `channels.telegram.webhookUrl`: увімкнути режим Webhook (потрібен `channels.telegram.webhookSecret`).
-- `channels.telegram.webhookSecret`: секрет webhook (обов’язковий, коли задано webhookUrl).
-- `channels.telegram.webhookPath`: локальний шлях webhook (типово `/telegram-webhook`).
-- `channels.telegram.webhookHost`: локальний хост прив’язування webhook (типово `127.0.0.1`).
-- `channels.telegram.webhookPort`: локальний порт прив’язування webhook (типово `8787`).
-- `channels.telegram.actions.reactions`: керування реакціями інструментів Telegram.
-- `channels.telegram.actions.sendMessage`: керування надсиланням повідомлень інструментів Telegram.
-- `channels.telegram.actions.deleteMessage`: керування видаленням повідомлень інструментів Telegram.
-- `channels.telegram.actions.sticker`: керування діями зі стікерами Telegram — надсилання і пошук (типово: false).
-- `channels.telegram.reactionNotifications`: `off | own | all` — керує тим, які реакції запускають системні події (типово: `own`, якщо не задано).
-- `channels.telegram.reactionLevel`: `off | ack | minimal | extensive` — керує можливостями агента щодо реакцій (типово: `minimal`, якщо не задано).
-- `channels.telegram.errorPolicy`: `reply | silent` — керує поведінкою відповідей на помилки (типово: `reply`). Підтримуються перевизначення для окремого облікового запису/групи/теми.
-- `channels.telegram.errorCooldownMs`: мінімальна кількість мс між відповідями на помилки в тому самому чаті (типово: `60000`). Запобігає спаму помилками під час збоїв.
+
-- [Довідник з конфігурації - Telegram](/uk/gateway/configuration-reference#telegram)
-
-Telegram-специфічні поля з високою цінністю:
-
-- запуск/auth: `enabled`, `botToken`, `tokenFile`, `accounts.*` (`tokenFile` має вказувати на звичайний файл; символічні посилання відхиляються)
-- контроль доступу: `dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`, `groups`, `groups.*.topics.*`, `bindings[]` верхнього рівня (`type: "acp"`)
+- startup/auth: `enabled`, `botToken`, `tokenFile`, `accounts.*` (`tokenFile` має вказувати на звичайний файл; символьні посилання відхиляються)
+- керування доступом: `dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`, `groups`, `groups.*.topics.*`, верхньорівневі `bindings[]` (`type: "acp"`)
- погодження exec: `execApprovals`, `accounts.*.execApprovals`
- команда/меню: `commands.native`, `commands.nativeSkills`, `customCommands`
-- threading/відповіді: `replyToMode`
+- треди/відповіді: `replyToMode`
- streaming: `streaming` (preview), `streaming.preview.toolProgress`, `blockStreaming`
- форматування/доставка: `textChunkLimit`, `chunkMode`, `linkPreview`, `responsePrefix`
- медіа/мережа: `mediaMaxMb`, `timeoutSeconds`, `pollingStallThresholdMs`, `retry`, `network.autoSelectFamily`, `network.dangerouslyAllowPrivateNetwork`, `proxy`
@@ -977,11 +911,31 @@ Telegram-специфічні поля з високою цінністю:
- помилки: `errorPolicy`, `errorCooldownMs`
- записи/історія: `configWrites`, `historyLimit`, `dmHistoryLimit`, `dms.*.historyLimit`
+
+
+
+Пріоритет для кількох облікових записів: коли налаштовано два або більше ID облікових записів, задайте `channels.telegram.defaultAccount` (або включіть `channels.telegram.accounts.default`), щоб явно визначити маршрутизацію за замовчуванням. Інакше OpenClaw використовує перший нормалізований ID облікового запису, а `openclaw doctor` показує попередження. Іменовані облікові записи успадковують `channels.telegram.allowFrom` / `groupAllowFrom`, але не значення `accounts.default.*`.
+
+
## Пов’язане
-- [Підключення](/uk/channels/pairing)
-- [Групи](/uk/channels/groups)
-- [Безпека](/uk/gateway/security)
-- [Маршрутизація каналів](/uk/channels/channel-routing)
-- [Маршрутизація кількох агентів](/uk/concepts/multi-agent)
-- [Усунення проблем](/uk/channels/troubleshooting)
+
+
+ Зв’яжіть користувача Telegram із gateway.
+
+
+ Поведінка allowlist для груп і тем.
+
+
+ Маршрутизуйте вхідні повідомлення до агентів.
+
+
+ Модель загроз і посилення захисту.
+
+
+ Відображайте групи й теми на агентів.
+
+
+ Міжканальна діагностика.
+
+
diff --git a/docs/uk/ci.md b/docs/uk/ci.md
index 79eed70ee..cfd4b8e46 100644
--- a/docs/uk/ci.md
+++ b/docs/uk/ci.md
@@ -2,31 +2,47 @@
read_when:
- Вам потрібно зрозуміти, чому завдання CI запустилося або не запустилося
- Ви налагоджуєте збої перевірок GitHub Actions
-summary: Граф завдань CI, шлюзи областей дії та локальні еквіваленти команд
+summary: Граф завдань CI, обмежувальні перевірки за областю змін і локальні еквіваленти команд
title: Конвеєр CI
x-i18n:
- generated_at: "2026-04-23T18:47:31Z"
+ generated_at: "2026-04-23T19:48:40Z"
model: gpt-5.4
provider: openai
- source_hash: 8cca997a1606bafc08c904bf5527cf6aefb2a0428c2cb7668c757c7a1a08c4e1
+ source_hash: 3e250c90d9be13dc25a0b028de5d72cf821387e33c0965cac7b935579e3c6ae7
source_path: ci.md
workflow: 15
---
# Конвеєр CI
-CI запускається на кожен push до `main` і на кожен pull request. Він використовує розумне визначення областей дії, щоб пропускати дорогі завдання, коли змінилися лише не пов’язані ділянки.
+CI запускається при кожному push у `main` і для кожного pull request. Він використовує розумне обмеження за областю змін, щоб пропускати дорогі завдання, коли змінилися лише не пов’язані частини.
-QA Lab має окремі смуги CI поза основним робочим процесом із розумним визначенням областей дії. Робочий процес
-`Parity gate` запускається для відповідних змін у PR і при ручному запуску; він
-збирає приватний runtime QA і порівнює агентні набори mock GPT-5.4 та Opus 4.6.
-Робочий процес `QA-Lab - All Lanes` запускається щоночі на `main` і при
-ручному запуску; він розгалужує mock parity gate, live Matrix lane і live
-Telegram lane як паралельні завдання. Live-завдання використовують середовище
-`qa-live-shared`, а Telegram lane використовує оренди Convex. `OpenClaw Release
-Checks` також запускає ті самі смуги QA Lab перед погодженням релізу.
+QA Lab має окремі смуги CI поза основним workflow з розумним обмеженням за областю змін. Workflow
+`Parity gate` запускається для відповідних змін у PR і через ручний запуск; він
+збирає приватне QA runtime і порівнює agentic-набори mock GPT-5.4 і Opus 4.6.
+Workflow `QA-Lab - All Lanes` запускається щоночі на `main` і через
+ручний запуск; він розгалужує mock parity gate, live Matrix lane і live
+Telegram lane як паралельні завдання. Live-завдання використовують середовище `qa-live-shared`,
+а Telegram lane використовує Convex leases. `OpenClaw Release
+Checks` також запускає ті самі смуги QA Lab перед схваленням релізу.
-Робочий процес `Duplicate PRs After Merge` — це ручний робочий процес для мейнтейнерів для очищення дублікатів після приземлення змін. Типово він працює в режимі dry-run і закриває лише явно вказані PR, коли `apply=true`. Перед змінами на GitHub він перевіряє, що приземлений PR уже злитий, і що кожен дублікат має або спільне згадане issue, або перетин змінених фрагментів.
+Workflow `Duplicate PRs After Merge` — це ручний maintainer-workflow для
+очищення дублікатів після злиття. За замовчуванням він працює в режимі dry-run і
+закриває лише явно перелічені PR, коли `apply=true`. Перш ніж змінювати GitHub,
+він перевіряє, що злитий PR справді змерджено і що кожен дублікат має або
+спільну згадану issue, або перетин змінених фрагментів.
+
+Workflow `Test Performance Agent` — це подієва службова смуга Codex
+для повільних тестів. Вона не має окремого запуску лише за розкладом:
+її може запустити успішний не-ботовий push CI у `main`, але вона пропускається,
+якщо інший запуск workflow-run уже відбувся або виконується в той самий UTC-день.
+Ручний запуск обходить це денне обмеження активності. Ця смуга будує
+групований звіт продуктивності Vitest для повного набору тестів, дозволяє Codex
+вносити лише невеликі виправлення продуктивності тестів без втрати покриття, а потім
+повторно запускає звіт для повного набору тестів і відхиляє зміни, які зменшують
+кількість базових тестів, що проходять. Якщо в базовому стані є тести, що падають,
+Codex може виправляти лише очевидні збої, а звіт для повного набору після роботи агента
+має пройти повністю, перш ніж щось буде закомічено.
```bash
gh workflow run duplicate-after-merge.yml \
@@ -39,80 +55,83 @@ gh workflow run duplicate-after-merge.yml \
| Завдання | Призначення | Коли запускається |
| -------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------ |
-| `preflight` | Визначає зміни лише в документації, змінені області дії, змінені extensions і будує маніфест CI | Завжди для нечернеткових push і PR |
-| `security-scm-fast` | Виявлення приватних ключів і аудит workflow через `zizmor` | Завжди для нечернеткових push і PR |
-| `security-dependency-audit` | Аудит production lockfile без залежностей щодо попереджень npm | Завжди для нечернеткових push і PR |
-| `security-fast` | Обов’язковий агрегат для швидких завдань безпеки | Завжди для нечернеткових push і PR |
-| `build-artifacts` | Збирає `dist/`, Control UI, перевірки built-artifact і повторно використовувані downstream artifacts | Зміни, що стосуються Node |
-| `checks-fast-core` | Швидкі смуги коректності Linux, такі як перевірки bundled/plugin-contract/protocol | Зміни, що стосуються Node |
-| `checks-fast-contracts-channels` | Шардовані перевірки контрактів каналів зі стабільним агрегованим результатом перевірки | Зміни, що стосуються Node |
-| `checks-node-extensions` | Повні шарди тестів bundled Plugin для всього набору extension | Зміни, що стосуються Node |
-| `checks-node-core-test` | Шарди core Node тестів, без смуг каналів, bundled, контрактів і extensions | Зміни, що стосуються Node |
-| `extension-fast` | Цільові тести лише для змінених bundled plugins | Pull request-и зі змінами в extensions |
-| `check` | Шардований еквівалент основного локального шлюзу: prod types, lint, guards, test types і strict smoke | Зміни, що стосуються Node |
-| `check-additional` | Перевірки архітектури, меж, поверхні extensions, меж пакетів і шардів gateway-watch | Зміни, що стосуються Node |
-| `build-smoke` | Smoke-тести зібраного CLI і smoke перевірка пам’яті під час запуску | Зміни, що стосуються Node |
-| `checks` | Верифікатор для built-artifact тестів каналів плюс сумісність Node 22 лише для push | Зміни, що стосуються Node |
-| `check-docs` | Форматування документації, lint і перевірки зламаних посилань | Змінено документацію |
-| `skills-python` | Ruff + pytest для Skills на основі Python | Зміни, релевантні Python Skills |
-| `checks-windows` | Специфічні для Windows тестові смуги | Зміни, релевантні Windows |
-| `macos-node` | Смуга тестів TypeScript на macOS із використанням спільних built artifacts | Зміни, релевантні macOS |
-| `macos-swift` | Swift lint, збірка і тести для застосунку macOS | Зміни, релевантні macOS |
-| `android` | Android unit-тести для обох flavor плюс одна збірка debug APK | Зміни, релевантні Android |
+| `preflight` | Визначає зміни лише в docs, змінені області, змінені extensions і будує маніфест CI | Завжди для не-чернеткових push і PR |
+| `security-scm-fast` | Виявлення приватних ключів і аудит workflow через `zizmor` | Завжди для не-чернеткових push і PR |
+| `security-dependency-audit` | Аудит production lockfile без залежностей щодо advisories npm | Завжди для не-чернеткових push і PR |
+| `security-fast` | Обов’язковий агрегатор для швидких security-завдань | Завжди для не-чернеткових push і PR |
+| `build-artifacts` | Збирає `dist/`, Control UI, перевірки build-артефактів і повторно використовувані downstream-артефакти | Зміни, релевантні для Node |
+| `checks-fast-core` | Швидкі Linux-смуги коректності, такі як bundled/plugin-contract/protocol перевірки | Зміни, релевантні для Node |
+| `checks-fast-contracts-channels` | Шардовані перевірки channel contract зі стабільним агрегованим результатом перевірки | Зміни, релевантні для Node |
+| `checks-node-extensions` | Повні шарди тестів bundled-plugin для всього набору extension | Зміни, релевантні для Node |
+| `checks-node-core-test` | Шарди core Node-тестів, окрім channel, bundled, contract та extension-смуг | Зміни, релевантні для Node |
+| `extension-fast` | Сфокусовані тести лише для змінених bundled plugins | Pull request із змінами в extension |
+| `check` | Шардований еквівалент основної локальної перевірки: prod types, lint, guards, test types і strict smoke | Зміни, релевантні для Node |
+| `check-additional` | Шарди для перевірок архітектури, меж, extension-surface guards, package-boundary і gateway-watch | Зміни, релевантні для Node |
+| `build-smoke` | Smoke-тести зібраного CLI і smoke перевірка пам’яті на старті | Зміни, релевантні для Node |
+| `checks` | Засіб перевірки для channel-тестів build-артефактів плюс сумісність Node 22 лише для push | Зміни, релевантні для Node |
+| `check-docs` | Форматування docs, lint і перевірки битих посилань | Змінено docs |
+| `skills-python` | Ruff + pytest для Skills на Python | Зміни, релевантні для Python Skills |
+| `checks-windows` | Тестові смуги, специфічні для Windows | Зміни, релевантні для Windows |
+| `macos-node` | Смуга TypeScript-тестів на macOS із використанням спільних build-артефактів | Зміни, релевантні для macOS |
+| `macos-swift` | Swift lint, build і тести для застосунку macOS | Зміни, релевантні для macOS |
+| `android` | Android unit-тести для обох flavor плюс одна debug APK-збірка | Зміни, релевантні для Android |
+| `test-performance-agent` | Щоденна оптимізація повільних тестів Codex після довіреної активності | Успіх main CI або ручний запуск |
## Порядок Fail-Fast
-Завдання впорядковані так, щоб дешеві перевірки падали раніше, ніж запустяться дорогі:
+Завдання впорядковано так, щоб дешеві перевірки падали раніше, ніж запустяться дорогі:
-1. `preflight` визначає, які смуги взагалі існують. Логіка `docs-scope` і `changed-scope` — це кроки всередині цього завдання, а не окремі завдання.
-2. `security-scm-fast`, `security-dependency-audit`, `security-fast`, `check`, `check-additional`, `check-docs` і `skills-python` швидко завершуються з помилкою, не чекаючи важчих завдань із артефактами та платформними матрицями.
+1. `preflight` вирішує, які смуги взагалі існують. Логіка `docs-scope` і `changed-scope` — це кроки всередині цього завдання, а не окремі завдання.
+2. `security-scm-fast`, `security-dependency-audit`, `security-fast`, `check`, `check-additional`, `check-docs` і `skills-python` швидко падають, не чекаючи важчих матричних завдань для артефактів і платформ.
3. `build-artifacts` виконується паралельно зі швидкими Linux-смугами, щоб downstream-споживачі могли стартувати, щойно спільна збірка буде готова.
-4. Після цього розгалужуються важчі платформні та runtime-смуги: `checks-fast-core`, `checks-fast-contracts-channels`, `checks-node-extensions`, `checks-node-core-test`, PR-only `extension-fast`, `checks`, `checks-windows`, `macos-node`, `macos-swift` і `android`.
+4. Після цього розгалужуються важчі платформені та runtime-смуги: `checks-fast-core`, `checks-fast-contracts-channels`, `checks-node-extensions`, `checks-node-core-test`, PR-only `extension-fast`, `checks`, `checks-windows`, `macos-node`, `macos-swift` і `android`.
-Логіка областей дії міститься в `scripts/ci-changed-scope.mjs` і покрита unit-тестами в `src/scripts/ci-changed-scope.test.ts`.
-Зміни CI workflow перевіряють Node CI graph плюс lint workflow, але самі по собі не примушують запускати нативні збірки Windows, Android або macOS; ці платформні смуги й надалі обмежені змінами у платформному коді.
-Перевірки Windows Node обмежені специфічними для Windows обгортками process/path, допоміжними засобами runner для npm/pnpm/UI, конфігурацією package manager і поверхнями CI workflow, які запускають цю смугу; не пов’язані зміни в source, Plugin, install-smoke і лише тестах залишаються на Linux Node smугам, щоб не резервувати 16-vCPU Windows worker для покриття, яке вже перевіряється звичайними тестовими шардами.
-Окремий workflow `install-smoke` повторно використовує той самий скрипт областей дії через власне завдання `preflight`. Він обчислює `run_install_smoke` на основі вужчого сигналу changed-smoke, тому Docker/install smoke запускається для змін, пов’язаних з install, packaging, container, production-змінами bundled extension і поверхнями core plugin/channel/gateway/Plugin SDK, які використовують Docker smoke jobs. Зміни лише в тестах і лише в документації не резервують Docker workers. Його QR package smoke примушує Docker-шар `pnpm install` виконатися повторно, зберігаючи кеш BuildKit pnpm store, тож він усе ще перевіряє встановлення без повторного завантаження залежностей на кожному запуску. Його gateway-network e2e повторно використовує runtime image, зібраний раніше в межах завдання, тож додає реальне покриття WebSocket між контейнерами без додавання ще однієї Docker-збірки. Локальний `test:docker:all` попередньо збирає один спільний live-test image і один спільний built-app image з `scripts/e2e/Dockerfile`, а потім запускає live/E2E smoke lanes паралельно з `OPENCLAW_SKIP_DOCKER_BUILD=1`; налаштуйте типову паралельність 4 через `OPENCLAW_DOCKER_ALL_PARALLELISM`. Локальний агрегат типово припиняє планувати нові pooled lanes після першої помилки, а кожна смуга має тайм-аут 120 хвилин, який можна перевизначити через `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS`. Смуги, чутливі до запуску або провайдера, виконуються ексклюзивно після паралельного пулу. Повторно використовуваний live/E2E workflow віддзеркалює шаблон спільного image, збираючи й публікуючи один Docker E2E image з тегом SHA у GHCR перед Docker matrix, а потім запускає матрицю з `OPENCLAW_SKIP_DOCKER_BUILD=1`. Запланований live/E2E workflow щодня запускає повний Docker-набір для шляху релізу. Docker-тести QR та installer зберігають власні install-орієнтовані Dockerfiles. Окреме завдання `docker-e2e-fast` запускає обмежений Docker-профіль bundled Plugin під тайм-аутом команди 120 секунд: відновлення залежностей setup-entry плюс ізоляція синтетичного збою bundled-loader. Повна матриця bundled update/channel залишається ручною/для повного набору, оскільки виконує повторні реальні проходи `npm update` і doctor repair.
+Логіка області змін міститься в `scripts/ci-changed-scope.mjs` і покрита unit-тестами в `src/scripts/ci-changed-scope.test.ts`.
+Зміни в workflow CI перевіряють граф Node CI та lint workflow, але самі по собі не примушують запускати нативні збірки Windows, Android або macOS; ці платформені смуги й далі обмежуються змінами у вихідному коді відповідних платформ.
+Перевірки Windows Node обмежені специфічними для Windows обгортками process/path, допоміжними засобами для npm/pnpm/UI runner, конфігурацією package manager і поверхнями workflow CI, які запускають цю смугу; не пов’язані зміни у вихідному коді, plugin, install-smoke і зміни лише в тестах залишаються на Linux Node-смугах, щоб не займати Windows worker із 16 vCPU для покриття, яке вже забезпечується звичайними шардами тестів.
+Окремий workflow `install-smoke` повторно використовує той самий script області змін через власне завдання `preflight`. Він обчислює `run_install_smoke` на основі вужчого сигналу changed-smoke, тому Docker/install smoke запускається для змін, пов’язаних з install, packaging, container, production-змін bundled extension і core-поверхонь plugin/channel/gateway/Plugin SDK, які перевіряють Docker smoke-завдання. Зміни лише в тестах і лише в docs не займають Docker workers. Його QR package smoke примушує Docker-шар `pnpm install` виконатися повторно, зберігаючи кеш BuildKit pnpm store, тому інсталяція все одно перевіряється без повторного завантаження залежностей при кожному запуску. Його gateway-network e2e повторно використовує runtime image, зібраний раніше в межах завдання, тому додає реальне покриття WebSocket між контейнерами без додавання ще однієї Docker-збірки. Локальна команда `test:docker:all` попередньо збирає один спільний live-test image і один спільний образ зібраного застосунку `scripts/e2e/Dockerfile`, а потім запускає live/E2E smoke-смуги паралельно з `OPENCLAW_SKIP_DOCKER_BUILD=1`; стандартну паралельність 4 можна налаштувати через `OPENCLAW_DOCKER_ALL_PARALLELISM`. Локальний агрегатор за замовчуванням припиняє планувати нові pooled-смуги після першого збою, а кожна смуга має тайм-аут 120 хвилин, який можна перевизначити через `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS`. Смуги, чутливі до старту або провайдера, виконуються ексклюзивно після паралельного пулу. Повторно використовуваний live/E2E workflow відтворює шаблон спільного image, збираючи й публікуючи один GHCR Docker E2E image з тегом SHA перед Docker-матрицею, а потім запускає матрицю з `OPENCLAW_SKIP_DOCKER_BUILD=1`. Запланований live/E2E workflow щодня запускає повний Docker-набір для release-path. Тести QR і installer Docker зберігають власні Dockerfile, зосереджені на інсталяції. Окреме завдання `docker-e2e-fast` запускає обмежений Docker-профіль bundled-plugin з тайм-аутом команди 120 секунд: repair залежностей setup-entry і синтетичну ізоляцію збоїв bundled-loader. Повна матриця bundled update/channel лишається manual/full-suite, оскільки виконує повторні реальні проходи npm update і doctor repair.
-Локальна логіка changed-lane міститься в `scripts/changed-lanes.mjs` і виконується через `scripts/check-changed.mjs`. Цей локальний шлюз суворіший щодо архітектурних меж, ніж широка CI-область дії платформ: production-зміни core запускають core prod typecheck плюс core tests, зміни лише в core tests запускають тільки core test typecheck/tests, production-зміни extension запускають extension prod typecheck плюс extension tests, а зміни лише в extension tests запускають лише extension test typecheck/tests. Зміни у публічному Plugin SDK або plugin-contract розширюють валідацію на extensions, оскільки extensions залежать від цих core-контрактів. Зміни лише в метаданих релізу зі збільшенням версії запускають цільові перевірки version/config/root-dependency. Невідомі зміни в root/config безпечно переводять у всі смуги.
+Логіка локальних changed-lanes міститься в `scripts/changed-lanes.mjs` і виконується через `scripts/check-changed.mjs`. Ця локальна перевірка суворіше ставиться до архітектурних меж, ніж широке платформене обмеження в CI: production-зміни core запускають typecheck core prod плюс тести core, зміни лише в тестах core запускають лише typecheck/tests для тестів core, production-зміни extension запускають typecheck extension prod плюс тести extension, а зміни лише в тестах extension запускають лише typecheck/tests для тестів extension. Зміни в публічному Plugin SDK або plugin-contract розширюють перевірку на extension, оскільки extension залежать від цих core-контрактів. Зміни лише в release metadata version bump запускають цільові перевірки version/config/root-dependency. Невідомі зміни в root/config безпечно переводять у всі смуги.
-Для push матриця `checks` додає смугу `compat-node22`, що запускається лише для push. Для pull request ця смуга пропускається, і матриця залишається зосередженою на звичайних test/channel смугах.
+Для push матриця `checks` додає смугу `compat-node22`, яка виконується лише для push. Для pull request ця смуга пропускається, і матриця залишається зосередженою на звичайних тестових/channel-смугах.
-Найповільніші сімейства Node-тестів розділені або збалансовані так, щоб кожне завдання лишалося невеликим без надмірного резервування runner-ів: контракти каналів запускаються у трьох зважених шардах, тести bundled Plugin збалансовані між шістьма extension workers, невеликі core unit-смуги поєднані попарно, auto-reply запускається на трьох збалансованих workers замість шести дрібних workers, а конфігурації agentic gateway/plugin розподілені по наявних source-only agentic Node jobs замість очікування built artifacts. Широкі browser, QA, media і miscellaneous тести Plugin використовують свої спеціальні конфігурації Vitest замість спільного універсального набору plugin. Завдання шардів extension запускають групи конфігурацій plugin послідовно з одним Vitest worker і більшим heap Node, щоб import-важкі пакети plugin не перевантажували малі CI runner-и. Широка agents lane використовує спільний file-parallel scheduler Vitest, оскільки в ній домінують import/scheduling, а не один повільний тестовий файл. `runtime-config` запускається разом із шардом infra core-runtime, щоб спільний runtime shard не залишався останнім. `check-additional` тримає разом compile/canary роботу меж пакетів і відокремлює архітектуру runtime topology від покриття gateway watch; shard boundary guard запускає свої невеликі незалежні guards паралельно всередині одного завдання. Gateway watch, channel tests і shard core support-boundary виконуються паралельно всередині `build-artifacts` після того, як `dist/` і `dist-runtime/` уже зібрані, зберігаючи свої старі назви перевірок як легкі verifier jobs і водночас уникаючи двох додаткових Blacksmith workers і другої черги споживачів артефактів.
-Android CI запускає і `testPlayDebugUnitTest`, і `testThirdPartyDebugUnitTest`, а потім збирає Play debug APK. У third-party flavor немає окремого source set або manifest; його смуга unit-тестів усе одно компілює цей flavor із прапорцями BuildConfig для SMS/call-log, водночас уникаючи дубльованого завдання пакування debug APK на кожен Android-релевантний push.
-`extension-fast` є лише для PR, тому що push-запуски вже виконують повні шарди bundled Plugin. Це зберігає зворотний зв’язок для змінених plugins під час review, не резервуючи додатковий Blacksmith worker на `main` для покриття, яке вже є в `checks-node-extensions`.
+Найповільніші сімейства Node-тестів розділені або збалансовані так, щоб кожне завдання лишалося невеликим без надмірного резервування runner-ів: channel contracts виконуються як три зважені шарди, тести bundled plugin збалансовані між шістьма extension worker-ами, малі core unit-смуги об’єднані попарно, auto-reply виконується як три збалансовані worker-и замість шести дрібних worker-ів, а конфігурації agentic gateway/plugin розподілені по наявних source-only agentic Node-завданнях замість очікування build-артефактів. Широкі browser-, QA-, media- і miscellaneous plugin-тести використовують власні конфігурації Vitest замість спільного універсального plugin catch-all. Завдання extension shard виконують групи конфігурацій plugin послідовно з одним Vitest worker і більшим Node heap, щоб import-важкі пакети plugin не перевантажували малі CI runner-и. Широка smуга agents використовує спільний файл-паралельний планувальник Vitest, оскільки в ній домінують imports/планування, а не один окремий повільний тестовий файл. `runtime-config` виконується разом із шардом infra core-runtime, щоб спільний runtime-shard не залишався найдовшим. `check-additional` тримає разом package-boundary compile/canary-роботи й відокремлює архітектуру runtime topology від покриття gateway watch; shard boundary guard виконує свої малі незалежні guards паралельно в межах одного завдання. Gateway watch, channel-тести й shard core support-boundary виконуються паралельно всередині `build-artifacts` після того, як `dist/` і `dist-runtime/` уже зібрано, зберігаючи старі назви перевірок як легкі завдання-верифікатори й водночас уникаючи двох додаткових Blacksmith worker-ів і другої черги споживачів артефактів.
-GitHub може позначати замінені завдання як `cancelled`, коли новіший push потрапляє в той самий PR або ref `main`. Вважайте це шумом CI, якщо тільки найновіший запуск для того самого ref також не завершується з помилкою. Агреговані перевірки шардів використовують `!cancelled() && always()`, тож вони все одно повідомляють про звичайні збої шардів, але не стають у чергу після того, як увесь workflow уже був замінений новішим.
+Android CI запускає і `testPlayDebugUnitTest`, і `testThirdPartyDebugUnitTest`, а потім збирає Play debug APK. Flavor third-party не має окремого source set або manifest; його смуга unit-тестів усе одно компілює цей flavor із прапорцями SMS/call-log у BuildConfig, водночас уникаючи дубльованого завдання пакування debug APK при кожному push, релевантному для Android.
+`extension-fast` є лише для PR, тому що push-запуски вже виконують повні шарди bundled plugin. Це зберігає швидкий зворотний зв’язок для reviews щодо змінених plugin без резервування додаткового Blacksmith worker у `main` для покриття, яке вже є в `checks-node-extensions`.
-Ключ конкурентності CI має версіонування (`CI-v7-*`), щоб zombie-процес на боці GitHub у старій групі черги не міг безкінечно блокувати новіші запуски main.
+GitHub може позначати замінені новішими завдання як `cancelled`, коли новіший push потрапляє в той самий PR або ref `main`. Сприймайте це як шум CI, якщо тільки найновіший запуск для того самого ref також не падає. Агреговані shard-перевірки використовують `!cancelled() && always()`, тож вони й далі повідомляють про звичайні збої shard-ів, але не стають у чергу після того, як увесь workflow уже був замінений новішим.
+Ключ конкурентності CI має версію (`CI-v7-*`), щоб zombie-процес на боці GitHub у старій групі черги не міг безстроково блокувати новіші запуски main.
-## Runners
+## Runner-и
-| Runner | Завдання |
-| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `ubuntu-24.04` | `preflight`, швидкі завдання безпеки та агрегати (`security-scm-fast`, `security-dependency-audit`, `security-fast`), швидкі перевірки protocol/contract/bundled, шардовані перевірки контрактів каналів, шарди `check`, крім lint, шарди й агрегати `check-additional`, агреговані верифікатори Node-тестів, перевірки документації, Python Skills, workflow-sanity, labeler, auto-response; preflight для install-smoke також використовує Ubuntu, розміщену на GitHub, щоб матриця Blacksmith могла стати в чергу раніше |
-| `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`, build-smoke, шарди Linux Node-тестів, шарди тестів bundled Plugin, `android` |
-| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`, який залишається достатньо чутливим до CPU, тому 8 vCPU коштували дорожче, ніж зекономили; Docker-збірки install-smoke, де вартість часу очікування в черзі для 32 vCPU перевищувала виграш |
-| `blacksmith-16vcpu-windows-2025` | `checks-windows` |
-| `blacksmith-6vcpu-macos-latest` | `macos-node` у `openclaw/openclaw`; для fork використовується `macos-latest` |
-| `blacksmith-12vcpu-macos-latest` | `macos-swift` у `openclaw/openclaw`; для fork використовується `macos-latest` |
+| Runner | Завдання |
+| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `ubuntu-24.04` | `preflight`, швидкі security-завдання та агрегати (`security-scm-fast`, `security-dependency-audit`, `security-fast`), швидкі protocol/contract/bundled-перевірки, шардовані перевірки channel contract, шарди `check`, окрім lint, шарди й агрегати `check-additional`, агреговані верифікатори Node-тестів, перевірки docs, Python Skills, workflow-sanity, labeler, auto-response; preflight для install-smoke також використовує GitHub-hosted Ubuntu, щоб матриця Blacksmith могла стати в чергу раніше |
+| `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`, build-smoke, шарди Linux Node-тестів, шарди тестів bundled plugin, `android` |
+| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`, який і далі достатньо чутливий до CPU, тож 8 vCPU коштували дорожче, ніж заощаджували; Docker-збірки install-smoke, де час очікування в черзі для 32 vCPU коштував дорожче, ніж давав вигоду |
+| `blacksmith-16vcpu-windows-2025` | `checks-windows` |
+| `blacksmith-6vcpu-macos-latest` | `macos-node` у `openclaw/openclaw`; для fork використовується резервний `macos-latest` |
+| `blacksmith-12vcpu-macos-latest` | `macos-swift` у `openclaw/openclaw`; для fork використовується резервний `macos-latest` |
## Локальні еквіваленти
```bash
-pnpm changed:lanes # перевірити локальний класифікатор changed-lane для origin/main...HEAD
-pnpm check:changed # розумний локальний шлюз: changed typecheck/lint/tests за граничною смугою
-pnpm check # швидкий локальний шлюз: production tsgo + шардований lint + паралельні швидкі guards
+pnpm changed:lanes # переглянути локальний класифікатор changed-lane для origin/main...HEAD
+pnpm check:changed # розумна локальна перевірка: changed typecheck/lint/tests за boundary lane
+pnpm check # швидка локальна перевірка: production tsgo + sharded lint + parallel fast guards
pnpm check:test-types
-pnpm check:timed # той самий шлюз із таймінгами для кожного етапу
+pnpm check:timed # та сама перевірка з таймінгами для кожного етапу
pnpm build:strict-smoke
pnpm check:architecture
pnpm test:gateway:watch-regression
pnpm test # тести vitest
pnpm test:channels
pnpm test:contracts:channels
-pnpm check:docs # форматування документації + lint + перевірка битих посилань
-pnpm build # зібрати dist, коли важливі смуги CI artifact/build-smoke
+pnpm check:docs # форматування docs + lint + биті посилання
+pnpm build # збірка dist, коли важливі смуги CI artifact/build-smoke
node scripts/ci-run-timings.mjs # підсумувати загальний час, час у черзі та найповільніші завдання
node scripts/ci-run-timings.mjs --recent 10 # порівняти нещодавні успішні запуски main CI
+pnpm test:perf:groups --full-suite --allow-failures --output .artifacts/test-perf/baseline-before.json
+pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifacts/test-perf/after-agent.json
```
diff --git a/docs/uk/help/testing.md b/docs/uk/help/testing.md
index f4aa79091..f0f61f008 100644
--- a/docs/uk/help/testing.md
+++ b/docs/uk/help/testing.md
@@ -1,158 +1,160 @@
---
read_when:
- Запуск тестів локально або в CI
- - Додавання регресійних тестів для помилок моделей/провайдерів
- - Налагодження поведінки Gateway + agent
-summary: 'Набір для тестування: unit/e2e/live набори, Docker runners і що покриває кожен тест'
+ - Додавання регресійних тестів для багів моделі/провайдера
+ - Налагодження поведінки Gateway + агента
+summary: 'Набір для тестування: набори unit/e2e/live, Docker-ранери та що охоплює кожен тест'
title: Тестування
x-i18n:
- generated_at: "2026-04-23T19:25:31Z"
+ generated_at: "2026-04-23T19:48:40Z"
model: gpt-5.4
provider: openai
- source_hash: 1a26531abaab4e09f27976a12c5f4394f5f30eade060659670ba57adfc5fdc71
+ source_hash: a868c91c94d862b75375a90bc9b5b0d8cf618e81c437e275ef1830c4a3a70c38
source_path: help/testing.md
workflow: 15
---
-OpenClaw має три набори Vitest (unit/integration, e2e, live) і невеликий набір
-Docker runners. Цей документ — посібник «як ми тестуємо»:
+OpenClaw має три набори Vitest (unit/integration, e2e, live) і невеликий набір Docker-ранерів. Цей документ — посібник «як ми тестуємо»:
-- Що покриває кожен набір (і що він навмисно _не_ покриває).
+- Що охоплює кожен набір (і що він навмисно _не_ охоплює).
- Які команди запускати для типових сценаріїв роботи (локально, перед push, налагодження).
-- Як live-тести знаходять облікові дані й вибирають моделі/провайдерів.
+- Як live-тести знаходять облікові дані та вибирають моделі/провайдерів.
- Як додавати регресійні тести для реальних проблем із моделями/провайдерами.
## Швидкий старт
У більшості випадків:
-- Повний gate (очікується перед push): `pnpm build && pnpm check && pnpm check:test-types && pnpm test`
-- Швидший локальний запуск повного набору на потужній машині: `pnpm test:max`
+- Повний контрольний прогін (очікується перед push): `pnpm build && pnpm check && pnpm check:test-types && pnpm test`
+- Швидший локальний запуск усього набору на потужній машині: `pnpm test:max`
- Прямий цикл спостереження Vitest: `pnpm test:watch`
-- Пряме націлювання на файл тепер також маршрутизує шляхи extension/channel: `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts`
-- Під час ітерацій над однією помилкою спочатку віддавайте перевагу точковим запускам.
-- Сайт QA з Docker: `pnpm qa:lab:up`
-- QA lane на базі Linux VM: `pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline`
+- Прямий таргетинг файлів тепер також маршрутизує шляхи extension/channel: `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts`
+- Коли ви ітеруєтеся над одним падінням, спочатку віддавайте перевагу цільовим запускам.
+- QA-сайт на базі Docker: `pnpm qa:lab:up`
+- QA-лінія на базі Linux VM: `pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline`
-Коли ви торкаєтеся тестів або хочете додаткової впевненості:
+Коли ви торкаєтесь тестів або хочете додаткової впевненості:
-- Coverage gate: `pnpm test:coverage`
+- Контрольний прогін покриття: `pnpm test:coverage`
- Набір E2E: `pnpm test:e2e`
Під час налагодження реальних провайдерів/моделей (потрібні реальні облікові дані):
-- Live-набір (моделі + probe інструментів/зображень Gateway): `pnpm test:live`
-- Точково запустити один live-файл тихо: `pnpm test:live -- src/agents/models.profiles.live.test.ts`
-- Docker sweep live-моделей: `pnpm test:docker:live-models`
- - Кожна вибрана модель тепер виконує текстовий хід плюс невеликий probe у стилі читання файла.
- Моделі, чиї метадані вказують на підтримку вхідних `image`, також виконують малий хід із зображенням.
- Вимкніть додаткові probe за допомогою `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` або
- `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0`, коли ізолюєте збої провайдерів.
- - Покриття в CI: щоденний `OpenClaw Scheduled Live And E2E Checks` і ручний
+- Набір live (моделі + probe Gateway для інструментів/зображень): `pnpm test:live`
+- Точково запустити один live-файл у тихому режимі: `pnpm test:live -- src/agents/models.profiles.live.test.ts`
+- Docker-прогін live-моделей: `pnpm test:docker:live-models`
+ - Кожна вибрана модель тепер виконує текстовий хід і невеликий probe у стилі читання файлу.
+ Моделі, у чиїх метаданих вказано вхід `image`, також виконують мініатюрний хід із зображенням.
+ Вимкніть додаткові probe через `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` або
+ `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0`, коли ізолюєте збої провайдера.
+ - Покриття в CI: щоденні `OpenClaw Scheduled Live And E2E Checks` і ручні
`OpenClaw Release Checks` обидва викликають повторно використовуваний workflow live/E2E з
- `include_live_suites: true`, що включає окремі matrix jobs Docker live-моделей,
- розбиті за провайдерами.
- - Для точкових повторних запусків у CI запустіть `OpenClaw Live And E2E Checks (Reusable)`
+ `include_live_suites: true`, який включає окремі матричні job-и Docker live-моделей,
+ розшардовані за провайдером.
+ - Для точкових повторних запусків у CI dispatch-ніть `OpenClaw Live And E2E Checks (Reusable)`
з `include_live_suites: true` і `live_models_only: true`.
- - Додавайте нові високосигнальні секрети провайдерів до `scripts/ci-hydrate-live-auth.sh`
- плюс до `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` і його
- запланованих/release викликів.
-- Smoke-тест вартості Moonshot/Kimi: коли задано `MOONSHOT_API_KEY`, виконайте
- `openclaw models list --provider moonshot --json`, а потім окремий
+ - Додавайте нові високосигнальні секрети провайдерів до `scripts/ci-hydrate-live-auth.sh`,
+ а також до `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` і його
+ запланованих/релізних викликів.
+- Димовий тест вартості Moonshot/Kimi: коли встановлено `MOONSHOT_API_KEY`, виконайте
+ `openclaw models list --provider moonshot --json`, а потім ізольований
`openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json`
- для `moonshot/kimi-k2.6`. Переконайтеся, що JSON повідомляє про Moonshot/K2.6, а
- транскрипт помічника зберігає нормалізований `usage.cost`.
+ для `moonshot/kimi-k2.6`. Переконайтеся, що JSON повідомляє Moonshot/K2.6, а
+ транскрипт асистента зберігає нормалізоване `usage.cost`.
-Порада: якщо вам потрібен лише один збійний випадок, звужуйте live-тести через env-змінні allowlist, описані нижче.
+Порада: коли вам потрібен лише один збійний випадок, віддавайте перевагу звуженню live-тестів через env-змінні allowlist, описані нижче.
-## Runners, специфічні для QA
+## Спеціальні QA-ранери
-Ці команди стоять поруч з основними наборами тестів, коли вам потрібен реалізм QA-lab:
+Ці команди розташовані поруч з основними наборами тестів, коли вам потрібен реалізм qa-lab:
-CI запускає QA Lab в окремих workflow. `Parity gate` запускається для відповідних PR і
-через ручний dispatch з mock-провайдерами. `QA-Lab - All Lanes` запускається щоночі на
-`main` і через ручний dispatch з mock parity gate, live Matrix lane і
-live Telegram lane під керуванням Convex як паралельними jobs. `OpenClaw Release Checks`
-запускає ті самі lanes перед затвердженням release.
+CI запускає QA Lab в окремих workflow. `Parity gate` виконується для відповідних PR і
+з ручного dispatch із mock-провайдерами. `QA-Lab - All Lanes` виконується щоночі на
+`main` і з ручного dispatch з mock parity gate, live-лінією Matrix та live-лінією Telegram,
+керованою Convex, як паралельними job-ами. `OpenClaw Release Checks`
+запускає ті самі лінії перед схваленням релізу.
- `pnpm openclaw qa suite`
- Запускає сценарії QA з репозиторію безпосередньо на хості.
- - Типово запускає кілька вибраних сценаріїв паралельно з ізольованими
- worker-ами gateway. `qa-channel` типово має concurrency 4 (обмежено
- кількістю вибраних сценаріїв). Використовуйте `--concurrency ` для налаштування
- кількості worker-ів або `--concurrency 1` для старішого послідовного lane.
- - Завершується з ненульовим кодом, якщо будь-який сценарій зазнав невдачі. Використовуйте `--allow-failures`, якщо
- вам потрібні артефакти без збійного коду завершення.
- - Підтримує режими провайдерів `live-frontier`, `mock-openai` і `aimock`.
+ - За замовчуванням запускає кілька вибраних сценаріїв паралельно з ізольованими
+ воркерами Gateway. `qa-channel` за замовчуванням має concurrency 4 (обмежується
+ кількістю вибраних сценаріїв). Використовуйте `--concurrency `, щоб налаштувати
+ кількість воркерів, або `--concurrency 1` для старішої послідовної лінії.
+ - Завершується з ненульовим кодом, якщо будь-який сценарій падає. Використовуйте `--allow-failures`, коли
+ вам потрібні артефакти без коду завершення з помилкою.
+ - Підтримує режими провайдера `live-frontier`, `mock-openai` і `aimock`.
`aimock` запускає локальний сервер провайдера на базі AIMock для експериментального
- покриття фікстур і моків протоколу без заміни сценарно-орієнтованого
- lane `mock-openai`.
+ покриття фікстур і протокольних mock-ів, не замінюючи орієнтовану на сценарії
+ лінію `mock-openai`.
- `pnpm openclaw qa suite --runner multipass`
- - Запускає той самий набір QA всередині одноразової Linux VM Multipass.
+ - Запускає той самий набір QA усередині одноразової Linux VM Multipass.
- Зберігає ту саму поведінку вибору сценаріїв, що й `qa suite` на хості.
- Повторно використовує ті самі прапорці вибору провайдера/моделі, що й `qa suite`.
- - Live-запуски передають у гість підтримувані входи авторизації QA, практичні для гостьової системи:
- ключі провайдерів із env, шлях до конфігурації QA live provider і `CODEX_HOME`,
- якщо він наявний.
- - Каталоги виводу мають залишатися в межах кореня репозиторію, щоб гість міг записувати назад через
+ - Live-запуски передають підтримувані вхідні дані автентифікації QA, практичні для гостьової системи:
+ ключі провайдерів на основі env, шлях до конфігурації QA live provider та `CODEX_HOME`,
+ якщо він присутній.
+ - Каталоги виводу мають залишатися в межах кореня репозиторію, щоб гостьова система могла записувати назад через
змонтований workspace.
- - Записує звичайний звіт QA + підсумок, а також логи Multipass у
+ - Записує звичайний QA-звіт + підсумок, а також журнали Multipass у
`.artifacts/qa-e2e/...`.
- `pnpm qa:lab:up`
- - Запускає сайт QA на базі Docker для операторської QA-роботи.
+ - Запускає QA-сайт на базі Docker для QA-роботи в операторському стилі.
- `pnpm test:docker:npm-onboard-channel-agent`
- Збирає npm tarball із поточного checkout, глобально встановлює його в
- Docker, виконує неінтерактивний onboarding OpenAI API key, типово налаштовує Telegram,
- перевіряє, що вмикання plugin встановлює runtime dependencies на вимогу,
- запускає doctor і виконує один локальний хід agent-а проти мокованої кінцевої точки OpenAI.
- - Використовуйте `OPENCLAW_NPM_ONBOARD_CHANNEL=discord`, щоб виконати той самий lane
- пакованого встановлення з Discord.
+ Docker, виконує неінтерактивне налаштування з API-ключем OpenAI, за замовчуванням
+ налаштовує Telegram, перевіряє, що ввімкнення plugin встановлює runtime-залежності за потреби,
+ запускає doctor і виконує один локальний хід агента проти mock-endpoint OpenAI.
+ - Використовуйте `OPENCLAW_NPM_ONBOARD_CHANNEL=discord`, щоб запустити ту саму лінію
+ встановлення з пакета з Discord.
- `pnpm test:docker:bundled-channel-deps`
- - Пакує й установлює поточну збірку OpenClaw у Docker, запускає Gateway
- з налаштованим OpenAI, а потім вмикає вбудовані channel/plugin-и через
- редагування config.
- - Перевіряє, що виявлення setup залишає runtime dependencies
- неналаштованих plugin-ів відсутніми, перший налаштований запуск Gateway або doctor встановлює runtime dependencies кожного вбудованого plugin-а на вимогу,
- а другий перезапуск не перевстановлює dependencies, які вже були активовані.
- - Також установлює відомий старіший npm baseline, вмикає Telegram перед запуском
- `openclaw update --tag ` і перевіряє, що post-update doctor
- кандидата відновлює runtime dependencies вбудованих channel без
+ - Пакує та встановлює поточну збірку OpenClaw у Docker, запускає Gateway
+ зі сконфігурованим OpenAI, а потім вмикає bundled channel/plugins через
+ редагування конфігурації.
+ - Перевіряє, що виявлення налаштування залишає runtime-залежності
+ несконфігурованих plugins відсутніми, що перший сконфігурований запуск Gateway або doctor встановлює
+ runtime-залежності кожного bundled plugin за потреби, і що другий перезапуск не перевстановлює
+ залежності, які вже були активовані.
+ - Також установлює відому старішу npm-базову версію, вмикає Telegram перед запуском
+ `openclaw update --tag `, і перевіряє, що doctor кандидата
+ після оновлення відновлює runtime-залежності bundled channel без
postinstall-відновлення з боку harness.
- `pnpm openclaw qa aimock`
- - Запускає лише локальний сервер провайдера AIMock для прямого smoke-тестування протоколу.
+ - Запускає лише локальний сервер провайдера AIMock для прямого димового
+ тестування протоколу.
- `pnpm openclaw qa matrix`
- - Запускає live QA lane Matrix проти одноразового homeserver Tuwunel на базі Docker.
- - Цей QA-хост наразі призначений лише для repo/dev. Паковані встановлення OpenClaw не постачають
- `qa-lab`, тому не надають `openclaw qa`.
- - Checkout-и репозиторію завантажують вбудований runner напряму; окремий крок встановлення plugin-а не потрібен.
- - Надає трьох тимчасових користувачів Matrix (`driver`, `sut`, `observer`) плюс одну приватну кімнату, а потім запускає дочірній QA gateway з реальним Matrix plugin як транспортом SUT.
- - Типово використовує зафіксований стабільний образ Tuwunel `ghcr.io/matrix-construct/tuwunel:v1.5.1`. Перевизначайте через `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE`, коли потрібно протестувати інший образ.
- - Matrix не надає спільних прапорців джерела облікових даних, оскільки lane локально створює одноразових користувачів.
- - Записує звіт Matrix QA, підсумок, артефакт observed-events і комбінований лог stdout/stderr у `.artifacts/qa-e2e/...`.
+ - Запускає live-лінію QA Matrix проти одноразового homeserver Tuwunel на базі Docker.
+ - Цей хост QA сьогодні призначений лише для repo/dev. Упаковані встановлення OpenClaw не постачають
+ `qa-lab`, тому вони не надають `openclaw qa`.
+ - Checkout-и репозиторію завантажують bundled runner безпосередньо; окремий крок
+ встановлення plugin не потрібен.
+ - Створює трьох тимчасових користувачів Matrix (`driver`, `sut`, `observer`) плюс одну приватну кімнату, а потім запускає дочірній QA gateway із реальним Matrix plugin як транспортом SUT.
+ - За замовчуванням використовує зафіксований стабільний образ Tuwunel `ghcr.io/matrix-construct/tuwunel:v1.5.1`. Перевизначайте через `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE`, коли потрібно протестувати інший образ.
+ - Matrix не надає спільних прапорців джерела облікових даних, оскільки лінія локально створює одноразових користувачів.
+ - Записує QA-звіт Matrix, підсумок, артефакт observed-events і комбінований журнал виводу stdout/stderr у `.artifacts/qa-e2e/...`.
- `pnpm openclaw qa telegram`
- - Запускає live QA lane Telegram проти реальної приватної групи, використовуючи токени bot-ів driver і SUT з env.
- - Потребує `OPENCLAW_QA_TELEGRAM_GROUP_ID`, `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` і `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`. ID групи має бути числовим Telegram chat id.
- - Підтримує `--credential-source convex` для спільних пулів облікових даних. Типово використовуйте режим env або задайте `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`, щоб увімкнути орендовані спільні облікові дані.
- - Завершується з ненульовим кодом, якщо будь-який сценарій зазнав невдачі. Використовуйте `--allow-failures`, якщо
- вам потрібні артефакти без збійного коду завершення.
- - Потребує двох різних bot-ів в одній приватній групі, причому bot SUT має мати Telegram username.
- - Для стабільного спостереження bot-to-bot увімкніть Bot-to-Bot Communication Mode у `@BotFather` для обох bot-ів і переконайтеся, що bot driver може спостерігати трафік bot-ів у групі.
- - Записує звіт Telegram QA, підсумок і артефакт observed-messages у `.artifacts/qa-e2e/...`. Сценарії з відповідями включають RTT від запиту надсилання driver до спостереженої відповіді SUT.
+ - Запускає live-лінію QA Telegram проти реальної приватної групи, використовуючи токени бота driver і SUT з env.
+ - Потребує `OPENCLAW_QA_TELEGRAM_GROUP_ID`, `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` і `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`. Ідентифікатор групи має бути числовим Telegram chat id.
+ - Підтримує `--credential-source convex` для спільних пулованих облікових даних. За замовчуванням використовуйте режим env або встановіть `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`, щоб увімкнути пуловані оренди.
+ - Завершується з ненульовим кодом, якщо будь-який сценарій падає. Використовуйте `--allow-failures`, коли
+ вам потрібні артефакти без коду завершення з помилкою.
+ - Потребує двох різних ботів в одній приватній групі, причому бот SUT має мати Telegram username.
+ - Для стабільного спостереження bot-to-bot увімкніть режим Bot-to-Bot Communication Mode у `@BotFather` для обох ботів і переконайтеся, що бот driver може спостерігати трафік ботів у групі.
+ - Записує QA-звіт Telegram, підсумок і артефакт observed-messages у `.artifacts/qa-e2e/...`. Сценарії з відповідями включають RTT від запиту надсилання driver до спостереженої відповіді SUT.
-Live transport lanes спільно використовують один стандартний контракт, щоб нові транспорти не розходилися:
+Live-транспортні лінії використовують єдиний стандартний контракт, щоб нові транспорти не розходилися:
-`qa-channel` залишається широким синтетичним набором QA і не входить до матриці покриття live transport.
+`qa-channel` залишається широким синтетичним набором QA і не є частиною матриці покриття live-транспорту.
-| Lane | Canary | Блокування згадувань | Блокування allowlist | Відповідь верхнього рівня | Відновлення після перезапуску | Подальші дії в треді | Ізоляція тредів | Спостереження за реакціями | Команда help |
-| -------- | ------ | -------------------- | -------------------- | ------------------------- | ----------------------------- | -------------------- | --------------- | -------------------------- | ------------ |
-| Matrix | x | x | x | x | x | x | x | x | |
-| Telegram | x | | | | | | | | x |
+| Лінія | Canary | Гейтінг згадок | Блокування allowlist | Відповідь верхнього рівня | Відновлення після перезапуску | Подальша відповідь у треді | Ізоляція тредів | Спостереження реакцій | Команда help |
+| -------- | ------ | -------------- | -------------------- | ------------------------- | ----------------------------- | -------------------------- | --------------- | --------------------- | ------------ |
+| Matrix | x | x | x | x | x | x | x | x | |
+| Telegram | x | | | | | | | | x |
### Спільні облікові дані Telegram через Convex (v1)
Коли для `openclaw qa telegram` увімкнено `--credential-source convex` (або `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`),
QA lab отримує ексклюзивну оренду з пулу на базі Convex, надсилає Heartbeat
-цієї оренди, поки lane виконується, і звільняє оренду під час завершення.
+для цієї оренди, поки лінія виконується, і звільняє оренду під час завершення роботи.
Еталонний каркас проєкту Convex:
@@ -160,30 +162,30 @@ QA lab отримує ексклюзивну оренду з пулу на ба
Обов’язкові env-змінні:
-- `OPENCLAW_QA_CONVEX_SITE_URL` (наприклад `https://your-deployment.convex.site`)
+- `OPENCLAW_QA_CONVEX_SITE_URL` (наприклад, `https://your-deployment.convex.site`)
- Один секрет для вибраної ролі:
- `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` для `maintainer`
- `OPENCLAW_QA_CONVEX_SECRET_CI` для `ci`
- Вибір ролі облікових даних:
- CLI: `--credential-role maintainer|ci`
- - Типове значення через env: `OPENCLAW_QA_CREDENTIAL_ROLE` (типово `ci` у CI, інакше `maintainer`)
+ - Env за замовчуванням: `OPENCLAW_QA_CREDENTIAL_ROLE` (у CI за замовчуванням `ci`, інакше `maintainer`)
Необов’язкові env-змінні:
-- `OPENCLAW_QA_CREDENTIAL_LEASE_TTL_MS` (типово `1200000`)
-- `OPENCLAW_QA_CREDENTIAL_HEARTBEAT_INTERVAL_MS` (типово `30000`)
-- `OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS` (типово `90000`)
-- `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS` (типово `15000`)
-- `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX` (типово `/qa-credentials/v1`)
+- `OPENCLAW_QA_CREDENTIAL_LEASE_TTL_MS` (за замовчуванням `1200000`)
+- `OPENCLAW_QA_CREDENTIAL_HEARTBEAT_INTERVAL_MS` (за замовчуванням `30000`)
+- `OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS` (за замовчуванням `90000`)
+- `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS` (за замовчуванням `15000`)
+- `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX` (за замовчуванням `/qa-credentials/v1`)
- `OPENCLAW_QA_CREDENTIAL_OWNER_ID` (необов’язковий trace id)
-- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` дозволяє loopback URL Convex `http://` лише для локальної розробки.
+- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` дозволяє loopback `http://` URL Convex лише для локальної розробки.
-`OPENCLAW_QA_CONVEX_SITE_URL` у звичайній роботі має використовувати `https://`.
+`OPENCLAW_QA_CONVEX_SITE_URL` у звичайному режимі роботи має використовувати `https://`.
-Адміністративні команди maintainer-а (додавання/видалення/перелік пулу) потребують
+Адміністративні команди для супровідників (додавання/видалення/список пулу) вимагають
саме `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`.
-CLI-хелпери для maintainers:
+CLI-допоміжні команди для супровідників:
```bash
pnpm openclaw qa credentials add --kind telegram --payload-file qa/telegram-credential.json
@@ -191,9 +193,9 @@ pnpm openclaw qa credentials list --kind telegram
pnpm openclaw qa credentials remove --credential-id
```
-Використовуйте `--json` для машиночитаного виводу в скриптах і утилітах CI.
+Використовуйте `--json` для машинозчитуваного виводу в скриптах і утилітах CI.
-Типовий контракт кінцевих точок (`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`):
+Контракт endpoint за замовчуванням (`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`):
- `POST /acquire`
- Запит: `{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs }`
@@ -216,7 +218,7 @@ pnpm openclaw qa credentials remove --credential-id
- Запит: `{ kind?, status?, includePayload?, limit? }`
- Успіх: `{ status: "ok", credentials, count }`
-Форма payload для виду Telegram:
+Форма payload для типу Telegram:
- `{ groupId: string, driverToken: string, sutToken: string }`
- `groupId` має бути рядком із числовим Telegram chat id.
@@ -224,55 +226,55 @@ pnpm openclaw qa credentials remove --credential-id
### Додавання каналу до QA
-Додавання каналу до markdown-системи QA потребує рівно двох речей:
+Додавання каналу до markdown-системи QA вимагає рівно двох речей:
-1. Транспортний адаптер для каналу.
-2. Набір сценаріїв, який перевіряє контракт каналу.
+1. Транспортного адаптера для каналу.
+2. Набору сценаріїв, який перевіряє контракт каналу.
-Не додавайте новий кореневий QA-командний простір верхнього рівня, якщо спільний хост `qa-lab`
-може керувати цим процесом.
+Не додавайте новий кореневий QA-командний рівень, якщо спільний хост `qa-lab` може
+керувати цим потоком.
-`qa-lab` володіє спільною механікою хоста:
+`qa-lab` відповідає за спільну хостову механіку:
-- кореневою командою `openclaw qa`
-- запуском і завершенням наборів
-- паралельністю worker-ів
-- записом артефактів
-- генерацією звітів
-- виконанням сценаріїв
-- псевдонімами сумісності для старіших сценаріїв `qa-channel`
+- кореневу команду `openclaw qa`
+- запуск і завершення suite
+- concurrency воркерів
+- запис артефактів
+- генерацію звітів
+- виконання сценаріїв
+- compatibility aliases для старіших сценаріїв `qa-channel`
-Runner plugin-и володіють транспортним контрактом:
+Runner plugins відповідають за транспортний контракт:
- як `openclaw qa ` монтується під спільним коренем `qa`
- як Gateway налаштовується для цього транспорту
- як перевіряється готовність
-- як інжектуються вхідні події
+- як інжектяться вхідні події
- як спостерігаються вихідні повідомлення
- як надаються транскрипти й нормалізований стан транспорту
-- як виконуються дії, підкріплені транспортом
-- як обробляється специфічне для транспорту скидання або очищення
+- як виконуються дії, підтримувані транспортом
+- як обробляється транспортно-специфічний reset або cleanup
-Мінімальна планка впровадження нового каналу така:
+Мінімальний поріг впровадження нового каналу такий:
1. Залишайте `qa-lab` власником спільного кореня `qa`.
-2. Реалізуйте transport runner на спільному хостовому seam `qa-lab`.
-3. Тримайте специфічну для транспорту механіку всередині runner plugin-а або harness каналу.
+2. Реалізуйте transport runner на спільному host seam `qa-lab`.
+3. Залишайте транспортно-специфічну механіку всередині runner plugin або harness каналу.
4. Монтуйте runner як `openclaw qa ` замість реєстрації конкуруючої кореневої команди.
- Runner plugin-и повинні оголошувати `qaRunners` у `openclaw.plugin.json` і експортувати відповідний масив `qaRunnerCliRegistrations` із `runtime-api.ts`.
- Зберігайте `runtime-api.ts` легким; лінивий CLI і виконання runner-а мають залишатися за окремими entrypoint-ами.
+ Runner plugins повинні оголошувати `qaRunners` у `openclaw.plugin.json` і експортувати відповідний масив `qaRunnerCliRegistrations` із `runtime-api.ts`.
+ Тримайте `runtime-api.ts` легким; ліниве виконання CLI і runner має залишатися за окремими entrypoint.
5. Створюйте або адаптуйте markdown-сценарії в тематичних каталогах `qa/scenarios/`.
-6. Використовуйте загальні helper-и сценаріїв для нових сценаріїв.
-7. Зберігайте працездатність наявних псевдонімів сумісності, якщо лише репозиторій не виконує навмисну міграцію.
+6. Використовуйте загальні scenario helpers для нових сценаріїв.
+7. Зберігайте працездатність наявних compatibility aliases, якщо тільки в репозиторії не виконується навмисна міграція.
-Правило ухвалення рішення суворе:
+Правило прийняття рішення суворе:
-- Якщо поведінку можна виразити один раз у `qa-lab`, розміщуйте її в `qa-lab`.
-- Якщо поведінка залежить від одного канального транспорту, тримайте її в цьому runner plugin-і або plugin harness.
-- Якщо сценарію потрібна нова можливість, яку можуть використовувати більш ніж один канал, додайте загальний helper замість специфічної для каналу гілки в `suite.ts`.
-- Якщо поведінка має сенс лише для одного транспорту, залишайте сценарій специфічним для цього транспорту й явно відображайте це в контракті сценарію.
+- Якщо поведінку можна один раз виразити в `qa-lab`, розміщуйте її в `qa-lab`.
+- Якщо поведінка залежить від одного транспорту каналу, залишайте її в цьому runner plugin або plugin harness.
+- Якщо сценарію потрібна нова можливість, якою може користуватися більше ніж один канал, додавайте загальний helper замість channel-specific гілки в `suite.ts`.
+- Якщо поведінка має сенс лише для одного транспорту, залишайте сценарій transport-specific і явно фіксуйте це в контракті сценарію.
-Бажані назви загальних helper-ів для нових сценаріїв:
+Бажані назви generic helper для нових сценаріїв:
- `waitForTransportReady`
- `waitForChannelReady`
@@ -287,7 +289,7 @@ Runner plugin-и володіють транспортним контракто
- `formatTransportTranscript`
- `resetTransport`
-Псевдоніми сумісності залишаються доступними для наявних сценаріїв, зокрема:
+Compatibility aliases залишаються доступними для наявних сценаріїв, зокрема:
- `waitForQaChannelReady`
- `waitForOutboundMessage`
@@ -295,264 +297,263 @@ Runner plugin-и володіють транспортним контракто
- `formatConversationTranscript`
- `resetBus`
-Нова робота над каналами має використовувати загальні назви helper-ів.
-Псевдоніми сумісності існують, щоб уникнути міграції одним днем, а не як модель для
+Нова робота над каналами має використовувати generic helper names.
+Compatibility aliases існують, щоб уникнути міграції в стилі flag day, а не як модель для
створення нових сценаріїв.
## Набори тестів (що де запускається)
-Думайте про набори як про «зростаючий реалізм» (і зростаючу нестабільність/вартість):
+Сприймайте набори як «зростання реалізму» (і зростання нестабільності/вартості):
-### Unit / integration (типово)
+### Unit / integration (за замовчуванням)
- Команда: `pnpm test`
-- Config: нетаргетовані запуски використовують набір шардів `vitest.full-*.config.ts` і можуть розгортати багатопроєктні шарди в конфіги для окремих проєктів для паралельного планування
-- Файли: інвентарі core/unit у `src/**/*.test.ts`, `packages/**/*.test.ts`, `test/**/*.test.ts` і дозволені node-тести `ui`, охоплені `vitest.unit.config.ts`
-- Область:
+- Конфігурація: нетаргетовані запуски використовують набір шардів `vitest.full-*.config.ts` і можуть розгортати multi-project шарди в per-project конфігурації для паралельного планування
+- Файли: core/unit inventory у `src/**/*.test.ts`, `packages/**/*.test.ts`, `test/**/*.test.ts` і whitelist node-тести `ui`, які покриває `vitest.unit.config.ts`
+- Обсяг:
- Чисті unit-тести
- - In-process integration-тести (авторизація gateway, маршрутизація, інструменти, парсинг, config)
- - Детерміновані регресії для відомих помилок
+ - In-process integration-тести (автентифікація Gateway, маршрутизація, інструменти, парсинг, конфігурація)
+ - Детерміновані регресії для відомих багів
- Очікування:
- Запускається в CI
- Реальні ключі не потрібні
- Має бути швидким і стабільним
- - Нетаргетований `pnpm test` запускає дванадцять менших shard-конфігів (`core-unit-fast`, `core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-support-boundary`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`) замість одного гігантського нативного root-project процесу. Це зменшує піковий RSS на завантажених машинах і не дає роботі auto-reply/extension виснажувати не пов’язані набори. - `pnpm test --watch` усе ще використовує нативний граф проєктів root `vitest.config.ts`, оскільки багатошардовий цикл watch непрактичний. - `pnpm test`, `pnpm test:watch` і `pnpm test:perf:imports` спочатку маршрутизують явні цілі файлів/каталогів через scoped lanes, тож `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` уникає повної вартості запуску root project. - `pnpm test:changed` розгортає змінені git-шляхи в ті самі scoped lanes, коли diff торкається лише routable source/test файлів; редагування config/setup усе ще повертаються до широкого повторного запуску root-project. - `pnpm check:changed` — це типовий розумний локальний gate для вузької роботи. Він класифікує diff на core, тести core, extensions, тести extension, apps, docs, release metadata і tooling, а потім запускає відповідні lanes typecheck/lint/test. Зміни публічного Plugin SDK і plugin-contract включають перевірку extension, тому що extensions залежать від цих контрактів core. Оновлення версії лише в release metadata запускають точкові перевірки version/config/root-dependency замість повного набору, із guard, що відхиляє зміни package поза полем версії верхнього рівня. - Легкі з погляду імпортів unit-тести з agents, commands, plugins, helper-ів auto-reply, `plugin-sdk` та схожих чистих утилітних ділянок маршрутизуються через lane `unit-fast`, який пропускає `test/setup-openclaw-runtime.ts`; stateful/runtime-heavy файли лишаються на наявних lanes. - Вибрані helper-файли джерела `plugin-sdk` і `commands` також зіставляють запуски changed-mode з явними сусідніми тестами в цих легких lanes, щоб правки helper-ів не спричиняли повторний запуск усього важкого набору для цього каталогу. - `auto-reply` має три виділені кошики: helper-и core верхнього рівня, integration-тести верхнього рівня `reply.*` і піддерево `src/auto-reply/reply/**`. Це не дає найважчій роботі harness reply потрапляти на дешеві тести status/chunk/token.
+ - Нетаргетовані запуски `pnpm test` використовують дванадцять менших shard-конфігурацій (`core-unit-fast`, `core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-support-boundary`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`) замість одного гігантського native root-project process. Це зменшує піковий RSS на завантажених машинах і не дає роботі auto-reply/extension виснажувати не пов’язані набори. - `pnpm test --watch` як і раніше використовує native root-граф проєкту `vitest.config.ts`, оскільки цикл спостереження з multi-shard не є практичним. - `pnpm test`, `pnpm test:watch` і `pnpm test:perf:imports` спочатку маршрутизують явні target файлу/каталогу через scoped lanes, тож `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` уникає повної вартості запуску root project. - `pnpm test:changed` розгортає змінені git-шляхи в ті самі scoped lanes, коли diff торкається лише routable source/test файлів; редагування config/setup, як і раніше, повертаються до широкого повторного запуску root project. - `pnpm check:changed` — це стандартний розумний локальний контрольний прогін для вузької роботи. Він класифікує diff на core, core tests, extensions, extension tests, apps, docs, release metadata і tooling, а потім запускає відповідні lanes typecheck/lint/test. Зміни в публічному Plugin SDK і plugin-contract включають перевірку extensions, оскільки extensions залежать від цих core-контрактів. Оновлення версій, що стосуються лише release metadata, запускають таргетовані перевірки version/config/root-dependency замість повного набору, із захистом, який відхиляє зміни package поза полем версії верхнього рівня. - Полегшені з точки зору імпортів unit-тести для agents, commands, plugins, helper-функцій auto-reply, `plugin-sdk` та подібних чистих utility-областей маршрутизуються через lane `unit-fast`, яка пропускає `test/setup-openclaw-runtime.ts`; файли зі stateful/runtime-heavy поведінкою залишаються на наявних lanes. - Вибрані helper source-файли `plugin-sdk` і `commands` також відображають changed-mode запуски на явні sibling-тести в цих легких lanes, тож редагування helper уникають повторного запуску повного важкого набору для цього каталогу. - `auto-reply` має три виділені bucket: helper-функції core верхнього рівня, integration-тести верхнього рівня `reply.*` і піддерево `src/auto-reply/reply/**`. Це прибирає найважчу роботу harness reply із дешевих тестів status/chunk/token.
- - Коли ви змінюєте входи виявлення message-tool або runtime-контекст
- Compaction, зберігайте обидва рівні покриття.
- - Додавайте точкові helper-регресії для чистих меж маршрутизації й нормалізації.
- - Підтримуйте справність integration-наборів embedded runner:
+ - Коли ви змінюєте вхідні дані для виявлення message-tool або runtime-контекст Compaction, зберігайте обидва рівні покриття.
+ - Додавайте вузько сфокусовані helper-регресії для чистих меж маршрутизації та нормалізації.
+ - Підтримуйте в робочому стані integration suites embedded runner:
`src/agents/pi-embedded-runner/compact.hooks.test.ts`,
`src/agents/pi-embedded-runner/run.overflow-compaction.test.ts` і
`src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts`.
- - Ці набори перевіряють, що scoped id та поведінка Compaction і далі проходять
- через реальні шляхи `run.ts` / `compact.ts`; тести лише на helper-и
- не є достатньою заміною для цих integration-шляхів.
+ - Ці набори перевіряють, що scoped id і поведінка Compaction, як і раніше, проходять
+ через реальні шляхи `run.ts` / `compact.ts`; helper-only тести не є
+ достатньою заміною для цих integration-шляхів.
-
- - Базовий config Vitest типово використовує `threads`.
- - Спільний config Vitest фіксує `isolate: false` і використовує
- runner без ізоляції в root projects, e2e і live configs.
- - Root lane UI зберігає своє налаштування `jsdom` й optimizer, але теж запускається на
- спільному runner-і без ізоляції.
- - Кожен shard `pnpm test` успадковує ті самі типові значення
- `threads` + `isolate: false` зі спільного config Vitest.
- - `scripts/run-vitest.mjs` типово додає `--no-maglev` для дочірніх Node-процесів Vitest,
+
+ - Базова конфігурація Vitest за замовчуванням використовує `threads`.
+ - Спільна конфігурація Vitest фіксує `isolate: false` і використовує
+ non-isolated runner в root projects, а також у конфігураціях e2e і live.
+ - Root UI lane зберігає своє налаштування `jsdom` й optimizer, але також працює на
+ спільному non-isolated runner.
+ - Кожен shard `pnpm test` успадковує ті самі значення за замовчуванням `threads` + `isolate: false`
+ зі спільної конфігурації Vitest.
+ - `scripts/run-vitest.mjs` за замовчуванням додає `--no-maglev` для дочірніх Node-процесів Vitest,
щоб зменшити churn компіляції V8 під час великих локальних запусків.
- Установіть `OPENCLAW_VITEST_ENABLE_MAGLEV=1`, щоб порівняти з типовою поведінкою V8.
+ Встановіть `OPENCLAW_VITEST_ENABLE_MAGLEV=1`, щоб порівняти зі стандартною поведінкою V8.
- `pnpm changed:lanes` показує, які архітектурні lanes запускає diff.
- Pre-commit hook запускає `pnpm check:changed --staged` після staged
- formatting/linting, тож core-only commits не оплачують вартість тестів extension,
- якщо лише вони не торкаються публічних контрактів, орієнтованих на extension. Коміти лише з
- release metadata залишаються на точковому lane
- version/config/root-dependency.
+ formatting/linting, тож commit-и лише для core не оплачують вартість тестів extension,
+ якщо вони не торкаються публічних контрактів, орієнтованих на extension. Commit-и лише з
+ release metadata залишаються на таргетованій
+ lane version/config/root-dependency.
- Якщо точний staged-набір змін уже був перевірений
- рівними або сильнішими gates, використовуйте
- `scripts/committer --fast "" `, щоб пропустити лише повторний запуск hook changed-scope. Staged format/lint усе одно запускаються. Згадайте
- виконані gates у вашому handoff. Це також прийнятно після повторного запуску ізольованого нестабільного hook-а, якщо він проходить із точковим доказом.
+ рівними або сильнішими контрольними прогоном, використовуйте
+ `scripts/committer --fast "" `, щоб пропустити лише повторний запуск changed-scope hook.
+ Staged format/lint усе одно виконуються. Згадайте завершені контрольні прогони у вашому handoff. Це також прийнятно після
+ повторного запуску ізольованого flaky hook failure, який пройшов із scoped proof.
- `pnpm test:changed` маршрутизується через scoped lanes, коли змінені шляхи
- чисто відповідають меншому набору.
- - `pnpm test:max` і `pnpm test:changed:max` зберігають ту саму поведінку маршрутизації, лише з вищим лімітом worker-ів.
- - Автоматичне локальне масштабування worker-ів навмисно консервативне й зменшується,
- коли середнє навантаження хоста вже високе, тож кілька одночасних
- запусків Vitest типово шкодять менше.
- - Базовий config Vitest позначає проєкти/config-файли як
- `forceRerunTriggers`, щоб повторні запуски в режимі changed залишалися коректними,
- коли змінюється wiring тестів.
- - Config тримає `OPENCLAW_VITEST_FS_MODULE_CACHE` увімкненим на підтримуваних
- хостах; установіть `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`, якщо хочете
- одну явну локацію кешу для прямого профілювання.
+ чисто відображаються на менший набір.
+ - `pnpm test:max` і `pnpm test:changed:max` зберігають ту саму поведінку маршрутизації,
+ лише з вищим лімітом воркерів.
+ - Автоматичне масштабування локальних воркерів навмисно є консервативним і знижує навантаження,
+ коли середнє навантаження хоста вже високе, тож кілька паралельних
+ запусків Vitest за замовчуванням завдають менше шкоди.
+ - Базова конфігурація Vitest позначає файли projects/config як
+ `forceRerunTriggers`, щоб reruns у changed-mode залишалися коректними, коли змінюється wiring тестів.
+ - Конфігурація зберігає `OPENCLAW_VITEST_FS_MODULE_CACHE` увімкненим на
+ підтримуваних хостах; встановіть `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`, якщо хочете
+ одну явну локацію кешу для прямого profiling.
- - `pnpm test:perf:imports` вмикає звітування Vitest про тривалість імпортів плюс
- вивід розбивки імпортів.
- - `pnpm test:perf:imports:changed` обмежує той самий вид профілювання
- файлами, зміненими від `origin/main`.
+ - `pnpm test:perf:imports` вмикає звітність Vitest про тривалість імпорту плюс
+ вивід import-breakdown.
+ - `pnpm test:perf:imports:changed` звужує той самий вигляд profiling до
+ файлів, змінених відносно `origin/main`.
- `pnpm test:perf:changed:bench -- --ref ` порівнює маршрутизований
- `test:changed` із нативним шляхом root-project для цього закоміченого diff і виводить wall time плюс macOS max RSS.
- - `pnpm test:perf:changed:bench -- --worktree` виконує benchmark поточного
- брудного дерева, маршрутизуючи список змінених файлів через
- `scripts/test-projects.mjs` і root config Vitest.
- - `pnpm test:perf:profile:main` записує профіль CPU main-thread для
- старту Vitest/Vite та overhead трансформацій.
- - `pnpm test:perf:profile:runner` записує профілі CPU+heap runner-а для
- unit-набору з вимкненим файловим паралелізмом.
+ `test:changed` із native root-project шляхом для цього закоміченого diff і виводить wall time плюс macOS max RSS.
+ - `pnpm test:perf:changed:bench -- --worktree` бенчмаркує поточне брудне дерево, маршрутизуючи список змінених файлів через
+ `scripts/test-projects.mjs` і root-конфігурацію Vitest.
+ - `pnpm test:perf:profile:main` записує CPU-профіль main-thread для
+ витрат Vitest/Vite на startup і transform.
+ - `pnpm test:perf:profile:runner` записує CPU+heap профілі runner для
+ unit-набору з вимкненим file parallelism.
-### Стабільність (gateway)
+### Stability (Gateway)
- Команда: `pnpm test:stability:gateway`
-- Config: `vitest.gateway.config.ts`, примусово один worker
-- Область:
+- Конфігурація: `vitest.gateway.config.ts`, примусово один воркер
+- Обсяг:
- Запускає реальний loopback Gateway з увімкненою діагностикою за замовчуванням
- - Проганяє синтетичний churn повідомлень gateway, memory і великих payload через шлях діагностичних подій
- - Запитує `diagnostics.stability` через WS RPC Gateway
- - Покриває helper-и збереження набору діагностичної стабільності
- - Перевіряє, що recorder залишається обмеженим, синтетичні RSS-зразки лишаються в межах бюджету тиску, а глибини черг для кожної сесії повертаються до нуля
+ - Пропускає синтетичне churn повідомлень gateway, пам’яті та великих payload через діагностичний шлях подій
+ - Виконує запити до `diagnostics.stability` через WS RPC Gateway
+ - Покриває helper-функції збереження diagnostic stability bundle
+ - Перевіряє, що recorder залишається обмеженим, синтетичні вибірки RSS залишаються в межах бюджету тиску, а глибини черг для кожної сесії знову знижуються до нуля
- Очікування:
- Безпечно для CI і без ключів
- - Вузький lane для подальшої роботи над регресіями стабільності, а не заміна повному набору Gateway
+ - Вузька lane для подальшої роботи над stability-регресіями, а не заміна повного набору Gateway
-### E2E (gateway smoke)
+### E2E (димове тестування gateway)
- Команда: `pnpm test:e2e`
-- Config: `vitest.e2e.config.ts`
-- Файли: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts` і E2E-тести вбудованих plugin-ів у `extensions/`
-- Типові параметри runtime:
+- Конфігурація: `vitest.e2e.config.ts`
+- Файли: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts` і bundled-plugin E2E-тести в `extensions/`
+- Значення runtime за замовчуванням:
- Використовує Vitest `threads` з `isolate: false`, як і решта репозиторію.
- - Використовує адаптивну кількість worker-ів (CI: до 2, локально: 1 типово).
- - Типово працює в тихому режимі, щоб зменшити накладні витрати на console I/O.
+ - Використовує адаптивну кількість воркерів (CI: до 2, локально: 1 за замовчуванням).
+ - За замовчуванням запускається в тихому режимі, щоб зменшити накладні витрати на console I/O.
- Корисні перевизначення:
- - `OPENCLAW_E2E_WORKERS=` щоб примусово задати кількість worker-ів (обмежено 16).
- - `OPENCLAW_E2E_VERBOSE=1` щоб знову ввімкнути докладний вивід у консоль.
-- Область:
- - End-to-end поведінка Gateway з кількома екземплярами
- - Поверхні WebSocket/HTTP, pair-ing Node і важча мережева взаємодія
+ - `OPENCLAW_E2E_WORKERS=`, щоб примусово задати кількість воркерів (обмежено 16).
+ - `OPENCLAW_E2E_VERBOSE=1`, щоб знову ввімкнути докладний вивід у консоль.
+- Обсяг:
+ - Наскрізна поведінка gateway з кількома інстансами
+ - Поверхні WebSocket/HTTP, pairing Node і важча мережева взаємодія
- Очікування:
- - Запускається в CI (коли увімкнено в pipeline)
+ - Запускається в CI (коли ввімкнено в pipeline)
- Реальні ключі не потрібні
- - Більше рухомих частин, ніж у unit-тестах (може бути повільніше)
+ - Більше рухомих частин, ніж в unit-тестах (може бути повільнішим)
-### E2E: smoke OpenShell backend
+### E2E: димове тестування backend OpenShell
- Команда: `pnpm test:e2e:openshell`
- Файл: `extensions/openshell/src/backend.e2e.test.ts`
-- Область:
- - Запускає ізольований Gateway OpenShell на хості через Docker
- - Створює sandbox з тимчасового локального Dockerfile
- - Перевіряє OpenShell backend OpenClaw через реальні `sandbox ssh-config` + SSH exec
- - Перевіряє remote-canonical поведінку файлової системи через fs-bridge sandbox
+- Обсяг:
+ - Запускає ізольований gateway OpenShell на хості через Docker
+ - Створює sandbox із тимчасового локального Dockerfile
+ - Перевіряє backend OpenShell в OpenClaw через реальні `sandbox ssh-config` + SSH exec
+ - Перевіряє поведінку файлової системи в remote-canonical режимі через bridge файлової системи sandbox
- Очікування:
- - Лише opt-in; не входить до типового запуску `pnpm test:e2e`
- - Потребує локального CLI `openshell` і працездатного Docker daemon
- - Використовує ізольовані `HOME` / `XDG_CONFIG_HOME`, а потім знищує тестові gateway і sandbox
+ - Лише за явним увімкненням; не входить до стандартного запуску `pnpm test:e2e`
+ - Потребує локального CLI `openshell` і працюючого Docker daemon
+ - Використовує ізольовані `HOME` / `XDG_CONFIG_HOME`, а потім знищує test gateway і sandbox
- Корисні перевизначення:
- - `OPENCLAW_E2E_OPENSHELL=1` щоб увімкнути тест під час ручного запуску ширшого e2e-набору
- - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` щоб указати нестандартний CLI binary або wrapper script
+ - `OPENCLAW_E2E_OPENSHELL=1`, щоб увімкнути тест під час ручного запуску ширшого набору e2e
+ - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell`, щоб вказати нестандартний бінарний файл CLI або wrapper script
### Live (реальні провайдери + реальні моделі)
- Команда: `pnpm test:live`
-- Config: `vitest.live.config.ts`
-- Файли: `src/**/*.live.test.ts`, `test/**/*.live.test.ts` і live-тести вбудованих plugin-ів у `extensions/`
-- Типово: **увімкнено** через `pnpm test:live` (встановлює `OPENCLAW_LIVE_TEST=1`)
-- Область:
+- Конфігурація: `vitest.live.config.ts`
+- Файли: `src/**/*.live.test.ts`, `test/**/*.live.test.ts` і bundled-plugin live-тести в `extensions/`
+- За замовчуванням: **увімкнено** через `pnpm test:live` (встановлює `OPENCLAW_LIVE_TEST=1`)
+- Обсяг:
- «Чи справді цей провайдер/модель працює _сьогодні_ з реальними обліковими даними?»
- - Виявлення змін формату провайдера, особливостей tool-calling, проблем авторизації та поведінки rate limit
+ - Виявлення змін форматів провайдерів, особливостей виклику інструментів, проблем автентифікації та поведінки rate limit
- Очікування:
- - За задумом не є стабільним для CI (реальні мережі, реальні політики провайдерів, квоти, збої)
+ - За задумом нестабільний для CI (реальні мережі, реальні політики провайдерів, квоти, збої)
- Коштує грошей / витрачає rate limits
- - Краще запускати звужені підмножини, а не «все»
-- Live-запуски читають `~/.profile`, щоб підхопити відсутні API key.
-- Типово live-запуски все одно ізолюють `HOME` і копіюють config/auth матеріали в тимчасовий test home, щоб unit-фікстури не могли змінити ваш реальний `~/.openclaw`.
+ - Краще запускати звужені підмножини, а не «все підряд»
+- Live-запуски використовують `~/.profile`, щоб підхопити відсутні API-ключі.
+- За замовчуванням live-запуски все одно ізолюють `HOME` і копіюють матеріали config/auth у тимчасовий test home, щоб unit-фікстури не могли змінити ваш реальний `~/.openclaw`.
- Встановлюйте `OPENCLAW_LIVE_USE_REAL_HOME=1` лише тоді, коли вам навмисно потрібно, щоб live-тести використовували ваш реальний домашній каталог.
-- `pnpm test:live` тепер типово працює в тихішому режимі: він зберігає вивід прогресу `[live] ...`, але приховує додаткове повідомлення про `~/.profile` і приглушує bootstrap-логи gateway/шум Bonjour. Установіть `OPENCLAW_LIVE_TEST_QUIET=0`, якщо хочете повернути повні стартові логи.
-- Ротація API key (залежно від провайдера): задайте `*_API_KEYS` у форматі з комами/крапками з комою або `*_API_KEY_1`, `*_API_KEY_2` (наприклад `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) або перевизначення для live через `OPENCLAW_LIVE_*_KEY`; тести повторюють спроби при відповідях rate limit.
+- `pnpm test:live` тепер за замовчуванням працює в тихішому режимі: він залишає вивід прогресу `[live] ...`, але приглушує додаткове повідомлення про `~/.profile` і вимикає журнали bootstrap gateway/шум Bonjour. Встановіть `OPENCLAW_LIVE_TEST_QUIET=0`, якщо хочете повернути повні журнали запуску.
+- Ротація API-ключів (специфічна для провайдера): встановлюйте `*_API_KEYS` у форматі з комами/крапками з комою або `*_API_KEY_1`, `*_API_KEY_2` (наприклад, `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) або використовуйте перевизначення для live через `OPENCLAW_LIVE_*_KEY`; тести повторюють спробу у відповідь на rate limit.
- Вивід прогресу/Heartbeat:
- - Live-набори тепер виводять рядки прогресу в stderr, щоб довгі виклики провайдерів було видно як активні, навіть коли захоплення консолі Vitest тихе.
- - `vitest.live.config.ts` вимикає перехоплення консолі Vitest, тож рядки прогресу провайдера/gateway одразу потоково надходять під час live-запусків.
- - Налаштовуйте Heartbeat для direct-model через `OPENCLAW_LIVE_HEARTBEAT_MS`.
+ - Live-набори тепер виводять рядки прогресу в stderr, тож довгі виклики провайдерів помітно активні навіть тоді, коли перехоплення консолі Vitest тихе.
+ - `vitest.live.config.ts` вимикає перехоплення консолі Vitest, щоб рядки прогресу провайдера/gateway одразу передавалися під час live-запусків.
+ - Налаштовуйте Heartbeat для прямої моделі через `OPENCLAW_LIVE_HEARTBEAT_MS`.
- Налаштовуйте Heartbeat для gateway/probe через `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS`.
## Який набір мені запускати?
-Використовуйте цю таблицю рішень:
+Скористайтеся цією таблицею рішень:
-- Редагуєте логіку/тести: запускайте `pnpm test` (і `pnpm test:coverage`, якщо змінили багато)
-- Торкаєтеся мережевої взаємодії gateway / WS protocol / pairing: додайте `pnpm test:e2e`
-- Налагоджуєте «мій bot не працює» / збої, специфічні для провайдера / tool calling: запускайте звужений `pnpm test:live`
+- Редагуєте логіку/тести: запускайте `pnpm test` (і `pnpm test:coverage`, якщо ви багато що змінили)
+- Торкаєтеся мережевої взаємодії gateway / протоколу WS / pairing: додайте `pnpm test:e2e`
+- Налагоджуєте «мій бот не працює» / специфічні для провайдера збої / виклик інструментів: запускайте звужений `pnpm test:live`
-## Live: sweep можливостей Android Node
+## Live: перевірка можливостей Android Node
- Тест: `src/gateway/android-node.capabilities.live.test.ts`
- Скрипт: `pnpm android:test:integration`
-- Мета: викликати **кожну команду, яку зараз оголошує** підключений Android Node, і перевірити поведінку контракту команди.
-- Область:
- - Ручне/попередньо підготовлене налаштування (набір не встановлює/не запускає/не pair-ить app).
- - Перевірка `node.invoke` Gateway для вибраного Android Node команда за командою.
-- Обов’язкове попереднє налаштування:
- - Android app уже підключений і спарений з gateway.
+- Мета: викликати **кожну команду, яку наразі рекламує** підключений Android Node, і перевірити поведінку контракту команд.
+- Обсяг:
+ - Попередньо підготовлене/ручне налаштування (набір не встановлює, не запускає і не виконує pairing app).
+ - Перевірка `node.invoke` gateway команда за командою для вибраного Android Node.
+- Необхідне попереднє налаштування:
+ - Android app уже підключено та спарено з gateway.
- App утримується на передньому плані.
- - Надано дозволи/згоду на захоплення для можливостей, які ви очікуєте успішними.
+ - Для можливостей, які ви очікуєте успішно пройти, надано дозволи/згоду на захоплення.
- Необов’язкові перевизначення цілі:
- `OPENCLAW_ANDROID_NODE_ID` або `OPENCLAW_ANDROID_NODE_NAME`.
- `OPENCLAW_ANDROID_GATEWAY_URL` / `OPENCLAW_ANDROID_GATEWAY_TOKEN` / `OPENCLAW_ANDROID_GATEWAY_PASSWORD`.
- Повні подробиці налаштування Android: [Android App](/uk/platforms/android)
-## Live: smoke моделей (ключі профілів)
+## Live: димове тестування моделі (ключі профілів)
-Live-тести поділено на два рівні, щоб можна було ізолювати збої:
+Live-тести поділено на два шари, щоб можна було ізолювати збої:
-- «Direct model» показує, що провайдер/модель взагалі може відповісти з цим ключем.
-- «Gateway smoke» показує, що для цієї моделі працює повний pipeline gateway+agent (сесії, історія, інструменти, політика sandbox тощо).
+- «Пряма модель» показує, що провайдер/модель взагалі може відповідати з наданим ключем.
+- «Димове тестування Gateway» показує, що повний pipeline gateway+agent працює для цієї моделі (сесії, історія, інструменти, політика sandbox тощо).
-### Рівень 1: Direct model completion (без gateway)
+### Шар 1: Пряме завершення моделі (без gateway)
- Тест: `src/agents/models.profiles.live.test.ts`
- Мета:
- Перелічити виявлені моделі
- Використати `getApiKeyForModel`, щоб вибрати моделі, для яких у вас є облікові дані
- - Виконати невелике completion для кожної моделі (і точкові регресії за потреби)
+ - Виконати невелике completion для кожної моделі (і цільові регресії там, де потрібно)
- Як увімкнути:
- `pnpm test:live` (або `OPENCLAW_LIVE_TEST=1`, якщо викликаєте Vitest напряму)
-- Установіть `OPENCLAW_LIVE_MODELS=modern` (або `all`, псевдонім для modern), щоб реально запустити цей набір; інакше він буде пропущений, щоб `pnpm test:live` лишався сфокусованим на gateway smoke
+- Встановіть `OPENCLAW_LIVE_MODELS=modern` (або `all`, псевдонім для modern), щоб справді запустити цей набір; інакше його буде пропущено, щоб `pnpm test:live` залишався зосередженим на димовому тестуванні gateway
- Як вибирати моделі:
- - `OPENCLAW_LIVE_MODELS=modern` щоб запустити сучасний allowlist (Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4)
- - `OPENCLAW_LIVE_MODELS=all` — це псевдонім для сучасного allowlist
+ - `OPENCLAW_LIVE_MODELS=modern`, щоб запустити modern allowlist (Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4)
+ - `OPENCLAW_LIVE_MODELS=all` — псевдонім для modern allowlist
- або `OPENCLAW_LIVE_MODELS="openai/gpt-5.5,anthropic/claude-opus-4-6,..."` (allowlist через кому)
- - Sweep modern/all типово обмежуються curated high-signal cap; установіть `OPENCLAW_LIVE_MAX_MODELS=0` для вичерпного modern sweep або додатне число для меншого обмеження.
+ - Прогони modern/all за замовчуванням обмежені відібраною high-signal межею; встановіть `OPENCLAW_LIVE_MAX_MODELS=0` для вичерпного прогону modern або додатне число для меншого ліміту.
- Як вибирати провайдерів:
- `OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"` (allowlist через кому)
- Звідки беруться ключі:
- - Типово: сховище профілів і fallback-и env
- - Установіть `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати **лише сховище профілів**
+ - За замовчуванням: сховище профілів і env fallback-и
+ - Встановіть `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати **лише сховище профілів**
- Навіщо це існує:
- - Відокремлює «API провайдера зламане / ключ невалідний» від «pipeline gateway agent зламаний»
- - Містить невеликі ізольовані регресії (приклад: replay reasoning OpenAI Responses/Codex Responses + потоки tool-call)
+ - Відокремлює «API провайдера зламане / ключ недійсний» від «pipeline агента gateway зламаний»
+ - Містить невеликі ізольовані регресії (приклад: OpenAI Responses/Codex Responses reasoning replay + потоки tool-call)
-### Рівень 2: Gateway + smoke dev agent (те, що насправді робить "@openclaw")
+### Шар 2: Димове тестування Gateway + dev agent (що насправді робить "@openclaw")
- Тест: `src/gateway/gateway-models.profiles.live.test.ts`
- Мета:
- Підняти in-process gateway
- - Створити/змінити сесію `agent:dev:*` (перевизначення моделі на кожен запуск)
- - Ітерувати моделі-з-ключами й перевіряти:
+ - Створити/оновити сесію `agent:dev:*` (перевизначення моделі для кожного запуску)
+ - Ітеруватися моделями-з-ключами і перевіряти:
- «змістовну» відповідь (без інструментів)
- - що реальний виклик інструмента працює (probe читання)
- - необов’язкові додаткові probe інструментів (probe exec+read)
- - що шляхи регресії OpenAI (лише tool-call → подальший виклик) і далі працюють
-- Деталі probe (щоб можна було швидко пояснювати збої):
- - probe `read`: тест записує файл nonce у workspace і просить agent-а `read` його та повернути nonce.
- - probe `exec+read`: тест просить agent-а через `exec` записати nonce в тимчасовий файл, а потім `read` прочитати його назад.
- - probe зображення: тест прикріплює згенерований PNG (кіт + рандомізований код) і очікує, що модель поверне `cat `.
+ - що працює реальний виклик інструмента (read probe)
+ - необов’язкові додаткові probe інструментів (exec+read probe)
+ - що регресійні шляхи OpenAI (лише tool-call → подальша відповідь) і далі працюють
+- Подробиці probe (щоб ви могли швидко пояснювати збої):
+ - `read` probe: тест записує файл із nonce у workspace і просить агента `read` його та повернути nonce.
+ - `exec+read` probe: тест просить агента через `exec` записати nonce у тимчасовий файл, а потім `read`-ом прочитати його назад.
+ - image probe: тест прикріплює згенерований PNG (cat + випадковий код) і очікує, що модель поверне `cat `.
- Посилання на реалізацію: `src/gateway/gateway-models.profiles.live.test.ts` і `src/gateway/live-image-probe.ts`.
- Як увімкнути:
- `pnpm test:live` (або `OPENCLAW_LIVE_TEST=1`, якщо викликаєте Vitest напряму)
- Як вибирати моделі:
- - Типово: сучасний allowlist (Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4)
- - `OPENCLAW_LIVE_GATEWAY_MODELS=all` — це псевдонім для сучасного allowlist
- - Або задайте `OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"` (або список через кому), щоб звузити вибір
- - Sweep gateway modern/all типово обмежуються curated high-signal cap; установіть `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0` для вичерпного modern sweep або додатне число для меншого обмеження.
-- Як вибирати провайдерів (уникнути «OpenRouter everything»):
+ - За замовчуванням: modern allowlist (Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4)
+ - `OPENCLAW_LIVE_GATEWAY_MODELS=all` — псевдонім для modern allowlist
+ - Або встановіть `OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"` (або список через кому), щоб звузити
+ - Прогони modern/all gateway за замовчуванням обмежені відібраною high-signal межею; встановіть `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0` для вичерпного прогону modern або додатне число для меншого ліміту.
+- Як вибирати провайдерів (уникати «усе з OpenRouter»):
- `OPENCLAW_LIVE_GATEWAY_PROVIDERS="google,google-antigravity,google-gemini-cli,openai,anthropic,zai,minimax"` (allowlist через кому)
-- Tool + image probe завжди увімкнені в цьому live-тесті:
- - probe `read` + probe `exec+read` (стрес для інструментів)
- - probe зображення запускається, коли модель оголошує підтримку вхідних зображень
- - Потік (високорівнево):
- - Тест генерує маленький PNG з «CAT» + випадковим кодом (`src/gateway/live-image-probe.ts`)
+- Probe інструментів і зображень у цьому live-тесті завжди ввімкнені:
+ - `read` probe + `exec+read` probe (навантаження на інструменти)
+ - image probe запускається, коли модель рекламує підтримку вхідних зображень
+ - Потік (на високому рівні):
+ - Тест генерує крихітний PNG із “CAT” + випадковим кодом (`src/gateway/live-image-probe.ts`)
- Надсилає його через `agent` `attachments: [{ mimeType: "image/png", content: "" }]`
- - Gateway розбирає attachments у `images[]` (`src/gateway/server-methods/agent.ts` + `src/gateway/chat-attachments.ts`)
- - Вбудований agent передає мультимодальне повідомлення користувача моделі
- - Перевірка: відповідь містить `cat` + код (допуск OCR: дозволені незначні помилки)
+ - Gateway парсить вкладення в `images[]` (`src/gateway/server-methods/agent.ts` + `src/gateway/chat-attachments.ts`)
+ - Embedded agent передає моделі мультимодальне повідомлення користувача
+ - Перевірка: відповідь містить `cat` + код (допуск OCR: незначні помилки дозволені)
Порада: щоб побачити, що саме ви можете тестувати на своїй машині (і точні id `provider/model`), виконайте:
@@ -561,26 +562,26 @@ openclaw models list
openclaw models list --json
```
-## Live: smoke CLI backend (Claude, Codex, Gemini або інші локальні CLI)
+## Live: димове тестування backend CLI (Claude, Codex, Gemini або інші локальні CLI)
- Тест: `src/gateway/gateway-cli-backend.live.test.ts`
-- Мета: перевірити pipeline Gateway + agent, використовуючи локальний CLI backend, не торкаючись типового config.
-- Типові параметри smoke для конкретного backend живуть у визначенні `cli-backend.ts` extension-власника.
+- Мета: перевірити pipeline Gateway + agent, використовуючи локальний backend CLI, не торкаючись вашої стандартної конфігурації.
+- Значення димового тестування backend за замовчуванням для конкретного backend містяться у визначенні `cli-backend.ts` extension-власника.
- Увімкнення:
- `pnpm test:live` (або `OPENCLAW_LIVE_TEST=1`, якщо викликаєте Vitest напряму)
- `OPENCLAW_LIVE_CLI_BACKEND=1`
-- Типові значення:
- - Типовий провайдер/модель: `claude-cli/claude-sonnet-4-6`
- - Поведінка command/args/image береться з метаданих plugin-а власника CLI backend.
+- Значення за замовчуванням:
+ - Провайдер/модель за замовчуванням: `claude-cli/claude-sonnet-4-6`
+ - Поведінка команди/аргументів/зображень береться з метаданих plugin-а backend CLI-власника.
- Перевизначення (необов’язково):
- `OPENCLAW_LIVE_CLI_BACKEND_MODEL="codex-cli/gpt-5.5"`
- `OPENCLAW_LIVE_CLI_BACKEND_COMMAND="/full/path/to/codex"`
- `OPENCLAW_LIVE_CLI_BACKEND_ARGS='["exec","--json","--color","never","--sandbox","read-only","--skip-git-repo-check"]'`
- - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE=1`, щоб надіслати реальний attachment зображення (шляхи інжектуються в prompt).
- - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"`, щоб передавати шляхи файлів зображень як CLI args замість інжекції в prompt.
- - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"` (або `"list"`), щоб контролювати спосіб передавання args зображень, коли встановлено `IMAGE_ARG`.
- - `OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1`, щоб надіслати другий хід і перевірити потік відновлення.
- - `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0`, щоб вимкнути типовий probe безперервності тієї самої сесії Claude Sonnet -> Opus (установіть `1`, щоб примусово ввімкнути його, коли вибрана модель підтримує ціль перемикання).
+ - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE=1`, щоб надіслати реальне вкладення-зображення (шляхи інжектяться в prompt).
+ - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"`, щоб передавати шляхи до файлів зображень як аргументи CLI замість інжекції в prompt.
+ - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"` (або `"list"`), щоб керувати способом передавання аргументів зображень, коли встановлено `IMAGE_ARG`.
+ - `OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1`, щоб надіслати другий хід і перевірити потік resume.
+ - `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0`, щоб вимкнути стандартний probe безперервності тієї самої сесії Claude Sonnet -> Opus (встановіть `1`, щоб примусово його ввімкнути, коли вибрана модель підтримує ціль перемикання).
Приклад:
@@ -596,7 +597,7 @@ OPENCLAW_LIVE_CLI_BACKEND=1 \
pnpm test:docker:live-cli-backend
```
-Рецепти Docker для одного провайдера:
+Рецепти Docker для окремих провайдерів:
```bash
pnpm test:docker:live-cli-backend:claude
@@ -607,29 +608,29 @@ pnpm test:docker:live-cli-backend:gemini
Примітки:
-- Docker runner розміщений у `scripts/test-live-cli-backend-docker.sh`.
-- Він запускає smoke live CLI-backend усередині Docker-образу репозиторію від імені користувача `node`, який не є root.
-- Він визначає метадані CLI smoke з extension-власника, а потім установлює відповідний Linux CLI package (`@anthropic-ai/claude-code`, `@openai/codex` або `@google/gemini-cli`) у кешований доступний для запису префікс у `OPENCLAW_DOCKER_CLI_TOOLS_DIR` (типово: `~/.cache/openclaw/docker-cli-tools`).
-- `pnpm test:docker:live-cli-backend:claude-subscription` потребує portable OAuth передплати Claude Code через `~/.claude/.credentials.json` з `claudeAiOauth.subscriptionType` або `CLAUDE_CODE_OAUTH_TOKEN` з `claude setup-token`. Спочатку він доводить прямий `claude -p` у Docker, а потім виконує два ходи Gateway CLI-backend без збереження env-змінних API key Anthropic. Цей lane передплати типово вимикає probe Claude MCP/tool і image, оскільки Claude зараз маршрутизує використання сторонніх застосунків через білінг extra-usage, а не звичайні ліміти плану передплати.
-- Smoke live CLI-backend тепер перевіряє той самий end-to-end потік для Claude, Codex і Gemini: текстовий хід, хід класифікації зображення, потім виклик інструмента MCP `cron`, перевірений через CLI gateway.
-- Типовий smoke Claude також змінює сесію з Sonnet на Opus і перевіряє, що відновлена сесія все ще пам’ятає попередню нотатку.
+- Docker-ранер розміщений у `scripts/test-live-cli-backend-docker.sh`.
+- Він запускає димове тестування live CLI-backend усередині Docker-образу репозиторію від імені непривілейованого користувача `node`.
+- Він визначає метадані димового тестування CLI з extension-власника, а потім встановлює відповідний Linux-пакет CLI (`@anthropic-ai/claude-code`, `@openai/codex` або `@google/gemini-cli`) у кешований доступний для запису префікс за адресою `OPENCLAW_DOCKER_CLI_TOOLS_DIR` (за замовчуванням: `~/.cache/openclaw/docker-cli-tools`).
+- `pnpm test:docker:live-cli-backend:claude-subscription` вимагає переносиму OAuth-автентифікацію підписки Claude Code через або `~/.claude/.credentials.json` із `claudeAiOauth.subscriptionType`, або `CLAUDE_CODE_OAUTH_TOKEN` із `claude setup-token`. Спочатку він доводить прямий запуск `claude -p` у Docker, а потім виконує два ходи Gateway CLI-backend без збереження env-змінних API-ключа Anthropic. Ця лінія підписки за замовчуванням вимикає probe Claude MCP/tool і image, оскільки Claude наразі маршрутизує використання сторонніх застосунків через тарифікацію extra-usage, а не через звичайні ліміти плану підписки.
+- Димове тестування live CLI-backend тепер перевіряє той самий наскрізний потік для Claude, Codex і Gemini: текстовий хід, хід класифікації зображення, потім виклик інструмента MCP `cron`, перевірений через CLI gateway.
+- Стандартне димове тестування Claude також оновлює сесію з Sonnet до Opus і перевіряє, що відновлена сесія все ще пам’ятає попередню нотатку.
-## Live: smoke ACP bind (`/acp spawn ... --bind here`)
+## Live: димове тестування ACP bind (`/acp spawn ... --bind here`)
- Тест: `src/gateway/gateway-acp-bind.live.test.ts`
-- Мета: перевірити реальний потік conversation-bind ACP з live ACP agent:
+- Мета: перевірити реальний потік conversation-bind ACP із live ACP agent:
- надіслати `/acp spawn --bind here`
- - прив’язати синтетичну conversation каналу повідомлень на місці
- - надіслати звичайне подальше повідомлення в тій самій conversation
- - перевірити, що подальше повідомлення потрапляє до transcript прив’язаної ACP session
+ - прив’язати синтетичну розмову message-channel на місці
+ - надіслати звичайний подальший запит у тій самій розмові
+ - перевірити, що подальший запит потрапляє до транскрипту прив’язаної ACP-сесії
- Увімкнення:
- `pnpm test:live src/gateway/gateway-acp-bind.live.test.ts`
- `OPENCLAW_LIVE_ACP_BIND=1`
-- Типові значення:
- - ACP agent-и в Docker: `claude,codex,gemini`
- - ACP agent для прямого `pnpm test:live ...`: `claude`
- - Синтетичний канал: контекст conversation у стилі Slack DM
- - ACP backend: `acpx`
+- Значення за замовчуванням:
+ - ACP-агенти в Docker: `claude,codex,gemini`
+ - ACP-агент для прямого `pnpm test:live ...`: `claude`
+ - Синтетичний канал: контекст розмови у стилі Slack DM
+ - ACP-backend: `acpx`
- Перевизначення:
- `OPENCLAW_LIVE_ACP_BIND_AGENT=claude`
- `OPENCLAW_LIVE_ACP_BIND_AGENT=codex`
@@ -638,8 +639,8 @@ pnpm test:docker:live-cli-backend:gemini
- `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND='npx -y @agentclientprotocol/claude-agent-acp@'`
- `OPENCLAW_LIVE_ACP_BIND_CODEX_MODEL=gpt-5.5`
- Примітки:
- - Цей lane використовує поверхню gateway `chat.send` з admin-only синтетичними полями originating-route, щоб тести могли прикріпити контекст message-channel без удавання зовнішньої доставки.
- - Коли `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND` не задано, тест використовує вбудований реєстр agent-ів plugin-а `acpx` для вибраного ACP harness agent.
+ - Ця лінія використовує поверхню gateway `chat.send` з admin-only синтетичними полями originating-route, щоб тести могли прикріплювати контекст message-channel без удавання зовнішньої доставки.
+ - Коли `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND` не встановлено, тест використовує вбудований реєстр агентів plugin `acpx` для вибраного ACP harness agent.
Приклад:
@@ -655,7 +656,7 @@ OPENCLAW_LIVE_ACP_BIND=1 \
pnpm test:docker:live-acp-bind
```
-Рецепти Docker для одного agent-а:
+Рецепти Docker для окремих агентів:
```bash
pnpm test:docker:live-acp-bind:claude
@@ -665,34 +666,35 @@ pnpm test:docker:live-acp-bind:gemini
Примітки щодо Docker:
-- Docker runner розміщений у `scripts/test-live-acp-bind-docker.sh`.
-- Типово він запускає smoke ACP bind для всіх підтримуваних live CLI agent-ів послідовно: `claude`, `codex`, потім `gemini`.
+- Docker-ранер розміщений у `scripts/test-live-acp-bind-docker.sh`.
+- За замовчуванням він запускає димове тестування ACP bind послідовно для всіх підтримуваних live CLI agent: `claude`, `codex`, потім `gemini`.
- Використовуйте `OPENCLAW_LIVE_ACP_BIND_AGENTS=claude`, `OPENCLAW_LIVE_ACP_BIND_AGENTS=codex` або `OPENCLAW_LIVE_ACP_BIND_AGENTS=gemini`, щоб звузити матрицю.
-- Він читає `~/.profile`, переносить відповідні матеріали авторизації CLI в контейнер, установлює `acpx` у доступний для запису npm-префікс, а потім установлює потрібний live CLI (`@anthropic-ai/claude-code`, `@openai/codex` або `@google/gemini-cli`), якщо його немає.
-- Усередині Docker runner встановлює `OPENCLAW_LIVE_ACP_BIND_ACPX_COMMAND=$HOME/.npm-global/bin/acpx`, щоб `acpx` зберігав env-змінні провайдера з прочитаного profile доступними для дочірнього CLI harness.
+- Він використовує `~/.profile`, готує відповідний auth-матеріал CLI у контейнері, встановлює `acpx` у доступний для запису npm-префікс, а потім, якщо потрібно, встановлює запитаний live CLI (`@anthropic-ai/claude-code`, `@openai/codex` або `@google/gemini-cli`).
+- Усередині Docker раннер встановлює `OPENCLAW_LIVE_ACP_BIND_ACPX_COMMAND=$HOME/.npm-global/bin/acpx`, щоб `acpx` зберігав env-змінні провайдера з `profile`, доступні для дочірнього harness CLI.
-## Live: smoke app-server harness Codex
+## Live: димове тестування harness app-server Codex
-- Мета: перевірити harness Codex, що належить plugin-у, через звичайний метод gateway
- `agent`:
- - завантажити вбудований plugin `codex`
+- Мета: перевірити harness Codex, що належить plugin, через стандартний
+ метод gateway `agent`:
+ - завантажити bundled plugin `codex`
- вибрати `OPENCLAW_AGENT_RUNTIME=codex`
- надіслати перший хід gateway agent до `codex/gpt-5.5`
- - надіслати другий хід до тієї самої сесії OpenClaw і перевірити, що thread app-server
+ - надіслати другий хід у ту саму сесію OpenClaw і перевірити, що потік app-server
може відновитися
- - виконати `/codex status` і `/codex models` через той самий шлях команд gateway
- - за потреби виконати два shell probe з ескалацією, перевірені Guardian: одну нешкідливу
- команду, яку слід схвалити, і одне фіктивне вивантаження секрету, яке має бути
- відхилене, щоб agent перепитав
+ - запустити `/codex status` і `/codex models` через той самий шлях команди
+ gateway
+ - за потреби виконати два shell-probe з підвищеними правами, перевірені Guardian: одну нешкідливу
+ команду, яку має бути схвалено, і одне фальшиве завантаження секрету,
+ яке має бути відхилено, щоб агент перепитав
- Тест: `src/gateway/gateway-codex-harness.live.test.ts`
- Увімкнення: `OPENCLAW_LIVE_CODEX_HARNESS=1`
-- Типова модель: `codex/gpt-5.5`
+- Модель за замовчуванням: `codex/gpt-5.5`
- Необов’язковий image probe: `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1`
- Необов’язковий MCP/tool probe: `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1`
-- Необов’язковий probe Guardian: `OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=1`
-- Smoke встановлює `OPENCLAW_AGENT_HARNESS_FALLBACK=none`, щоб зламаний
- harness Codex не міг пройти, непомітно переключившись на PI.
-- Авторизація: `OPENAI_API_KEY` з shell/profile, а також необов’язково скопійовані
+- Необов’язковий Guardian probe: `OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=1`
+- Це димове тестування встановлює `OPENCLAW_AGENT_HARNESS_FALLBACK=none`, щоб зламаний harness Codex
+ не міг пройти, тихо переключившись на PI.
+- Автентифікація: `OPENAI_API_KEY` із shell/profile, плюс необов’язково скопійовані
`~/.codex/auth.json` і `~/.codex/config.toml`
Локальний рецепт:
@@ -716,50 +718,50 @@ pnpm test:docker:live-codex-harness
Примітки щодо Docker:
-- Docker runner розміщений у `scripts/test-live-codex-harness-docker.sh`.
-- Він читає змонтований `~/.profile`, передає `OPENAI_API_KEY`, копіює файли
- авторизації Codex CLI, якщо вони наявні, установлює `@openai/codex` у змонтований npm-префікс із можливістю запису,
- переносить source tree, а потім запускає лише live-тест Codex-harness.
-- Docker типово вмикає image, MCP/tool і Guardian probe. Установіть
- `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0` або
- `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0` або
- `OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0`, коли потрібен вужчий налагоджувальний
- запуск.
-- Docker також експортує `OPENCLAW_AGENT_HARNESS_FALLBACK=none`, як і config live-тесту, щоб fallback `openai-codex/*` або PI не міг приховати регресію harness Codex.
+- Docker-ранер розміщений у `scripts/test-live-codex-harness-docker.sh`.
+- Він використовує змонтований `~/.profile`, передає `OPENAI_API_KEY`, копіює файли
+ автентифікації Codex CLI, якщо вони є, встановлює `@openai/codex` у доступний для запису змонтований npm-префікс,
+ готує дерево вихідних файлів, а потім запускає лише live-тест Codex-harness.
+- Docker за замовчуванням вмикає image-, MCP/tool- і Guardian-probe. Встановіть
+ `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0`, або
+ `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0`, або
+ `OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0`, коли вам потрібен вужчий прогін для налагодження.
+- Docker також експортує `OPENCLAW_AGENT_HARNESS_FALLBACK=none`, як і конфігурація live-тесту,
+ щоб fallback `openai-codex/*` або PI не міг приховати регресію Codex harness.
-### Рекомендовані live-рецепти
+### Рекомендовані рецепти live
-Найшвидші та найменш нестабільні — вузькі явні allowlist:
+Найшвидші та найменш нестабільні — вузькі, явні allowlist:
-- Одна модель, direct (без gateway):
+- Одна модель, напряму (без gateway):
- `OPENCLAW_LIVE_MODELS="openai/gpt-5.5" pnpm test:live src/agents/models.profiles.live.test.ts`
-- Одна модель, gateway smoke:
+- Одна модель, димове тестування gateway:
- `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.5" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
-- Tool calling через кількох провайдерів:
+- Виклик інструментів у кількох провайдерів:
- `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.5,anthropic/claude-opus-4-6,google/gemini-3-flash-preview,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
-- Фокус на Google (Gemini API key + Antigravity):
- - Gemini (API key): `OPENCLAW_LIVE_GATEWAY_MODELS="google/gemini-3-flash-preview" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
+- Фокус на Google (API-ключ Gemini + Antigravity):
+ - Gemini (API-ключ): `OPENCLAW_LIVE_GATEWAY_MODELS="google/gemini-3-flash-preview" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
- Antigravity (OAuth): `OPENCLAW_LIVE_GATEWAY_MODELS="google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-pro-high" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
Примітки:
-- `google/...` використовує Gemini API (API key).
-- `google-antigravity/...` використовує міст OAuth Antigravity (кінцева точка agent у стилі Cloud Code Assist).
-- `google-gemini-cli/...` використовує локальний CLI Gemini на вашій машині (окрема авторизація + особливості tooling).
+- `google/...` використовує Gemini API (API-ключ).
+- `google-antigravity/...` використовує міст Antigravity OAuth (endpoint агента в стилі Cloud Code Assist).
+- `google-gemini-cli/...` використовує локальний Gemini CLI на вашій машині (окрема автентифікація + особливості інструментів).
- Gemini API проти Gemini CLI:
- - API: OpenClaw викликає розміщений Google Gemini API через HTTP (API key / авторизація профілю); саме це більшість користувачів мають на увазі під «Gemini».
- - CLI: OpenClaw викликає локальний binary `gemini`; він має власну авторизацію і може поводитися інакше (streaming/tool support/version skew).
+ - API: OpenClaw викликає розміщений Google Gemini API через HTTP (автентифікація API-ключем / профілем); зазвичай саме це більшість користувачів мають на увазі під “Gemini”.
+ - CLI: OpenClaw викликає локальний бінарний файл `gemini`; він має власну автентифікацію та може поводитися інакше (streaming/підтримка інструментів/version skew).
## Live: матриця моделей (що ми покриваємо)
-Фіксованого «списку моделей CI» немає (live — це opt-in), але ось **рекомендовані** моделі, які варто регулярно покривати на машині розробника з ключами.
+Немає фіксованого «списку моделей CI» (live вмикається за потреби), але це **рекомендовані** моделі для регулярного покриття на dev-машині з ключами.
-### Набір сучасного smoke (tool calling + image)
+### Сучасний набір димового тестування (виклик інструментів + image)
-Це запуск «поширених моделей», який ми очікуємо підтримувати працездатним:
+Це прогін «типових моделей», який ми очікуємо підтримувати в робочому стані:
- OpenAI (не Codex): `openai/gpt-5.5` (необов’язково: `openai/gpt-5.4-mini`)
- OpenAI Codex: `openai-codex/gpt-5.5`
@@ -769,12 +771,12 @@ pnpm test:docker:live-codex-harness
- Z.AI (GLM): `zai/glm-4.7`
- MiniMax: `minimax/MiniMax-M2.7`
-Запуск gateway smoke з tools + image:
+Запуск димового тестування gateway з інструментами + image:
`OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.5,openai-codex/gpt-5.5,anthropic/claude-opus-4-6,google/gemini-3.1-pro-preview,google/gemini-3-flash-preview,google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-flash,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
-### Базовий рівень: tool calling (Read + необов’язковий Exec)
+### Базовий рівень: виклик інструментів (Read + необов’язковий Exec)
-Виберіть щонайменше одну модель для кожного сімейства провайдерів:
+Виберіть щонайменше одну модель з кожної родини провайдерів:
- OpenAI: `openai/gpt-5.5` (або `openai/gpt-5.4-mini`)
- Anthropic: `anthropic/claude-opus-4-6` (або `anthropic/claude-sonnet-4-6`)
@@ -782,44 +784,44 @@ pnpm test:docker:live-codex-harness
- Z.AI (GLM): `zai/glm-4.7`
- MiniMax: `minimax/MiniMax-M2.7`
-Необов’язкове додаткове покриття (добре мати):
+Необов’язкове додаткове покриття (було б добре мати):
-- xAI: `xai/grok-4` (або найновішу доступну)
-- Mistral: `mistral/`… (виберіть одну модель із підтримкою `tools`, яку ви увімкнули)
-- Cerebras: `cerebras/`… (якщо маєте доступ)
-- LM Studio: `lmstudio/`… (локально; tool calling залежить від режиму API)
+- xAI: `xai/grok-4` (або найновіша доступна)
+- Mistral: `mistral/`… (виберіть одну модель із підтримкою `tools`, яку у вас увімкнено)
+- Cerebras: `cerebras/`… (якщо у вас є доступ)
+- LM Studio: `lmstudio/`… (локально; виклик інструментів залежить від режиму API)
-### Vision: надсилання зображення (attachment → мультимодальне повідомлення)
+### Vision: надсилання image (вкладення → мультимодальне повідомлення)
-Додайте щонайменше одну модель із підтримкою зображень до `OPENCLAW_LIVE_GATEWAY_MODELS` (варіанти Claude/Gemini/OpenAI з підтримкою vision тощо), щоб перевірити image probe.
+Додайте щонайменше одну модель із підтримкою зображень у `OPENCLAW_LIVE_GATEWAY_MODELS` (варіанти Claude/Gemini/OpenAI з підтримкою vision тощо), щоб перевірити image probe.
-### Aggregators / альтернативні gateway
+### Агрегатори / альтернативні Gateway
Якщо у вас увімкнені ключі, ми також підтримуємо тестування через:
- OpenRouter: `openrouter/...` (сотні моделей; використовуйте `openclaw models scan`, щоб знайти кандидатів із підтримкою tools+image)
-- OpenCode: `opencode/...` для Zen і `opencode-go/...` для Go (авторизація через `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY`)
+- OpenCode: `opencode/...` для Zen і `opencode-go/...` для Go (автентифікація через `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY`)
-Більше провайдерів, які можна включити до live matrix (якщо у вас є облікові дані/config):
+Більше провайдерів, які можна включити в live-матрицю (якщо у вас є облікові дані/конфігурація):
- Вбудовані: `openai`, `openai-codex`, `anthropic`, `google`, `google-vertex`, `google-antigravity`, `google-gemini-cli`, `zai`, `openrouter`, `opencode`, `opencode-go`, `xai`, `groq`, `cerebras`, `mistral`, `github-copilot`
-- Через `models.providers` (користувацькі кінцеві точки): `minimax` (cloud/API), а також будь-який OpenAI/Anthropic-сумісний proxy (LM Studio, vLLM, LiteLLM тощо)
+- Через `models.providers` (custom endpoint): `minimax` (cloud/API), а також будь-який OpenAI/Anthropic-сумісний proxy (LM Studio, vLLM, LiteLLM тощо)
-Порада: не намагайтеся жорстко прописати в документації «всі моделі». Авторитетний список — це те, що повертає `discoverModels(...)` на вашій машині, плюс доступні ключі.
+Порада: не намагайтеся жорстко зашивати в документацію «всі моделі». Авторитетний список — це те, що повертає `discoverModels(...)` на вашій машині, плюс ті ключі, які доступні.
## Облікові дані (ніколи не комітьте)
-Live-тести знаходять облікові дані так само, як CLI. Практичні наслідки:
+Live-тести знаходять облікові дані так само, як і CLI. Практичні наслідки:
-- Якщо CLI працює, live-тести мають знаходити ті самі ключі.
+- Якщо CLI працює, live-тести мають знайти ті самі ключі.
- Якщо live-тест каже «немає облікових даних», налагоджуйте це так само, як налагоджували б `openclaw models list` / вибір моделі.
-- Профілі авторизації для окремих агентів: `~/.openclaw/agents//agent/auth-profiles.json` (саме це означає «ключі профілів» у live-тестах)
-- Config: `~/.openclaw/openclaw.json` (або `OPENCLAW_CONFIG_PATH`)
-- Каталог застарілого стану: `~/.openclaw/credentials/` (копіюється до staged live home, якщо присутній, але це не основне сховище ключів профілів)
-- Локальні live-запуски типово копіюють активний config, файли `auth-profiles.json` для окремих агентів, застарілий `credentials/` і підтримувані зовнішні каталоги авторизації CLI до тимчасового test home; staged live homes пропускають `workspace/` і `sandboxes/`, а перевизначення шляхів `agents.*.workspace` / `agentDir` прибираються, щоб probe не торкалися вашого реального workspace хоста.
+- Профілі автентифікації для окремих агентів: `~/.openclaw/agents//agent/auth-profiles.json` (саме це означає «ключі профілів» у live-тестах)
+- Конфігурація: `~/.openclaw/openclaw.json` (або `OPENCLAW_CONFIG_PATH`)
+- Каталог застарілого стану: `~/.openclaw/credentials/` (копіюється в підготовлений live-home, якщо присутній, але не є основним сховищем ключів профілів)
+- Локальні live-запуски за замовчуванням копіюють активну конфігурацію, файли `auth-profiles.json` для окремих агентів, застарілий `credentials/` і підтримувані зовнішні каталоги автентифікації CLI у тимчасовий test home; підготовлені live-home пропускають `workspace/` і `sandboxes/`, а перевизначення шляхів `agents.*.workspace` / `agentDir` видаляються, щоб probe не торкалися вашого реального workspace хоста.
-Якщо ви хочете покладатися на env-ключі (наприклад, експортовані у вашому `~/.profile`), запускайте локальні тести після `source ~/.profile` або використовуйте Docker runners нижче (вони можуть монтувати `~/.profile` у контейнер).
+Якщо ви хочете покладатися на env-ключі (наприклад, експортовані у вашому `~/.profile`), запускайте локальні тести після `source ~/.profile`, або використовуйте Docker-ранери нижче (вони можуть монтувати `~/.profile` у контейнер).
## Live Deepgram (транскрипція аудіо)
@@ -832,31 +834,31 @@ Live-тести знаходять облікові дані так само, я
- Увімкнення: `BYTEPLUS_API_KEY=... BYTEPLUS_LIVE_TEST=1 pnpm test:live extensions/byteplus/live.test.ts`
- Необов’язкове перевизначення моделі: `BYTEPLUS_CODING_MODEL=ark-code-latest`
-## Live workflow media ComfyUI
+## Live ComfyUI workflow media
- Тест: `extensions/comfy/comfy.live.test.ts`
- Увімкнення: `OPENCLAW_LIVE_TEST=1 COMFY_LIVE_TEST=1 pnpm test:live -- extensions/comfy/comfy.live.test.ts`
-- Область:
- - Перевіряє вбудовані шляхи comfy для зображень, відео і `music_generate`
+- Обсяг:
+ - Перевіряє bundled-шляхи comfy для image, video і `music_generate`
- Пропускає кожну можливість, якщо не налаштовано `models.providers.comfy.`
- - Корисно після змін у надсиланні workflow comfy, polling, завантаженнях або реєстрації plugin-а
+ - Корисно після змін у надсиланні workflow comfy, polling, завантаженнях або реєстрації plugin
## Live генерація зображень
- Тест: `test/image-generation.runtime.live.test.ts`
- Команда: `pnpm test:live test/image-generation.runtime.live.test.ts`
- Harness: `pnpm test:live:media image`
-- Область:
- - Перелічує кожен зареєстрований provider plugin генерації зображень
- - Завантажує відсутні env-змінні провайдерів із вашого login shell (`~/.profile`) перед probe
- - Типово використовує live/env API key раніше за збережені профілі авторизації, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні облікові дані shell
- - Пропускає провайдерів без придатної авторизації/профілю/моделі
+- Обсяг:
+ - Перелічує кожен зареєстрований plugin провайдера генерації зображень
+ - Завантажує відсутні env-змінні провайдера з вашого login shell (`~/.profile`) перед probe
+ - За замовчуванням використовує live/env API-ключі раніше за збережені auth-профілі, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні shell-облікові дані
+ - Пропускає провайдерів без придатної автентифікації/профілю/моделі
- Запускає стандартні варіанти генерації зображень через спільну runtime-можливість:
- `google:flash-generate`
- `google:pro-generate`
- `google:pro-edit`
- `openai:default-generate`
-- Поточні вбудовані провайдери, які покриваються:
+- Поточні bundled-провайдери, які покриваються:
- `fal`
- `google`
- `minimax`
@@ -867,290 +869,291 @@ Live-тести знаходять облікові дані так само, я
- `OPENCLAW_LIVE_IMAGE_GENERATION_PROVIDERS="openai,google,xai"`
- `OPENCLAW_LIVE_IMAGE_GENERATION_MODELS="openai/gpt-image-2,google/gemini-3.1-flash-image-preview,xai/grok-imagine-image"`
- `OPENCLAW_LIVE_IMAGE_GENERATION_CASES="google:flash-generate,google:pro-edit,xai:default-generate,xai:default-edit"`
-- Необов’язкова поведінка авторизації:
- - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати авторизацію зі сховища профілів і ігнорувати перевизначення лише з env
+- Необов’язкова поведінка автентифікації:
+ - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати автентифікацію зі сховища профілів і ігнорувати перевизначення лише через env
## Live генерація музики
- Тест: `extensions/music-generation-providers.live.test.ts`
- Увімкнення: `OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/music-generation-providers.live.test.ts`
- Harness: `pnpm test:live:media music`
-- Область:
- - Перевіряє спільний вбудований шлях провайдерів генерації музики
- - Наразі покриває Google і MiniMax
- - Завантажує env-змінні провайдерів із вашого login shell (`~/.profile`) перед probe
- - Типово використовує live/env API key раніше за збережені профілі авторизації, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні облікові дані shell
- - Пропускає провайдерів без придатної авторизації/профілю/моделі
+- Обсяг:
+ - Перевіряє спільний bundled-шлях провайдера генерації музики
+ - Наразі охоплює Google і MiniMax
+ - Завантажує env-змінні провайдера з вашого login shell (`~/.profile`) перед probe
+ - За замовчуванням використовує live/env API-ключі раніше за збережені auth-профілі, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні shell-облікові дані
+ - Пропускає провайдерів без придатної автентифікації/профілю/моделі
- Запускає обидва оголошені runtime-режими, коли вони доступні:
- - `generate` з вводом лише prompt
+ - `generate` з вхідними даними лише у вигляді prompt
- `edit`, коли провайдер оголошує `capabilities.edit.enabled`
- - Поточне покриття спільного lane:
+ - Поточне покриття спільної лінії:
- `google`: `generate`, `edit`
- `minimax`: `generate`
- - `comfy`: окремий live-файл Comfy, а не цей спільний sweep
+ - `comfy`: окремий live-файл Comfy, не цей спільний прогін
- Необов’язкове звуження:
- `OPENCLAW_LIVE_MUSIC_GENERATION_PROVIDERS="google,minimax"`
- `OPENCLAW_LIVE_MUSIC_GENERATION_MODELS="google/lyria-3-clip-preview,minimax/music-2.5+"`
-- Необов’язкова поведінка авторизації:
- - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати авторизацію зі сховища профілів і ігнорувати перевизначення лише з env
+- Необов’язкова поведінка автентифікації:
+ - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати автентифікацію зі сховища профілів і ігнорувати перевизначення лише через env
## Live генерація відео
- Тест: `extensions/video-generation-providers.live.test.ts`
- Увімкнення: `OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/video-generation-providers.live.test.ts`
- Harness: `pnpm test:live:media video`
-- Область:
- - Перевіряє спільний вбудований шлях провайдерів генерації відео
- - Типово використовує release-safe шлях smoke: провайдери без FAL, один запит text-to-video на провайдера, prompt про лобстера тривалістю одну секунду та обмеження операції для кожного провайдера з `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` (`180000` типово)
- - Типово пропускає FAL, оскільки затримка черги на стороні провайдера може домінувати над часом release; передайте `--video-providers fal` або `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="fal"`, щоб явно його запустити
- - Завантажує env-змінні провайдерів із вашого login shell (`~/.profile`) перед probe
- - Типово використовує live/env API key раніше за збережені профілі авторизації, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні облікові дані shell
- - Пропускає провайдерів без придатної авторизації/профілю/моделі
- - Типово запускає лише `generate`
- - Установіть `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1`, щоб також запускати оголошені режими transform, коли вони доступні:
- - `imageToVideo`, коли провайдер оголошує `capabilities.imageToVideo.enabled` і вибраний провайдер/модель приймає локальний ввід зображення у вигляді буфера в спільному sweep
- - `videoToVideo`, коли провайдер оголошує `capabilities.videoToVideo.enabled` і вибраний провайдер/модель приймає локальний ввід відео у вигляді буфера в спільному sweep
- - Поточні провайдери `imageToVideo`, оголошені, але пропущені у спільному sweep:
- - `vydra`, тому що вбудований `veo3` підтримує лише text, а вбудований `kling` потребує віддалений URL зображення
- - Покриття Vydra, специфічне для провайдера:
+- Обсяг:
+ - Перевіряє спільний bundled-шлях провайдера генерації відео
+ - За замовчуванням використовує безпечний для релізу шлях димового тестування: провайдери без FAL, один запит text-to-video на провайдера, одноcекундний lobster prompt і обмеження операції для кожного провайдера з `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` (`180000` за замовчуванням)
+ - За замовчуванням пропускає FAL, оскільки затримка черги на боці провайдера може домінувати над часом релізу; передайте `--video-providers fal` або `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="fal"`, щоб явно його запустити
+ - Завантажує env-змінні провайдера з вашого login shell (`~/.profile`) перед probe
+ - За замовчуванням використовує live/env API-ключі раніше за збережені auth-профілі, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні shell-облікові дані
+ - Пропускає провайдерів без придатної автентифікації/профілю/моделі
+ - За замовчуванням запускає лише `generate`
+ - Встановіть `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1`, щоб також запускати оголошені режими перетворення, коли вони доступні:
+ - `imageToVideo`, коли провайдер оголошує `capabilities.imageToVideo.enabled` і вибраний провайдер/модель приймає локальний image-вхід на основі buffer у спільному прогоні
+ - `videoToVideo`, коли провайдер оголошує `capabilities.videoToVideo.enabled` і вибраний провайдер/модель приймає локальний video-вхід на основі buffer у спільному прогоні
+ - Поточні оголошені, але пропущені провайдери `imageToVideo` у спільному прогоні:
+ - `vydra`, тому що bundled `veo3` підтримує лише text, а bundled `kling` вимагає віддалений image URL
+ - Специфічне для провайдера покриття Vydra:
- `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_VYDRA_VIDEO=1 pnpm test:live -- extensions/vydra/vydra.live.test.ts`
- - цей файл запускає `veo3` text-to-video плюс lane `kling`, який типово використовує віддалений URL-зразок зображення
+ - цей файл запускає `veo3` text-to-video плюс лінію `kling`, яка за замовчуванням використовує фікстуру з віддаленим image URL
- Поточне live-покриття `videoToVideo`:
- лише `runway`, коли вибрана модель — `runway/gen4_aleph`
- - Поточні провайдери `videoToVideo`, оголошені, але пропущені у спільному sweep:
- - `alibaba`, `qwen`, `xai`, тому що ці шляхи наразі потребують віддалені reference URL `http(s)` / MP4
- - `google`, тому що поточний спільний lane Gemini/Veo використовує локальний буферний ввід, а цей шлях не приймається у спільному sweep
- - `openai`, тому що поточний спільний lane не гарантує доступ до org-specific можливостей video inpaint/remix
+ - Поточні оголошені, але пропущені провайдери `videoToVideo` у спільному прогоні:
+ - `alibaba`, `qwen`, `xai`, тому що ці шляхи наразі вимагають віддалені reference URL `http(s)` / MP4
+ - `google`, тому що поточна спільна лінія Gemini/Veo використовує локальний вхід на основі buffer, і цей шлях не приймається у спільному прогоні
+ - `openai`, тому що поточна спільна лінія не гарантує організаційно-специфічний доступ до video inpaint/remix
- Необов’язкове звуження:
- `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="google,openai,runway"`
- `OPENCLAW_LIVE_VIDEO_GENERATION_MODELS="google/veo-3.1-fast-generate-preview,openai/sora-2,runway/gen4_aleph"`
- - `OPENCLAW_LIVE_VIDEO_GENERATION_SKIP_PROVIDERS=""`, щоб включити кожного провайдера до типового sweep, зокрема FAL
- - `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS=60000`, щоб зменшити обмеження операції для кожного провайдера в агресивному smoke-запуску
-- Необов’язкова поведінка авторизації:
- - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати авторизацію зі сховища профілів і ігнорувати перевизначення лише з env
+ - `OPENCLAW_LIVE_VIDEO_GENERATION_SKIP_PROVIDERS=""`, щоб включити кожного провайдера до стандартного прогону, зокрема FAL
+ - `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS=60000`, щоб зменшити обмеження операції для кожного провайдера під час агресивного димового прогону
+- Необов’язкова поведінка автентифікації:
+ - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати автентифікацію зі сховища профілів і ігнорувати перевизначення лише через env
-## Harness live media
+## Harness для media live
- Команда: `pnpm test:live:media`
- Призначення:
- - Запускає спільні live-набори зображень, музики та відео через один рідний для репозиторію entrypoint
- - Автоматично завантажує відсутні env-змінні провайдерів із `~/.profile`
- - Типово автоматично звужує кожен набір до провайдерів, які зараз мають придатну авторизацію
- - Повторно використовує `scripts/test-live.mjs`, тому поведінка Heartbeat і тихого режиму залишається узгодженою
+ - Запускає спільні live-набори для image, music і video через один рідний для репозиторію entrypoint
+ - Автоматично завантажує відсутні env-змінні провайдера з `~/.profile`
+ - За замовчуванням автоматично звужує кожен набір до провайдерів, які наразі мають придатну автентифікацію
+ - Повторно використовує `scripts/test-live.mjs`, тож поведінка Heartbeat і тихого режиму залишається узгодженою
- Приклади:
- `pnpm test:live:media`
- `pnpm test:live:media image video --providers openai,google,minimax`
- `pnpm test:live:media video --video-providers openai,runway --all-providers`
- `pnpm test:live:media music --quiet`
-## Docker runners (необов’язкові перевірки «працює в Linux»)
+## Docker-ранери (необов’язкові перевірки «працює в Linux»)
-Ці Docker runners поділяються на дві групи:
+Ці Docker-ранери поділяються на дві групи:
-- Runners live-моделей: `test:docker:live-models` і `test:docker:live-gateway` запускають лише відповідний live-файл ключів профілю всередині Docker-образу репозиторію (`src/agents/models.profiles.live.test.ts` і `src/gateway/gateway-models.profiles.live.test.ts`), монтують ваш локальний каталог config і workspace (і читають `~/.profile`, якщо його змонтовано). Відповідні локальні entrypoint-и — `test:live:models-profiles` і `test:live:gateway-profiles`.
-- Docker runners live типово використовують менший smoke-cap, щоб повний sweep у Docker залишався практичним:
- `test:docker:live-models` типово використовує `OPENCLAW_LIVE_MAX_MODELS=12`, а
- `test:docker:live-gateway` типово використовує `OPENCLAW_LIVE_GATEWAY_SMOKE=1`,
+- Live-model ранери: `test:docker:live-models` і `test:docker:live-gateway` запускають лише відповідний live-файл із profile-key усередині Docker-образу репозиторію (`src/agents/models.profiles.live.test.ts` і `src/gateway/gateway-models.profiles.live.test.ts`), монтують ваш локальний каталог конфігурації та workspace (і використовують `~/.profile`, якщо його змонтовано). Відповідні локальні entrypoint — `test:live:models-profiles` і `test:live:gateway-profiles`.
+- Docker live-ранери за замовчуванням використовують меншу межу димового тестування, щоб повний Docker-прогін залишався практичним:
+ `test:docker:live-models` за замовчуванням використовує `OPENCLAW_LIVE_MAX_MODELS=12`, а
+ `test:docker:live-gateway` за замовчуванням використовує `OPENCLAW_LIVE_GATEWAY_SMOKE=1`,
`OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8`,
`OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000` і
`OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`. Перевизначайте ці env-змінні, коли
вам явно потрібне більше вичерпне сканування.
-- `test:docker:all` один раз збирає live Docker image через `test:docker:live-build`, а потім повторно використовує його для двох Docker lanes live. Він також збирає один спільний image `scripts/e2e/Dockerfile` через `test:docker:e2e-build` і повторно використовує його для контейнерних smoke runners E2E, які перевіряють зібраний app.
-- Контейнерні smoke runners: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:npm-onboard-channel-agent`, `test:docker:gateway-network`, `test:docker:mcp-channels`, `test:docker:pi-bundle-mcp-tools`, `test:docker:cron-mcp-cleanup`, `test:docker:plugins`, `test:docker:plugin-update` і `test:docker:config-reload` запускають один або кілька реальних контейнерів і перевіряють інтеграційні шляхи вищого рівня.
+- `test:docker:all` один раз збирає live Docker-образ через `test:docker:live-build`, а потім повторно використовує його для двох Docker-ліній live. Воно також збирає один спільний образ `scripts/e2e/Dockerfile` через `test:docker:e2e-build` і повторно використовує його для контейнерних E2E-ранерів димового тестування, які перевіряють зібраний app.
+- Контейнерні ранери димового тестування: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:npm-onboard-channel-agent`, `test:docker:gateway-network`, `test:docker:mcp-channels`, `test:docker:pi-bundle-mcp-tools`, `test:docker:cron-mcp-cleanup`, `test:docker:plugins`, `test:docker:plugin-update` і `test:docker:config-reload` піднімають один або кілька реальних контейнерів і перевіряють інтеграційні шляхи вищого рівня.
-Docker runners live-моделей також bind-mount-ять лише потрібні CLI homes авторизації (або всі підтримувані, коли запуск не звужено), а потім копіюють їх у домашній каталог контейнера перед запуском, щоб зовнішній CLI OAuth міг оновлювати токени без зміни сховища авторизації хоста:
+Docker-ранери live-model також bind-монтують лише потрібні домівки автентифікації CLI (або всі підтримувані, коли прогін не звужено), а потім копіюють їх у домашній каталог контейнера перед запуском, щоб OAuth зовнішнього CLI міг оновлювати токени без зміни сховища автентифікації хоста:
-- Direct models: `pnpm test:docker:live-models` (скрипт: `scripts/test-live-models-docker.sh`)
-- Smoke ACP bind: `pnpm test:docker:live-acp-bind` (скрипт: `scripts/test-live-acp-bind-docker.sh`)
-- Smoke CLI backend: `pnpm test:docker:live-cli-backend` (скрипт: `scripts/test-live-cli-backend-docker.sh`)
-- Smoke app-server harness Codex: `pnpm test:docker:live-codex-harness` (скрипт: `scripts/test-live-codex-harness-docker.sh`)
+- Прямі моделі: `pnpm test:docker:live-models` (скрипт: `scripts/test-live-models-docker.sh`)
+- Димове тестування ACP bind: `pnpm test:docker:live-acp-bind` (скрипт: `scripts/test-live-acp-bind-docker.sh`)
+- Димове тестування CLI backend: `pnpm test:docker:live-cli-backend` (скрипт: `scripts/test-live-cli-backend-docker.sh`)
+- Димове тестування harness app-server Codex: `pnpm test:docker:live-codex-harness` (скрипт: `scripts/test-live-codex-harness-docker.sh`)
- Gateway + dev agent: `pnpm test:docker:live-gateway` (скрипт: `scripts/test-live-gateway-models-docker.sh`)
-- Live smoke Open WebUI: `pnpm test:docker:openwebui` (скрипт: `scripts/e2e/openwebui-docker.sh`)
-- Майстер онбордингу (TTY, повне scaffold-налаштування): `pnpm test:docker:onboard` (скрипт: `scripts/e2e/onboard-docker.sh`)
-- Smoke онбордингу/channel/agent через npm tarball: `pnpm test:docker:npm-onboard-channel-agent` глобально встановлює запакований tarball OpenClaw у Docker, налаштовує OpenAI через онбординг env-ref і типово Telegram, перевіряє, що ввімкнення plugin встановлює його runtime deps на вимогу, запускає doctor і виконує один мокований хід agent проти OpenAI. Повторно використовуйте попередньо зібраний tarball через `OPENCLAW_NPM_ONBOARD_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, пропустіть перебудову на хості через `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` або змініть канал через `OPENCLAW_NPM_ONBOARD_CHANNEL=discord`.
-- Мережа Gateway (два контейнери, WS auth + health): `pnpm test:docker:gateway-network` (скрипт: `scripts/e2e/gateway-network-docker.sh`)
-- Мінімальна reasoning-регресія OpenAI Responses web_search: `pnpm test:docker:openai-web-search-minimal` (скрипт: `scripts/e2e/openai-web-search-minimal-docker.sh`) запускає мокований сервер OpenAI через Gateway, перевіряє, що `web_search` підвищує `reasoning.effort` з `minimal` до `low`, потім примусово викликає відхилення provider schema і перевіряє, що сирі подробиці з’являються в логах Gateway.
-- Міст MCP channel (ініціалізований Gateway + stdio bridge + raw smoke notification-frame Claude): `pnpm test:docker:mcp-channels` (скрипт: `scripts/e2e/mcp-channels-docker.sh`)
-- Інструменти Pi bundle MCP (реальний stdio MCP server + smoke allow/deny вбудованого профілю Pi): `pnpm test:docker:pi-bundle-mcp-tools` (скрипт: `scripts/e2e/pi-bundle-mcp-tools-docker.sh`)
-- Очищення Cron/subagent MCP (реальний Gateway + завершення дочірнього stdio MCP після ізольованих запусків cron і одноразового subagent): `pnpm test:docker:cron-mcp-cleanup` (скрипт: `scripts/e2e/cron-mcp-cleanup-docker.sh`)
-- Plugins (smoke встановлення + псевдонім `/plugin` + семантика перезапуску Claude-bundle): `pnpm test:docker:plugins` (скрипт: `scripts/e2e/plugins-docker.sh`)
-- Smoke незмінності оновлення Plugin: `pnpm test:docker:plugin-update` (скрипт: `scripts/e2e/plugin-update-unchanged-docker.sh`)
-- Smoke метаданих перезавантаження config: `pnpm test:docker:config-reload` (скрипт: `scripts/e2e/config-reload-source-docker.sh`)
-- Runtime deps вбудованого plugin: `pnpm test:docker:bundled-channel-deps` типово збирає невеликий образ Docker runner, один раз збирає й пакує OpenClaw на хості, а потім монтує цей tarball у кожен сценарій встановлення Linux. Повторно використовуйте образ через `OPENCLAW_SKIP_DOCKER_BUILD=1`, пропустіть перебудову на хості після свіжої локальної збірки через `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` або вкажіть наявний tarball через `OPENCLAW_BUNDLED_CHANNEL_PACKAGE_TGZ=/path/to/openclaw-*.tgz`.
-- Звужуйте runtime deps вбудованого plugin під час ітерацій, вимикаючи не пов’язані сценарії, наприклад:
+- Димове тестування Open WebUI live: `pnpm test:docker:openwebui` (скрипт: `scripts/e2e/openwebui-docker.sh`)
+- Майстер онбордингу (TTY, повне scaffolding): `pnpm test:docker:onboard` (скрипт: `scripts/e2e/onboard-docker.sh`)
+- Димове тестування онбордингу/каналу/агента через npm tarball: `pnpm test:docker:npm-onboard-channel-agent` глобально встановлює запакований tarball OpenClaw у Docker, налаштовує OpenAI через онбординг з env-ref плюс Telegram за замовчуванням, перевіряє, що ввімкнення plugin встановлює його runtime deps за потреби, запускає doctor і виконує один хід агента з mock OpenAI. Повторно використовуйте попередньо зібраний tarball через `OPENCLAW_NPM_ONBOARD_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, пропустіть host rebuild через `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` або перемкніть канал через `OPENCLAW_NPM_ONBOARD_CHANNEL=discord`.
+- Димове тестування глобального встановлення Bun: `bash scripts/e2e/bun-global-install-smoke.sh` пакує поточне дерево, встановлює його через `bun install -g` в ізольованому home і перевіряє, що `openclaw infer image providers --json` повертає bundled-провайдерів зображень замість зависання. Повторно використовуйте попередньо зібраний tarball через `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, пропустіть host build через `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` або скопіюйте `dist/` зі зібраного Docker-образу через `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local`.
+- Мережева взаємодія Gateway (два контейнери, WS auth + health): `pnpm test:docker:gateway-network` (скрипт: `scripts/e2e/gateway-network-docker.sh`)
+- Мінімальна reasoning-регресія OpenAI Responses web_search: `pnpm test:docker:openai-web-search-minimal` (скрипт: `scripts/e2e/openai-web-search-minimal-docker.sh`) запускає mock OpenAI server через Gateway, перевіряє, що `web_search` підвищує `reasoning.effort` з `minimal` до `low`, потім примусово викликає відхилення schema провайдера й перевіряє, що сирі подробиці з’являються в логах Gateway.
+- Міст каналу MCP (seeded Gateway + міст stdio + димове тестування raw Claude notification-frame): `pnpm test:docker:mcp-channels` (скрипт: `scripts/e2e/mcp-channels-docker.sh`)
+- Інструменти Pi bundle MCP (реальний stdio MCP server + димове тестування allow/deny профілю embedded Pi): `pnpm test:docker:pi-bundle-mcp-tools` (скрипт: `scripts/e2e/pi-bundle-mcp-tools-docker.sh`)
+- Очищення MCP Cron/subagent (реальний Gateway + завершення дочірнього stdio MCP після ізольованих прогонів cron і одноразового subagent): `pnpm test:docker:cron-mcp-cleanup` (скрипт: `scripts/e2e/cron-mcp-cleanup-docker.sh`)
+- Plugins (димове тестування встановлення + псевдонім `/plugin` + семантика перезапуску Claude-bundle): `pnpm test:docker:plugins` (скрипт: `scripts/e2e/plugins-docker.sh`)
+- Димове тестування незмінного оновлення Plugin: `pnpm test:docker:plugin-update` (скрипт: `scripts/e2e/plugin-update-unchanged-docker.sh`)
+- Димове тестування метаданих перезавантаження конфігурації: `pnpm test:docker:config-reload` (скрипт: `scripts/e2e/config-reload-source-docker.sh`)
+- Runtime deps bundled plugin: `pnpm test:docker:bundled-channel-deps` за замовчуванням збирає невеликий образ Docker-ранера, один раз збирає та пакує OpenClaw на host, а потім монтує цей tarball у кожний сценарій встановлення Linux. Повторно використовуйте образ через `OPENCLAW_SKIP_DOCKER_BUILD=1`, пропустіть host rebuild після свіжої локальної збірки через `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` або вкажіть наявний tarball через `OPENCLAW_BUNDLED_CHANNEL_PACKAGE_TGZ=/path/to/openclaw-*.tgz`.
+- Звужуйте runtime deps bundled plugin під час ітерацій, вимикаючи не пов’язані сценарії, наприклад:
`OPENCLAW_BUNDLED_CHANNEL_SCENARIOS=0 OPENCLAW_BUNDLED_CHANNEL_UPDATE_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_ROOT_OWNED_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_SETUP_ENTRY_SCENARIO=0 pnpm test:docker:bundled-channel-deps`.
-Щоб вручну попередньо зібрати й повторно використовувати спільний образ built-app:
+Щоб вручну попередньо зібрати та повторно використовувати спільний образ built-app:
```bash
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e:local pnpm test:docker:e2e-build
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e:local OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels
```
-Перевизначення образів, специфічні для наборів, як-от `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE`, усе ще мають пріоритет, якщо задані. Коли `OPENCLAW_SKIP_DOCKER_BUILD=1` вказує на віддалений спільний образ, скрипти завантажують його, якщо його ще немає локально. QR- і installer-тести Docker зберігають власні Dockerfile, оскільки вони перевіряють поведінку package/install, а не спільний runtime built-app.
+Перевизначення образів для конкретних наборів, як-от `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE`, усе ще мають пріоритет, якщо встановлені. Коли `OPENCLAW_SKIP_DOCKER_BUILD=1` вказує на віддалений спільний образ, скрипти завантажують його, якщо його ще немає локально. Docker-тести QR та інсталятора зберігають власні Dockerfile, тому що вони перевіряють поведінку package/install, а не runtime спільного built-app.
-Docker runners live-моделей також монтують поточний checkout лише для читання і
-переносять його в тимчасовий workdir усередині контейнера. Це зберігає runtime
-image компактним, але все одно запускає Vitest проти ваших точних локальних source/config.
-Крок перенесення пропускає великі локальні кеші й результати збірки app, такі як
+Docker-ранери live-model також монтують поточний checkout лише для читання і
+підготовлюють його у тимчасовому workdir усередині контейнера. Це зберігає
+runtime image компактним, водночас усе одно запускаючи Vitest проти ваших точних локальних source/config.
+Крок підготовки пропускає великі локальні кеші та результати збірки app, такі як
`.pnpm-store`, `.worktrees`, `__openclaw_vitest__` і локальні для app каталоги `.build` або
виводу Gradle, щоб Docker live-запуски не витрачали хвилини на копіювання
машинно-специфічних артефактів.
-Вони також встановлюють `OPENCLAW_SKIP_CHANNELS=1`, щоб live probe Gateway не запускали
-реальні worker-и каналів Telegram/Discord/etc. усередині контейнера.
+Вони також встановлюють `OPENCLAW_SKIP_CHANNELS=1`, щоб live-probe Gateway не запускали
+реальні воркери каналів Telegram/Discord тощо всередині контейнера.
`test:docker:live-models` усе ще запускає `pnpm test:live`, тож також передавайте
-`OPENCLAW_LIVE_GATEWAY_*`, коли потрібно звузити або виключити gateway
-live-покриття з цього Docker lane.
-`test:docker:openwebui` — це smoke вищого рівня для перевірки сумісності: він запускає
-контейнер Gateway OpenClaw з увімкненими OpenAI-сумісними HTTP endpoint-ами,
-запускає закріплений контейнер Open WebUI проти цього gateway, виконує вхід через
+`OPENCLAW_LIVE_GATEWAY_*`, коли вам потрібно звузити або виключити покриття
+gateway live з цієї Docker-лінії.
+`test:docker:openwebui` — це димове тестування сумісності вищого рівня: воно запускає
+контейнер gateway OpenClaw з увімкненими OpenAI-сумісними HTTP endpoint,
+запускає pin-ований контейнер Open WebUI проти цього gateway, виконує вхід через
Open WebUI, перевіряє, що `/api/models` надає `openclaw/default`, а потім надсилає
реальний chat-запит через proxy `/api/chat/completions` Open WebUI.
-Перший запуск може бути помітно повільнішим, тому що Docker може знадобитися завантажити
-образ Open WebUI, а самому Open WebUI — завершити власне холодне стартове налаштування.
-Цей lane очікує придатний live-ключ моделі, а `OPENCLAW_PROFILE_FILE`
-(типово `~/.profile`) є основним способом надати його в Dockerized-запусках.
+Перший запуск може бути помітно повільнішим, тому що Docker може потребувати завантаження
+образу Open WebUI, а Open WebUI може потребувати завершення власного cold-start налаштування.
+Ця лінія очікує наявність придатного live-ключа моделі, а `OPENCLAW_PROFILE_FILE`
+(`~/.profile` за замовчуванням) — основний спосіб надати його в Dockerized-запусках.
Успішні запуски виводять невеликий JSON payload на кшталт `{ "ok": true, "model":
"openclaw/default", ... }`.
-`test:docker:mcp-channels` навмисно детермінований і не потребує
-реального акаунта Telegram, Discord або iMessage. Він запускає ініціалізований контейнер
+`test:docker:mcp-channels` навмисно є детермінованим і не потребує
+реального облікового запису Telegram, Discord або iMessage. Воно запускає seeded контейнер
Gateway, запускає другий контейнер, який піднімає `openclaw mcp serve`, а потім
-перевіряє виявлення conversation-маршрутизації, читання transcript, метадані attachment,
-поведінку черги live events, маршрутизацію вихідного надсилання та сповіщення у стилі Claude про канал +
-дозволи через реальний stdio MCP bridge. Перевірка сповіщень
-напряму аналізує сирі stdio MCP frames, тож smoke перевіряє те, що міст
-справді випромінює, а не лише те, що випадково показує конкретний client SDK.
+перевіряє виявлення маршрутизованих розмов, читання транскриптів, метадані вкладень,
+поведінку черги live-подій, маршрутизацію outbound send, а також channel- і
+permission-сповіщення у стилі Claude через реальний stdio MCP bridge. Перевірка сповіщень
+безпосередньо аналізує raw stdio MCP frames, тож димове тестування перевіряє те, що
+міст реально випромінює, а не лише те, що випадково надає конкретний SDK клієнта.
`test:docker:pi-bundle-mcp-tools` є детермінованим і не потребує live-ключа
-моделі. Він збирає Docker image репозиторію, запускає реальний stdio MCP probe server
-усередині контейнера, матеріалізує цей server через вбудований runtime Pi bundle
-MCP, виконує інструмент, а потім перевіряє, що `coding` і `messaging` зберігають
+моделі. Воно збирає Docker-образ репозиторію, запускає реальний stdio MCP probe server
+усередині контейнера, матеріалізує цей server через runtime embedded Pi bundle
+MCP, виконує tool, а потім перевіряє, що `coding` і `messaging` зберігають
інструменти `bundle-mcp`, тоді як `minimal` і `tools.deny: ["bundle-mcp"]` їх фільтрують.
`test:docker:cron-mcp-cleanup` є детермінованим і не потребує live-ключа
-моделі. Він запускає ініціалізований Gateway з реальним stdio MCP probe server, виконує
+моделі. Воно запускає seeded Gateway з реальним stdio MCP probe server, виконує
ізольований хід cron і одноразовий дочірній хід `/subagents spawn`, а потім перевіряє,
що дочірній процес MCP завершується після кожного запуску.
-Ручний smoke plain-language thread ACP (не для CI):
+Ручне димове тестування ACP plain-language thread (не CI):
- `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...`
-- Зберігайте цей скрипт для робочих процесів регресії/налагодження. Він може знову знадобитися для перевірки маршрутизації ACP thread, тому не видаляйте його.
+- Зберігайте цей скрипт для workflow регресії/налагодження. Він може знову знадобитися для перевірки маршрутизації ACP thread, тож не видаляйте його.
Корисні env-змінні:
-- `OPENCLAW_CONFIG_DIR=...` (типово: `~/.openclaw`) монтується в `/home/node/.openclaw`
-- `OPENCLAW_WORKSPACE_DIR=...` (типово: `~/.openclaw/workspace`) монтується в `/home/node/.openclaw/workspace`
-- `OPENCLAW_PROFILE_FILE=...` (типово: `~/.profile`) монтується в `/home/node/.profile` і читається перед запуском тестів
-- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1`, щоб перевіряти лише env-змінні, прочитані з `OPENCLAW_PROFILE_FILE`, використовуючи тимчасові каталоги config/workspace і без монтування зовнішньої CLI auth
-- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...` (типово: `~/.cache/openclaw/docker-cli-tools`) монтується в `/home/node/.npm-global` для кешованих установлень CLI усередині Docker
-- Зовнішні каталоги/файли CLI auth у `$HOME` монтуються лише для читання під `/host-auth...`, а потім копіюються в `/home/node/...` перед початком тестів
- - Типові каталоги: `.minimax`
- - Типові файли: `~/.codex/auth.json`, `~/.codex/config.toml`, `.claude.json`, `~/.claude/.credentials.json`, `~/.claude/settings.json`, `~/.claude/settings.local.json`
+- `OPENCLAW_CONFIG_DIR=...` (за замовчуванням: `~/.openclaw`) монтується в `/home/node/.openclaw`
+- `OPENCLAW_WORKSPACE_DIR=...` (за замовчуванням: `~/.openclaw/workspace`) монтується в `/home/node/.openclaw/workspace`
+- `OPENCLAW_PROFILE_FILE=...` (за замовчуванням: `~/.profile`) монтується в `/home/node/.profile` і використовується перед запуском тестів
+- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1`, щоб перевірити лише env-змінні, використані з `OPENCLAW_PROFILE_FILE`, використовуючи тимчасові каталоги config/workspace і без зовнішніх монтувань auth CLI
+- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...` (за замовчуванням: `~/.cache/openclaw/docker-cli-tools`) монтується в `/home/node/.npm-global` для кешованих встановлень CLI усередині Docker
+- Зовнішні каталоги/файли auth CLI під `$HOME` монтуються лише для читання під `/host-auth...`, а потім копіюються в `/home/node/...` перед початком тестів
+ - Каталоги за замовчуванням: `.minimax`
+ - Файли за замовчуванням: `~/.codex/auth.json`, `~/.codex/config.toml`, `.claude.json`, `~/.claude/.credentials.json`, `~/.claude/settings.json`, `~/.claude/settings.local.json`
- Звужені запуски провайдерів монтують лише потрібні каталоги/файли, визначені з `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS`
- - Перевизначайте вручну через `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none` або список через кому на кшталт `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex`
-- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...`, щоб звузити запуск
-- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...`, щоб відфільтрувати провайдерів усередині контейнера
-- `OPENCLAW_SKIP_DOCKER_BUILD=1`, щоб повторно використати наявний образ `openclaw:local-live` для повторних запусків без потреби в перебудові
-- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб переконатися, що облікові дані беруться зі сховища профілів (а не з env)
-- `OPENCLAW_OPENWEBUI_MODEL=...`, щоб вибрати модель, яку gateway надає для smoke Open WebUI
-- `OPENCLAW_OPENWEBUI_PROMPT=...`, щоб перевизначити nonce-check prompt, який використовує smoke Open WebUI
-- `OPENWEBUI_IMAGE=...`, щоб перевизначити закріплений тег образу Open WebUI
+ - Перевизначайте вручну через `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none` або список через кому, наприклад `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex`
+- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...`, щоб звузити прогін
+- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...`, щоб відфільтрувати провайдерів у контейнері
+- `OPENCLAW_SKIP_DOCKER_BUILD=1`, щоб повторно використовувати наявний образ `openclaw:local-live` для повторних запусків, яким не потрібне перебирання
+- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб переконатися, що облікові дані надходять зі сховища профілів (а не з env)
+- `OPENCLAW_OPENWEBUI_MODEL=...`, щоб вибрати модель, яку gateway надає для димового тестування Open WebUI
+- `OPENCLAW_OPENWEBUI_PROMPT=...`, щоб перевизначити prompt перевірки nonce, використаний у димовому тестуванні Open WebUI
+- `OPENWEBUI_IMAGE=...`, щоб перевизначити pin-ований тег образу Open WebUI
-## Перевірка документації
+## Перевірка коректності документації
Після редагування документації запускайте перевірки docs: `pnpm check:docs`.
-Запускайте повну перевірку якорів Mintlify, коли вам також потрібні перевірки заголовків у межах сторінок: `pnpm docs:check-links:anchors`.
+Запускайте повну перевірку anchor у Mintlify, коли вам також потрібні перевірки heading у межах сторінки: `pnpm docs:check-links:anchors`.
-## Офлайн-регресії (безпечні для CI)
+## Офлайн-регресія (безпечна для CI)
Це регресії «реального pipeline» без реальних провайдерів:
-- Tool calling Gateway (мокований OpenAI, реальний цикл gateway + agent): `src/gateway/gateway.test.ts` (випадок: "runs a mock OpenAI tool call end-to-end via gateway agent loop")
-- Wizard Gateway (WS `wizard.start`/`wizard.next`, запис config + примусова auth): `src/gateway/gateway.test.ts` (випадок: "runs wizard over ws and writes auth token config")
+- Виклик інструментів Gateway (mock OpenAI, реальний цикл gateway + agent): `src/gateway/gateway.test.ts` (case: "runs a mock OpenAI tool call end-to-end via gateway agent loop")
+- Майстер Gateway (WS `wizard.start`/`wizard.next`, примусовий запис config + auth): `src/gateway/gateway.test.ts` (case: "runs wizard over ws and writes auth token config")
-## Evals надійності agent (Skills)
+## Оцінювання надійності агента (Skills)
-У нас уже є кілька безпечних для CI тестів, які поводяться як «evals надійності agent»:
+У нас уже є кілька безпечних для CI тестів, які поводяться як «оцінювання надійності агента»:
-- Мокований tool-calling через реальний цикл gateway + agent (`src/gateway/gateway.test.ts`).
-- End-to-end потоки wizard, які перевіряють підключення сесії та ефекти config (`src/gateway/gateway.test.ts`).
+- Mock-виклик інструментів через реальний цикл gateway + agent (`src/gateway/gateway.test.ts`).
+- Наскрізні потоки майстра, які перевіряють прив’язку сесії та ефекти конфігурації (`src/gateway/gateway.test.ts`).
-Чого все ще бракує для Skills (див. [Skills](/uk/tools/skills)):
+Що все ще відсутнє для Skills (див. [Skills](/uk/tools/skills)):
-- **Прийняття рішень:** коли Skills перелічено в prompt, чи вибирає agent правильний skill (або уникає нерелевантних)?
-- **Виконання вимог:** чи читає agent `SKILL.md` перед використанням і чи виконує потрібні кроки/args?
-- **Контракти workflow:** багатокрокові сценарії, які перевіряють порядок інструментів, перенесення історії сесії та межі sandbox.
+- **Прийняття рішень:** коли Skills перелічено в prompt, чи обирає агент правильний Skill (або уникає нерелевантних)?
+- **Відповідність:** чи читає агент `SKILL.md` перед використанням і чи виконує потрібні кроки/аргументи?
+- **Контракти workflow:** multi-turn сценарії, які перевіряють порядок інструментів, перенесення історії сесії та межі sandbox.
Майбутні evals спочатку мають залишатися детермінованими:
-- Runner сценаріїв із мокованими провайдерами для перевірки викликів інструментів + порядку, читання skill-файлів і підключення сесії.
-- Невеликий набір сценаріїв, зосереджених на skill (використати чи уникнути, gating, prompt injection).
-- Необов’язкові live evals (opt-in, із керуванням через env) лише після того, як буде створено безпечний для CI набір.
+- Scenario runner з mock-провайдерами для перевірки викликів інструментів + порядку, читання skill-файлів і прив’язки сесії.
+- Невеликий набір сценаріїв, орієнтованих на skills (використовувати чи уникати, gating, prompt injection).
+- Необов’язкові live evals (увімкнення за потреби, обмеження через env) лише після того, як буде готовий безпечний для CI набір.
## Контрактні тести (форма plugin і channel)
Контрактні тести перевіряють, що кожен зареєстрований plugin і channel відповідає
-своєму контракту інтерфейсу. Вони ітерують усі виявлені plugin-и й запускають набір
-перевірок форми та поведінки. Типовий unit lane `pnpm test` навмисно
-пропускає ці спільні seam- і smoke-файли; запускайте контрактні команди явно,
+своєму інтерфейсному контракту. Вони ітеруються за всіма виявленими plugins і запускають набір
+перевірок форми та поведінки. Стандартна unit-лінія `pnpm test` навмисно
+пропускає ці файли спільних seam і smoke; запускайте контрактні команди явно,
коли торкаєтеся спільних поверхонь channel або provider.
### Команди
-- Усі контракти: `pnpm test:contracts`
-- Лише контракти channel: `pnpm test:contracts:channels`
-- Лише контракти provider: `pnpm test:contracts:plugins`
+- Усі контрактні тести: `pnpm test:contracts`
+- Лише контрактні тести channel: `pnpm test:contracts:channels`
+- Лише контрактні тести provider: `pnpm test:contracts:plugins`
-### Контракти channel
+### Контрактні тести channel
-Розташовані в `src/channels/plugins/contracts/*.contract.test.ts`:
+Розміщені в `src/channels/plugins/contracts/*.contract.test.ts`:
-- **plugin** - Базова форма plugin-а (id, name, capabilities)
+- **plugin** - Базова форма plugin (id, name, capabilities)
- **setup** - Контракт майстра налаштування
- **session-binding** - Поведінка прив’язки сесії
- **outbound-payload** - Структура payload повідомлення
- **inbound** - Обробка вхідних повідомлень
-- **actions** - Обробники дій каналу
-- **threading** - Обробка ID тредів
-- **directory** - API каталогу/реєстру
+- **actions** - Обробники дій channel
+- **threading** - Обробка ID thread
+- **directory** - API directory/roster
- **group-policy** - Застосування групової політики
### Контракти статусу provider
-Розташовані в `src/plugins/contracts/*.contract.test.ts`.
+Розміщені в `src/plugins/contracts/*.contract.test.ts`.
-- **status** - Probe статусу каналу
-- **registry** - Форма реєстру plugin-ів
+- **status** - Перевірки статусу channel
+- **registry** - Форма реєстру plugin
-### Контракти provider
+### Контрактні тести provider
-Розташовані в `src/plugins/contracts/*.contract.test.ts`:
+Розміщені в `src/plugins/contracts/*.contract.test.ts`:
-- **auth** - Контракт потоку авторизації
-- **auth-choice** - Вибір/визначення авторизації
+- **auth** - Контракт потоку автентифікації
+- **auth-choice** - Вибір/добір автентифікації
- **catalog** - API каталогу моделей
-- **discovery** - Виявлення plugin-ів
-- **loader** - Завантаження plugin-ів
-- **runtime** - Runtime провайдера
-- **shape** - Форма/інтерфейс plugin-а
+- **discovery** - Виявлення plugin
+- **loader** - Завантаження plugin
+- **runtime** - Runtime provider
+- **shape** - Форма/інтерфейс plugin
- **wizard** - Майстер налаштування
### Коли запускати
-- Після змін експортів або підшляхів plugin-sdk
-- Після додавання або зміни channel чи provider plugin-а
-- Після рефакторингу реєстрації або виявлення plugin-ів
+- Після зміни export або subpath у plugin-sdk
+- Після додавання або зміни channel чи provider plugin
+- Після рефакторингу реєстрації plugin або виявлення
-Контрактні тести запускаються в CI і не потребують реальних API key.
+Контрактні тести запускаються в CI і не потребують реальних API-ключів.
## Додавання регресій (рекомендації)
-Коли ви виправляєте проблему провайдера/моделі, виявлену в live:
+Коли ви виправляєте проблему provider/model, виявлену в live:
-- Якщо можливо, додайте безпечну для CI регресію (мокований/заглушений провайдер або захоплення точної трансформації форми запиту)
-- Якщо проблема за своєю природою лише live (rate limits, політики авторизації), залишайте live-тест вузьким і opt-in через env-змінні
-- Віддавайте перевагу націленню на найменший шар, який ловить помилку:
- - помилка перетворення/повторення запиту провайдера → direct models test
- - помилка pipeline gateway session/history/tool → gateway live smoke або безпечний для CI мокований тест gateway
-- Guardrail обходу SecretRef:
- - `src/secrets/exec-secret-ref-id-parity.test.ts` виводить одну вибіркову ціль для кожного класу SecretRef із метаданих реєстру (`listSecretTargetRegistryEntries()`), а потім перевіряє, що exec id із сегментом traversal відхиляються.
- - Якщо ви додаєте нове сімейство цілей SecretRef з `includeInPlan` у `src/secrets/target-registry-data.ts`, оновіть `classifyTargetClass` у цьому тесті. Тест навмисно завершується з помилкою для некласифікованих target id, щоб нові класи не можна було тихо пропустити.
+- За можливості додавайте безпечну для CI регресію (mock/stub provider або захоплення точної трансформації форми запиту)
+- Якщо проблема за своєю природою лише live (rate limits, політики автентифікації), залишайте live-тест вузьким і таким, що вмикається через env vars
+- Віддавайте перевагу найменшому шару, який виявляє баг:
+ - баг перетворення/повторення запиту provider → тест прямих моделей
+ - баг pipeline сесії/історії/інструментів gateway → live smoke gateway або безпечний для CI mock-тест gateway
+- Захист SecretRef traversal:
+ - `src/secrets/exec-secret-ref-id-parity.test.ts` виводить по одній вибірковій цілі для кожного класу SecretRef із метаданих реєстру (`listSecretTargetRegistryEntries()`), а потім перевіряє, що exec id із traversal-segment відхиляються.
+ - Якщо ви додаєте нову родину цілей SecretRef `includeInPlan` у `src/secrets/target-registry-data.ts`, оновіть `classifyTargetClass` у цьому тесті. Тест навмисно падає на некласифікованих target id, щоб нові класи не можна було тихо пропустити.
diff --git a/docs/uk/reference/test.md b/docs/uk/reference/test.md
index f167f5c9e..01b8813ee 100644
--- a/docs/uk/reference/test.md
+++ b/docs/uk/reference/test.md
@@ -1,51 +1,53 @@
---
read_when:
- Запуск або виправлення тестів
-summary: Як запускати тести локально (vitest) і коли використовувати режими force/coverage
+summary: Як запускати тести локально (`vitest`) і коли використовувати режими force/coverage
title: Тести
x-i18n:
- generated_at: "2026-04-23T13:58:08Z"
+ generated_at: "2026-04-23T19:48:40Z"
model: gpt-5.4
provider: openai
- source_hash: e0bcecb0868b3b68361e5ef78afc3170f2a481771bda8f7d54200b1d778d044a
+ source_hash: 078ba2d49ffc117b5069304113ab4b08d734ced76f8e0ac491e79375d6f3fde4
source_path: reference/test.md
workflow: 15
---
# Тести
-- Повний набір для тестування (набори, live, Docker): [Тестування](/uk/help/testing)
+- Повний набір для тестування (набори тестів, live, Docker): [Тестування](/uk/help/testing)
-- `pnpm test:force`: Завершує всі завислі процеси gateway, що утримують типовий порт керування, а потім запускає повний набір Vitest з ізольованим портом gateway, щоб тести сервера не конфліктували із запущеним екземпляром. Використовуйте це, коли попередній запуск gateway залишив порт 18789 зайнятим.
-- `pnpm test:coverage`: Запускає набір unit-тестів із покриттям V8 (через `vitest.unit.config.ts`). Це перевірка unit-покриття завантажених файлів, а не покриття всіх файлів у всьому репозиторії. Порогові значення: 70% для рядків/функцій/інструкцій і 55% для гілок. Оскільки `coverage.all` має значення false, перевірка вимірює файли, завантажені набором unit-покриття, замість того щоб вважати кожен файл вихідного коду з розділених lane непокритим.
-- `pnpm test:coverage:changed`: Запускає unit-покриття лише для файлів, змінених відносно `origin/main`.
-- `pnpm test:changed`: розгортає змінені шляхи git у scoped Vitest lane, коли diff торкається лише routable файлів вихідного коду/тестів. Зміни конфігурації/налаштування все одно повертаються до нативного запуску root projects, щоб за потреби зміни в обв’язці запускали ширший повторний прогін.
-- `pnpm changed:lanes`: показує архітектурні lane, які запускаються через diff відносно `origin/main`.
-- `pnpm check:changed`: запускає розумну перевірку changed для diff відносно `origin/main`. Вона запускає core-частину разом із lane тестів core, роботу extension — із lane тестів extension, зміни лише в тестах — тільки з typecheck/tests для тестів, розширює зміни публічного Plugin SDK або plugin-contract до перевірки extension, а також залишає метадані релізу з оновленням лише версії на цільових перевірках version/config/root-dependency.
-- `pnpm test`: маршрутизує явні цілі файлів/каталогів через scoped Vitest lane. Запуски без конкретної цілі використовують фіксовані групи shard і розгортаються до leaf configs для локального паралельного виконання; група extension завжди розгортається до конфігурацій shard для кожного extension/plugin, а не в один великий процес root-project.
-- Повні запуски та запуски shard extension оновлюють локальні дані часу в `.artifacts/vitest-shard-timings.json`; наступні запуски використовують ці дані, щоб балансувати повільні й швидкі shard. Встановіть `OPENCLAW_TEST_PROJECTS_TIMINGS=0`, щоб ігнорувати локальний артефакт часу.
-- Вибрані тестові файли `plugin-sdk` і `commands` тепер маршрутизуються через окремі легкі lane, які залишають лише `test/setup.ts`, а важкі з погляду runtime випадки залишаються на наявних lane.
-- Вибрані допоміжні файли вихідного коду `plugin-sdk` і `commands` також зіставляють `pnpm test:changed` з явними сусідніми тестами в цих легких lane, тож невеликі зміни в helper не спричиняють повторний запуск важких наборів, що спираються на runtime.
-- `auto-reply` тепер також розділено на три окремі конфігурації (`core`, `top-level`, `reply`), щоб harness reply не домінував над легшими top-level тестами status/token/helper.
-- Базова конфігурація Vitest тепер типово використовує `pool: "threads"` і `isolate: false`, а спільний неізольований runner увімкнено в конфігураціях усього репозиторію.
+- `pnpm test:force`: Завершує всі завислі процеси gateway, які утримують стандартний порт керування, а потім запускає повний набір Vitest з ізольованим портом gateway, щоб серверні тести не конфліктували із запущеним екземпляром. Використовуйте це, коли попередній запуск gateway залишив зайнятим порт 18789.
+- `pnpm test:coverage`: Запускає набір unit-тестів із V8 coverage (через `vitest.unit.config.ts`). Це поріг unit coverage для завантажених файлів, а не coverage всіх файлів у всьому репозиторії. Порогові значення: 70% для lines/functions/statements і 55% для branches. Оскільки `coverage.all` має значення false, перевірка оцінює файли, завантажені набором unit coverage, замість того щоб вважати всі файли вихідного коду в розділених lane непокритими.
+- `pnpm test:coverage:changed`: Запускає unit coverage лише для файлів, змінених відносно `origin/main`.
+- `pnpm test:changed`: розгортає змінені git-шляхи в scoped Vitest lanes, коли diff зачіпає лише routable файли вихідного коду/тестів. Зміни конфігурації/налаштування все одно повертаються до нативного запуску root projects, щоб за потреби зміни wiring перезапускали ширший набір.
+- `pnpm changed:lanes`: показує архітектурні lanes, які запускаються для diff відносно `origin/main`.
+- `pnpm check:changed`: запускає розумну перевірку changed gate для diff відносно `origin/main`. Вона запускає core-роботу разом із core test lanes, роботу extensions — разом із extension test lanes, зміни лише в тестах — тільки з перевіркою типів тестів/самими тестами, розширює зміни публічного Plugin SDK або plugin-contract до валідації extensions і залишає підвищення версій лише в release metadata на цільових перевірках version/config/root-dependency.
+- `pnpm test`: маршрутизує явні цілі файлів/каталогів через scoped Vitest lanes. Запуски без явної цілі використовують фіксовані shard groups і розгортаються до leaf configs для локального паралельного виконання; група extensions завжди розгортається до per-extension shard configs, а не до одного великого процесу root-project.
+- Повні запуски та запуски extension shard оновлюють локальні дані таймінгів у `.artifacts/vitest-shard-timings.json`; наступні запуски використовують ці таймінги, щоб балансувати повільні й швидкі shards. Установіть `OPENCLAW_TEST_PROJECTS_TIMINGS=0`, щоб ігнорувати локальний артефакт таймінгів.
+- Вибрані тестові файли `plugin-sdk` і `commands` тепер маршрутизуються через окремі легкі lanes, які залишають лише `test/setup.ts`, а ресурсоємні runtime-випадки — у їхніх наявних lanes.
+- Вибрані вихідні helper-файли `plugin-sdk` і `commands` також зіставляють `pnpm test:changed` з явними сусідніми тестами в цих легких lanes, тож невеликі зміни helper-файлів не змушують повторно запускати важкі набори з runtime.
+- `auto-reply` тепер також розділяється на три окремі конфігурації (`core`, `top-level`, `reply`), щоб harness для reply не домінував над легшими тестами top-level для status/token/helper.
+- Базова конфігурація Vitest тепер за замовчуванням використовує `pool: "threads"` і `isolate: false`, а спільний неізольований runner увімкнено в усіх конфігураціях репозиторію.
- `pnpm test:channels` запускає `vitest.channels.config.ts`.
-- `pnpm test:extensions` і `pnpm test extensions` запускають усі shard extension/plugin. Важкі channel extension і OpenAI запускаються як окремі shard; інші групи extension залишаються згрупованими. Використовуйте `pnpm test extensions/` для одного lane bundled plugin.
-- `pnpm test:perf:imports`: вмикає звітність Vitest щодо тривалості імпорту та розбивки імпортів, водночас і надалі використовуючи scoped lane routing для явних цілей файлів/каталогів.
+- `pnpm test:extensions` і `pnpm test extensions` запускають усі shards extensions/plugins. Важкі channel extensions і OpenAI виконуються як окремі shards; інші групи extensions залишаються згрупованими. Використовуйте `pnpm test extensions/` для одного lane bundled plugin.
+- `pnpm test:perf:imports`: вмикає звіти Vitest про тривалість імпорту та деталізацію імпорту, водночас зберігаючи маршрутизацію через scoped lanes для явних цілей файлів/каталогів.
- `pnpm test:perf:imports:changed`: те саме профілювання імпорту, але лише для файлів, змінених відносно `origin/main`.
-- `pnpm test:perf:changed:bench -- --ref ` вимірює продуктивність маршрутизованого шляху changed-mode порівняно з нативним запуском root-project для того самого закоміченого git diff.
-- `pnpm test:perf:changed:bench -- --worktree` вимірює продуктивність поточного набору змін у worktree без попереднього коміту.
+- `pnpm test:perf:changed:bench -- --ref ` порівнює продуктивність маршрутизованого шляху changed-mode з нативним запуском root-project для того самого зафіксованого git diff.
+- `pnpm test:perf:changed:bench -- --worktree` порівнює поточний набір змін у worktree без попереднього коміту.
- `pnpm test:perf:profile:main`: записує CPU-профіль для головного потоку Vitest (`.artifacts/vitest-main-profile`).
- `pnpm test:perf:profile:runner`: записує профілі CPU + heap для unit runner (`.artifacts/vitest-runner-profile`).
-- Інтеграція Gateway: увімкнення через `OPENCLAW_TEST_INCLUDE_GATEWAY=1 pnpm test` або `pnpm test:gateway`.
-- `pnpm test:e2e`: Запускає наскрізні smoke-тести gateway (pairing кількох екземплярів WS/HTTP/node). Типово використовує `threads` + `isolate: false` з адаптивною кількістю worker у `vitest.e2e.config.ts`; налаштовується через `OPENCLAW_E2E_WORKERS=`, а для докладних журналів встановіть `OPENCLAW_E2E_VERBOSE=1`.
-- `pnpm test:live`: Запускає live-тести provider (minimax/zai). Потрібні API-ключі та `LIVE=1` (або специфічний для provider `*_LIVE_TEST=1`) для зняття пропуску.
-- `pnpm test:docker:all`: Один раз збирає спільний образ live-test і образ Docker E2E, а потім запускає Docker smoke lane з `OPENCLAW_SKIP_DOCKER_BUILD=1` із типовим паралелізмом 4. Налаштовується через `OPENCLAW_DOCKER_ALL_PARALLELISM=`. Runner припиняє планувати нові lane у пулі після першої помилки, якщо не встановлено `OPENCLAW_DOCKER_ALL_FAIL_FAST=0`, а кожен lane має тайм-аут 120 хвилин, який можна перевизначити через `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS`. Lane, чутливі до запуску або provider, виконуються ексклюзивно після паралельного пулу. Журнали для кожного lane записуються в `.artifacts/docker-tests//`.
-- `pnpm test:docker:openwebui`: Запускає Dockerized OpenClaw + Open WebUI, виконує вхід через Open WebUI, перевіряє `/api/models`, а потім запускає реальний проксійований чат через `/api/chat/completions`. Потребує придатного ключа live model (наприклад, OpenAI у `~/.profile`), завантажує зовнішній образ Open WebUI і не очікується настільки стабільним у CI, як звичайні набори unit/e2e.
-- `pnpm test:docker:mcp-channels`: Запускає контейнер Gateway із підготовленими даними та другий контейнер-клієнт, який запускає `openclaw mcp serve`, а потім перевіряє пошук маршрутизованих розмов, читання транскриптів, метадані вкладень, поведінку live-черги подій, маршрутизацію вихідного надсилання та сповіщення про channel + permissions у стилі Claude через реальний міст stdio. Перевірка сповіщення Claude читає сирі stdio MCP-кадри напряму, щоб smoke відображав те, що міст фактично надсилає.
+- `pnpm test:perf:groups --full-suite --allow-failures --output .artifacts/test-perf/baseline-before.json`: послідовно запускає кожну leaf-конфігурацію Vitest для повного набору й записує згруповані дані про тривалість разом з JSON/лог-артефактами для кожної конфігурації. Агент Test Performance використовує це як базову лінію перед спробою виправити повільні тести.
+- `pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifacts/test-perf/after-agent.json`: порівнює згруповані звіти після змін, спрямованих на продуктивність.
+- Інтеграція Gateway: вмикається через `OPENCLAW_TEST_INCLUDE_GATEWAY=1 pnpm test` або `pnpm test:gateway`.
+- `pnpm test:e2e`: запускає наскрізні smoke-тести gateway (парування кількох екземплярів WS/HTTP/node). За замовчуванням використовує `threads` + `isolate: false` з адаптивною кількістю workers у `vitest.e2e.config.ts`; налаштовується через `OPENCLAW_E2E_WORKERS=`, а для докладних логів установіть `OPENCLAW_E2E_VERBOSE=1`.
+- `pnpm test:live`: запускає live-тести провайдерів (minimax/zai). Потрібні API-ключі та `LIVE=1` (або провайдер-специфічний `*_LIVE_TEST=1`), щоб зняти skip.
+- `pnpm test:docker:all`: один раз збирає спільний образ live-test і образ Docker E2E, а потім запускає Docker smoke lanes з `OPENCLAW_SKIP_DOCKER_BUILD=1` і типовим рівнем паралелізму 4. Налаштовується через `OPENCLAW_DOCKER_ALL_PARALLELISM=`. Runner припиняє планувати нові lanes у пулі після першої помилки, якщо не встановлено `OPENCLAW_DOCKER_ALL_FAIL_FAST=0`, а кожен lane має тайм-аут 120 хвилин, який можна змінити через `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS`. Lanes, чутливі до запуску або провайдера, виконуються ексклюзивно після паралельного пулу. Логи для кожного lane записуються в `.artifacts/docker-tests//`.
+- `pnpm test:docker:openwebui`: запускає Dockerized OpenClaw + Open WebUI, входить через Open WebUI, перевіряє `/api/models`, а потім запускає реальний проксійований чат через `/api/chat/completions`. Потребує придатного ключа live-моделі (наприклад, OpenAI у `~/.profile`), завантажує зовнішній образ Open WebUI і не вважається стабільним для CI так, як звичайні набори unit/e2e.
+- `pnpm test:docker:mcp-channels`: запускає контейнер Gateway із підготовленими даними та другий клієнтський контейнер, який запускає `openclaw mcp serve`, а потім перевіряє виявлення маршрутизованих розмов, читання transcript, метадані вкладень, поведінку черги live events, маршрутизацію вихідного надсилання, а також channel- і permission-сповіщення в стилі Claude через реальний міст stdio. Перевірка сповіщень Claude читає сирі stdio MCP-кадри безпосередньо, щоб smoke-тест відображав те, що міст насправді надсилає.
-## Локальна перевірка PR
+## Локальна PR-перевірка
-Для локальних перевірок перед злиттям/проходженням PR запустіть:
+Для локальних перевірок перед злиттям PR запускайте:
- `pnpm check:changed`
- `pnpm check`
@@ -54,12 +56,12 @@ x-i18n:
- `pnpm test`
- `pnpm check:docs`
-Якщо `pnpm test` дає flaky-результат на завантаженому хості, перезапустіть один раз, перш ніж вважати це регресією, а потім ізолюйте через `pnpm test `. Для хостів з обмеженою пам’яттю використовуйте:
+Якщо `pnpm test` флейкає на навантаженому хості, перезапустіть один раз, перш ніж вважати це регресією, а потім ізолюйте через `pnpm test `. Для хостів з обмеженою пам’яттю використовуйте:
- `OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test`
- `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/tmp/openclaw-vitest-cache pnpm test:changed`
-## Бенч затримки моделі (локальні ключі)
+## Бенчмарк затримки моделі (локальні ключі)
Скрипт: [`scripts/bench-model.ts`](https://github.com/openclaw/openclaw/blob/main/scripts/bench-model.ts)
@@ -67,14 +69,14 @@ x-i18n:
- `source ~/.profile && pnpm tsx scripts/bench-model.ts --runs 10`
- Необов’язкові змінні середовища: `MINIMAX_API_KEY`, `MINIMAX_BASE_URL`, `MINIMAX_MODEL`, `ANTHROPIC_API_KEY`
-- Типовий prompt: “Відповідай одним словом: ok. Без розділових знаків або додаткового тексту.”
+- Типовий prompt: “Reply with a single word: ok. No punctuation or extra text.”
Останній запуск (2025-12-31, 20 прогонів):
- minimax median 1279ms (min 1114, max 2431)
- opus median 2454ms (min 1224, max 3170)
-## Бенч запуску CLI
+## Бенчмарк запуску CLI
Скрипт: [`scripts/bench-cli-startup.ts`](https://github.com/openclaw/openclaw/blob/main/scripts/bench-cli-startup.ts)
@@ -95,41 +97,41 @@ x-i18n:
- `pnpm tsx scripts/bench-cli-startup.ts --preset real --cpu-prof-dir .artifacts/cli-cpu`
- `pnpm tsx scripts/bench-cli-startup.ts --json`
-Набори preset:
+Presets:
- `startup`: `--version`, `--help`, `health`, `health --json`, `status --json`, `status`
- `real`: `health`, `status`, `status --json`, `sessions`, `sessions --json`, `agents list --json`, `gateway status`, `gateway status --json`, `gateway health --json`, `config get gateway.port`
-- `all`: обидва набори preset
+- `all`: обидва presets
-Вивід містить `sampleCount`, avg, p50, p95, min/max, розподіл exit-code/signal і зведення max RSS для кожної команди. Необов’язкові `--cpu-prof-dir` / `--heap-prof-dir` записують профілі V8 для кожного прогону, щоб вимірювання часу та збір профілів використовували один і той самий harness.
+Вивід містить `sampleCount`, avg, p50, p95, min/max, розподіл exit-code/signal і підсумки max RSS для кожної команди. Необов’язкові `--cpu-prof-dir` / `--heap-prof-dir` записують профілі V8 для кожного прогону, тож вимірювання часу та збирання профілів використовують один і той самий harness.
-Угоди щодо збереженого виводу:
+Узгоджені правила для збереженого виводу:
- `pnpm test:startup:bench:smoke` записує цільовий smoke-артефакт у `.artifacts/cli-startup-bench-smoke.json`
-- `pnpm test:startup:bench:save` записує артефакт повного набору в `.artifacts/cli-startup-bench-all.json`, використовуючи `runs=5` і `warmup=1`
-- `pnpm test:startup:bench:update` оновлює закомічений baseline fixture у `test/fixtures/cli-startup-bench.json`, використовуючи `runs=5` і `warmup=1`
+- `pnpm test:startup:bench:save` записує артефакт повного набору в `.artifacts/cli-startup-bench-all.json` з `runs=5` і `warmup=1`
+- `pnpm test:startup:bench:update` оновлює зафіксований у репозиторії baseline fixture у `test/fixtures/cli-startup-bench.json` з `runs=5` і `warmup=1`
-Закомічений fixture:
+Зафіксований fixture у репозиторії:
- `test/fixtures/cli-startup-bench.json`
-- Оновити через `pnpm test:startup:bench:update`
-- Порівняти поточні результати з fixture через `pnpm test:startup:bench:check`
+- Оновлення: `pnpm test:startup:bench:update`
+- Порівняння поточних результатів із fixture: `pnpm test:startup:bench:check`
-## Onboarding E2E (Docker)
+## Наскрізне тестування онбордингу (Docker)
-Docker необов’язковий; це потрібно лише для containerized smoke-тестів onboarding.
+Docker необов’язковий; це потрібно лише для containerized smoke-тестів онбордингу.
-Повний cold-start потік у чистому Linux-контейнері:
+Повний cold-start сценарій у чистому Linux-контейнері:
```bash
scripts/e2e/onboard-docker.sh
```
-Цей скрипт проводить interactive wizard через pseudo-tty, перевіряє файли config/workspace/session, потім запускає gateway і виконує `openclaw health`.
+Цей скрипт проходить інтерактивний майстер через pseudo-tty, перевіряє файли config/workspace/session, потім запускає gateway і виконує `openclaw health`.
## Smoke-тест імпорту QR (Docker)
-Гарантує, що `qrcode-terminal` завантажується в підтримуваних runtime Node у Docker (типово Node 24, сумісний Node 22):
+Гарантує, що `qrcode-terminal` завантажується в підтримуваних середовищах виконання Docker Node (типово Node 24, сумісний Node 22):
```bash
pnpm test:docker:qr