From d3cf7bd9d9b9624d475ee647aae48235f853d513 Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Thu, 23 Apr 2026 19:53:30 +0000 Subject: [PATCH] chore(i18n): refresh uk translations --- docs/uk/channels/telegram.md | 540 ++++++++-------- docs/uk/ci.md | 145 +++-- docs/uk/help/testing.md | 1133 +++++++++++++++++----------------- docs/uk/reference/test.md | 94 +-- 4 files changed, 945 insertions(+), 967 deletions(-) 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