diff --git a/docs/uk/channels/feishu.md b/docs/uk/channels/feishu.md index 39cfbf4f8..71ba047d9 100644 --- a/docs/uk/channels/feishu.md +++ b/docs/uk/channels/feishu.md @@ -2,29 +2,29 @@ read_when: - Ви хочете підключити бота Feishu/Lark - Ви налаштовуєте канал Feishu -summary: Огляд бота Feishu, функції та конфігурація +summary: Огляд, можливості та конфігурація бота Feishu title: Feishu x-i18n: - generated_at: "2026-04-27T22:37:52Z" - model: gpt-5.4 + generated_at: "2026-04-29T05:57:05Z" + model: gpt-5.5 provider: openai - source_hash: 54db77a6bb05d862fe8eb5dfc97d04e4252b20e2b0ccbf204eb49d9d7256b026 + source_hash: 37de7cbb12821f119ca1a06fcdb8e80a07752e1cbfc462344d24750fbf13147a source_path: channels/feishu.md - workflow: 15 + workflow: 16 --- # Feishu / Lark -Feishu/Lark — це універсальна платформа для співпраці, де команди спілкуються в чаті, діляться документами, керують календарями та разом виконують роботу. +Feishu/Lark — це універсальна платформа для спільної роботи, де команди спілкуються, діляться документами, керують календарями та працюють разом. -**Статус:** готово до використання у продакшені для особистих повідомлень боту та групових чатів. Режим WebSocket використовується за замовчуванням; режим webhook є необов’язковим. +**Статус:** готово до production для приватних повідомлень ботам і групових чатів. WebSocket є типовим режимом; режим Webhook необов’язковий. --- ## Швидкий старт -Потрібен OpenClaw 2026.4.25 або новіший. Щоб перевірити, виконайте `openclaw --version`. Щоб оновити, виконайте `openclaw update`. +Потрібен OpenClaw 2026.4.25 або новіший. Виконайте `openclaw --version`, щоб перевірити. Оновіться за допомогою `openclaw update`. @@ -32,10 +32,10 @@ Feishu/Lark — це універсальна платформа для спів ```bash openclaw channels login --channel feishu ``` - Відскануйте QR-код у мобільному застосунку Feishu/Lark, щоб автоматично створити бота Feishu/Lark. + Проскануйте QR-код мобільним застосунком Feishu/Lark, щоб автоматично створити бота Feishu/Lark. - + ```bash openclaw gateway restart ``` @@ -44,18 +44,18 @@ Feishu/Lark — це універсальна платформа для спів --- -## Керування доступом +## Контроль доступу -### Особисті повідомлення +### Приватні повідомлення -Налаштуйте `dmPolicy`, щоб керувати тим, хто може писати боту в особисті повідомлення: +Налаштуйте `dmPolicy`, щоб керувати тим, хто може надсилати приватні повідомлення боту: -- `"pairing"` — невідомі користувачі отримують код прив’язки; схваліть його через CLI +- `"pairing"` — невідомі користувачі отримують код сполучення; підтвердіть через CLI - `"allowlist"` — спілкуватися можуть лише користувачі, перелічені в `allowFrom` (типово: лише власник бота) -- `"open"` — дозволити всіх користувачів -- `"disabled"` — вимкнути всі особисті повідомлення +- `"open"` — дозволити публічні приватні повідомлення лише коли `allowFrom` містить `"*"`; з обмежувальними записами спілкуватися можуть лише відповідні користувачі +- `"disabled"` — вимкнути всі приватні повідомлення -**Схвалити запит на прив’язку:** +**Підтвердити запит на сполучення:** ```bash openclaw pairing list feishu @@ -66,26 +66,26 @@ openclaw pairing approve feishu **Політика груп** (`channels.feishu.groupPolicy`): -| Значення | Поведінка | -| ------------- | ------------------------------------------------------------------------------------------- | -| `"open"` | Відповідати на всі повідомлення в групах | -| `"allowlist"` | Відповідати лише в групах із `groupAllowFrom` або явно налаштованих у `groups.` | -| `"disabled"` | Вимкнути всі повідомлення в групах; явні записи `groups.` не перевизначають це | +| Значення | Поведінка | +| ------------- | ------------------------------------------------------------------------------------------------ | +| `"open"` | Відповідати на всі повідомлення в групах | +| `"allowlist"` | Відповідати лише групам у `groupAllowFrom` або явно налаштованим у `groups.` | +| `"disabled"` | Вимкнути всі групові повідомлення; явні записи `groups.` не перевизначають це | -Типове значення: `allowlist` +Типово: `allowlist` **Вимога згадки** (`channels.feishu.requireMention`): -- `true` — вимагати @mention (типово) -- `false` — відповідати без @mention +- `true` — вимагати @згадку (типово) +- `false` — відповідати без @згадки - Перевизначення для окремої групи: `channels.feishu.groups..requireMention` -- Згадки лише для розсилки `@all` і `@_all` не вважаються згадками бота. Повідомлення, яке містить і `@all`, і пряму згадку бота, усе одно вважається згадкою бота. +- Трансляційні лише `@all` і `@_all` не вважаються згадками бота. Повідомлення, яке згадує і `@all`, і бота напряму, усе одно зараховується як згадка бота. --- ## Приклади конфігурації груп -### Дозволити всі групи, без обов’язкової @mention +### Дозволити всі групи, без вимоги @згадки ```json5 { @@ -97,7 +97,7 @@ openclaw pairing approve feishu } ``` -### Дозволити всі групи, але все одно вимагати @mention +### Дозволити всі групи, але все ще вимагати @згадку ```json5 { @@ -117,14 +117,14 @@ openclaw pairing approve feishu channels: { feishu: { groupPolicy: "allowlist", - // Ідентифікатори груп мають вигляд: oc_xxx + // Group IDs look like: oc_xxx groupAllowFrom: ["oc_xxx", "oc_yyy"], }, }, } ``` -У режимі `allowlist` ви також можете дозволити групу, додавши явний запис `groups.`. Явні записи не перевизначають `groupPolicy: "disabled"`. Шаблонні значення за замовчуванням у `groups.*` налаштовують відповідні групи, але самі по собі не надають групам доступ. +У режимі `allowlist` ви також можете допустити групу, додавши явний запис `groups.`. Явні записи не перевизначають `groupPolicy: "disabled"`. Типові значення з wildcard у `groups.*` налаштовують відповідні групи, але самі по собі не допускають групи. ```json5 { @@ -141,7 +141,7 @@ openclaw pairing approve feishu } ``` -### Обмежити відправників усередині групи +### Обмежити відправників у групі ```json5 { @@ -151,7 +151,7 @@ openclaw pairing approve feishu groupAllowFrom: ["oc_xxx"], groups: { oc_xxx: { - // open_id користувачів мають вигляд: ou_xxx + // User open_ids look like: ou_xxx allowFrom: ["ou_user1", "ou_user2"], }, }, @@ -164,23 +164,23 @@ openclaw pairing approve feishu -## Отримання ідентифікаторів груп/користувачів +## Отримати ідентифікатори груп/користувачів ### Ідентифікатори груп (`chat_id`, формат: `oc_xxx`) -Відкрийте групу у Feishu/Lark, натисніть значок меню у верхньому правому куті та перейдіть до **Налаштувань**. Ідентифікатор групи (`chat_id`) вказано на сторінці налаштувань. +Відкрийте групу у Feishu/Lark, натисніть іконку меню у верхньому правому куті та перейдіть до **Налаштувань**. Ідентифікатор групи (`chat_id`) зазначено на сторінці налаштувань. -![Get Group ID](/images/feishu-get-group-id.png) +![Отримати ідентифікатор групи](/images/feishu-get-group-id.png) ### Ідентифікатори користувачів (`open_id`, формат: `ou_xxx`) -Запустіть Gateway, надішліть боту особисте повідомлення, а потім перевірте журнали: +Запустіть gateway, надішліть приватне повідомлення боту, потім перевірте журнали: ```bash openclaw logs --follow ``` -Знайдіть `open_id` у виведенні журналів. Ви також можете перевірити незавершені запити на прив’язку: +Шукайте `open_id` у виводі журналу. Також можна перевірити запити на сполучення, що очікують: ```bash openclaw pairing list feishu @@ -190,14 +190,14 @@ openclaw pairing list feishu ## Поширені команди -| Команда | Опис | -| --------- | ----------------------------- | -| `/status` | Показати стан бота | -| `/reset` | Скинути поточну сесію | -| `/model` | Показати або змінити AI-модель | +| Команда | Опис | +| --------- | ---------------------------- | +| `/status` | Показати статус бота | +| `/reset` | Скинути поточний сеанс | +| `/model` | Показати або змінити модель ШІ | -Feishu/Lark не підтримує вбудовані меню slash-команд, тому надсилайте їх як звичайні текстові повідомлення. +Feishu/Lark не підтримує нативні меню slash-команд, тому надсилайте їх як звичайні текстові повідомлення. --- @@ -207,24 +207,24 @@ Feishu/Lark не підтримує вбудовані меню slash-коман ### Бот не відповідає в групових чатах 1. Переконайтеся, що бота додано до групи -2. Переконайтеся, що ви згадали бота через @mention (це потрібно за замовчуванням) -3. Переконайтеся, що `groupPolicy` не має значення `"disabled"` +2. Переконайтеся, що ви @згадали бота (це потрібно типово) +3. Перевірте, що `groupPolicy` не є `"disabled"` 4. Перевірте журнали: `openclaw logs --follow` ### Бот не отримує повідомлення -1. Переконайтеся, що бота опубліковано та схвалено в Feishu Open Platform / Lark Developer +1. Переконайтеся, що бота опубліковано й схвалено у Feishu Open Platform / Lark Developer 2. Переконайтеся, що підписка на події містить `im.message.receive_v1` -3. Переконайтеся, що вибрано **persistent connection** (WebSocket) +3. Переконайтеся, що вибрано **постійне підключення** (WebSocket) 4. Переконайтеся, що надано всі потрібні області дозволів -5. Переконайтеся, що Gateway запущено: `openclaw gateway status` +5. Переконайтеся, що gateway працює: `openclaw gateway status` 6. Перевірте журнали: `openclaw logs --follow` -### Витік App Secret +### App Secret витік 1. Скиньте App Secret у Feishu Open Platform / Lark Developer 2. Оновіть значення у своїй конфігурації -3. Перезапустіть Gateway: `openclaw gateway restart` +3. Перезапустіть gateway: `openclaw gateway restart` --- @@ -241,7 +241,7 @@ Feishu/Lark не підтримує вбудовані меню slash-коман main: { appId: "cli_xxx", appSecret: "xxx", - name: "Основний бот", + name: "Primary bot", tts: { providers: { openai: { voice: "shimmer" }, @@ -251,7 +251,7 @@ Feishu/Lark не підтримує вбудовані меню slash-коман backup: { appId: "cli_yyy", appSecret: "yyy", - name: "Резервний бот", + name: "Backup bot", enabled: false, }, }, @@ -260,40 +260,40 @@ Feishu/Lark не підтримує вбудовані меню slash-коман } ``` -`defaultAccount` визначає, який обліковий запис використовується, коли вихідні API не вказують `accountId`. -`accounts..tts` використовує ту саму структуру, що й `messages.tts`, і виконує глибоке злиття поверх -глобальної конфігурації TTS, тож у багатоботних конфігураціях Feishu можна -зберігати спільні облікові дані провайдерів глобально, перевизначаючи лише voice, model, persona або auto mode +`defaultAccount` керує тим, який обліковий запис використовується, коли вихідні API не вказують `accountId`. +`accounts..tts` використовує ту саму форму, що й `messages.tts`, і виконує глибоке злиття поверх +глобальної конфігурації TTS, тому налаштування Feishu з кількома ботами можуть зберігати спільні облікові дані +провайдера глобально, перевизначаючи лише голос, модель, персону або автоматичний режим для кожного облікового запису. ### Обмеження повідомлень - `textChunkLimit` — розмір фрагмента вихідного тексту (типово: `2000` символів) -- `mediaMaxMb` — обмеження на вивантаження/завантаження медіа (типово: `30` МБ) +- `mediaMaxMb` — ліміт завантаження/вивантаження медіа (типово: `30` МБ) -### Потокова передача +### Потокове передавання -Feishu/Lark підтримує потокові відповіді через інтерактивні картки. Якщо ввімкнено, бот оновлює картку в реальному часі під час генерування тексту. +Feishu/Lark підтримує потокові відповіді через інтерактивні картки. Коли це ввімкнено, бот оновлює картку в реальному часі під час генерування тексту. ```json5 { channels: { feishu: { - streaming: true, // увімкнути потоковий вивід у картках (типово: true) - blockStreaming: true, // увімкнути потокову передачу на рівні блоків (типово: true) + streaming: true, // enable streaming card output (default: true) + blockStreaming: true, // enable block-level streaming (default: true) }, }, } ``` -Установіть `streaming: false`, щоб надсилати повну відповідь одним повідомленням. +Установіть `streaming: false`, щоб надіслати повну відповідь одним повідомленням. -### Оптимізація квот +### Оптимізація квоти Зменште кількість викликів API Feishu/Lark за допомогою двох необов’язкових прапорців: -- `typingIndicator` (типово `true`): установіть `false`, щоб пропускати виклики реакції друку -- `resolveSenderNames` (типово `true`): установіть `false`, щоб пропускати пошук профілів відправників +- `typingIndicator` (типово `true`): установіть `false`, щоб пропустити виклики реакції набору тексту +- `resolveSenderNames` (типово `true`): установіть `false`, щоб пропустити пошуки профілів відправників ```json5 { @@ -306,11 +306,11 @@ Feishu/Lark підтримує потокові відповіді через і } ``` -### Сесії ACP +### Сеанси ACP -Feishu/Lark підтримує ACP для особистих повідомлень і повідомлень у потоках груп. ACP у Feishu/Lark керується текстовими командами — вбудованих меню slash-команд немає, тому використовуйте повідомлення `/acp ...` безпосередньо в розмові. +Feishu/Lark підтримує ACP для приватних повідомлень і повідомлень у групових тредах. ACP у Feishu/Lark керується текстовими командами — нативних меню slash-команд немає, тому використовуйте повідомлення `/acp ...` безпосередньо в розмові. -#### Постійна прив’язка ACP +#### Постійне прив’язування ACP ```json5 { @@ -356,17 +356,17 @@ Feishu/Lark підтримує ACP для особистих повідомле #### Запуск ACP із чату -У особистому повідомленні Feishu/Lark або в потоці: +У приватному повідомленні або треді Feishu/Lark: ```text /acp spawn codex --thread here ``` -`--thread here` працює для особистих повідомлень і повідомлень у потоках Feishu/Lark. Подальші повідомлення в прив’язаній розмові спрямовуються безпосередньо до цієї сесії ACP. +`--thread here` працює для приватних повідомлень і повідомлень у тредах Feishu/Lark. Подальші повідомлення у прив’язаній розмові спрямовуються безпосередньо до цього сеансу ACP. -### Маршрутизація між кількома агентами +### Маршрутизація кількох агентів -Використовуйте `bindings`, щоб спрямовувати особисті повідомлення або групи Feishu/Lark до різних агентів. +Використовуйте `bindings`, щоб спрямовувати приватні повідомлення або групи Feishu/Lark до різних агентів. ```json5 { @@ -399,10 +399,10 @@ Feishu/Lark підтримує ACP для особистих повідомле Поля маршрутизації: - `match.channel`: `"feishu"` -- `match.peer.kind`: `"direct"` (особисте повідомлення) або `"group"` (груповий чат) +- `match.peer.kind`: `"direct"` (приватне повідомлення) або `"group"` (груповий чат) - `match.peer.id`: Open ID користувача (`ou_xxx`) або ідентифікатор групи (`oc_xxx`) -Див. [Отримання ідентифікаторів груп/користувачів](#get-groupuser-ids), щоб дізнатися, як їх знайти. +Див. [Отримати ідентифікатори груп/користувачів](#get-groupuser-ids), щоб отримати поради щодо пошуку. --- @@ -410,34 +410,34 @@ Feishu/Lark підтримує ACP для особистих повідомле Повна конфігурація: [Конфігурація Gateway](/uk/gateway/configuration) -| Налаштування | Опис | Типове значення | -| ------------------------------------------------- | ------------------------------------------------------------------------------------ | --------------- | -| `channels.feishu.enabled` | Увімкнути/вимкнути канал | `true` | -| `channels.feishu.domain` | Домен API (`feishu` або `lark`) | `feishu` | -| `channels.feishu.connectionMode` | Транспорт подій (`websocket` або `webhook`) | `websocket` | -| `channels.feishu.defaultAccount` | Типовий обліковий запис для вихідної маршрутизації | `default` | -| `channels.feishu.verificationToken` | Потрібен для режиму webhook | — | -| `channels.feishu.encryptKey` | Потрібен для режиму webhook | — | -| `channels.feishu.webhookPath` | Шлях маршруту webhook | `/feishu/events` | -| `channels.feishu.webhookHost` | Хост прив’язки webhook | `127.0.0.1` | -| `channels.feishu.webhookPort` | Порт прив’язки webhook | `3000` | -| `channels.feishu.accounts..appId` | App ID | — | -| `channels.feishu.accounts..appSecret` | App Secret | — | -| `channels.feishu.accounts..domain` | Перевизначення домену для окремого облікового запису | `feishu` | -| `channels.feishu.accounts..tts` | Перевизначення TTS для окремого облікового запису | `messages.tts` | -| `channels.feishu.dmPolicy` | Політика особистих повідомлень | `allowlist` | -| `channels.feishu.allowFrom` | Список дозволених для особистих повідомлень (`open_id`) | [BotOwnerId] | -| `channels.feishu.groupPolicy` | Політика груп | `allowlist` | -| `channels.feishu.groupAllowFrom` | Список дозволених груп | — | -| `channels.feishu.requireMention` | Вимагати @mention у групах | `true` | -| `channels.feishu.groups..requireMention` | Перевизначення @mention для окремої групи; явні ID також дозволяють групу в режимі allowlist | inherited | -| `channels.feishu.groups..enabled` | Увімкнути/вимкнути конкретну групу | `true` | -| `channels.feishu.textChunkLimit` | Розмір фрагмента повідомлення | `2000` | -| `channels.feishu.mediaMaxMb` | Обмеження розміру медіа | `30` | -| `channels.feishu.streaming` | Потоковий вивід у картках | `true` | -| `channels.feishu.blockStreaming` | Потокова передача на рівні блоків | `true` | -| `channels.feishu.typingIndicator` | Надсилати реакції набору тексту | `true` | -| `channels.feishu.resolveSenderNames` | Визначати відображувані імена відправників | `true` | +| Налаштування | Опис | Типово | +| ------------------------------------------------- | --------------------------------------------------------------------------------------------- | ---------------- | +| `channels.feishu.enabled` | Увімкнути/вимкнути канал | `true` | +| `channels.feishu.domain` | Домен API (`feishu` або `lark`) | `feishu` | +| `channels.feishu.connectionMode` | Транспорт подій (`websocket` або `webhook`) | `websocket` | +| `channels.feishu.defaultAccount` | Обліковий запис за замовчуванням для вихідної маршрутизації | `default` | +| `channels.feishu.verificationToken` | Потрібно для режиму webhook | — | +| `channels.feishu.encryptKey` | Потрібно для режиму webhook | — | +| `channels.feishu.webhookPath` | Шлях маршруту webhook | `/feishu/events` | +| `channels.feishu.webhookHost` | Хост прив’язки webhook | `127.0.0.1` | +| `channels.feishu.webhookPort` | Порт прив’язки webhook | `3000` | +| `channels.feishu.accounts..appId` | ID застосунку | — | +| `channels.feishu.accounts..appSecret` | Секрет застосунку | — | +| `channels.feishu.accounts..domain` | Перевизначення домену для окремого облікового запису | `feishu` | +| `channels.feishu.accounts..tts` | Перевизначення TTS для окремого облікового запису | `messages.tts` | +| `channels.feishu.dmPolicy` | Політика DM | `allowlist` | +| `channels.feishu.allowFrom` | Список дозволених DM (список open_id) | [BotOwnerId] | +| `channels.feishu.groupPolicy` | Політика груп | `allowlist` | +| `channels.feishu.groupAllowFrom` | Список дозволених груп | — | +| `channels.feishu.requireMention` | Вимагати @mention у групах | `true` | +| `channels.feishu.groups..requireMention` | Перевизначення @mention для окремої групи; явні ID також допускають групу в режимі allowlist | успадковано | +| `channels.feishu.groups..enabled` | Увімкнути/вимкнути конкретну групу | `true` | +| `channels.feishu.textChunkLimit` | Розмір фрагмента повідомлення | `2000` | +| `channels.feishu.mediaMaxMb` | Обмеження розміру медіа | `30` | +| `channels.feishu.streaming` | Потокове виведення карток | `true` | +| `channels.feishu.blockStreaming` | Потокове передавання на рівні блоків | `true` | +| `channels.feishu.typingIndicator` | Надсилати реакції набору тексту | `true` | +| `channels.feishu.resolveSenderNames` | Визначати відображувані імена відправників | `true` | --- @@ -453,13 +453,14 @@ Feishu/Lark підтримує ACP для особистих повідомле - ✅ Відео/медіа - ✅ Стікери -Вхідні аудіоповідомлення Feishu/Lark нормалізуються як заповнювачі медіа замість -необробленого JSON `file_key`. Якщо налаштовано `tools.media.audio`, OpenClaw -завантажує ресурс голосового повідомлення та виконує спільну транскрипцію аудіо перед -ходом агента, щоб агент отримав транскрибований мовний текст. Якщо Feishu вже містить -текст транскрипції безпосередньо в аудіокорисному навантаженні, цей текст використовується без -додаткового виклику ASR. Без провайдера транскрипції аудіо агент усе одно отримує -заповнювач `` разом зі збереженим вкладенням, а не необроблене корисне навантаження ресурсу Feishu. +Вхідні аудіоповідомлення Feishu/Lark нормалізуються як медіаплейсхолдери, а не +як необроблений JSON `file_key`. Коли налаштовано `tools.media.audio`, OpenClaw +завантажує ресурс голосової нотатки й запускає спільну транскрипцію аудіо перед +ходом агента, тож агент отримує текстову розшифровку мовлення. Якщо Feishu містить +текст транскрипції безпосередньо в аудіо payload, цей текст використовується без +ще одного виклику ASR. Без провайдера транскрипції аудіо агент усе одно отримує +плейсхолдер `` разом зі збереженим вкладенням, а не необроблений +payload ресурсу Feishu. ### Надсилання @@ -468,34 +469,35 @@ Feishu/Lark підтримує ACP для особистих повідомле - ✅ Файли - ✅ Аудіо - ✅ Відео/медіа -- ✅ Інтерактивні картки (включно з потоковими оновленнями) -- ⚠️ Форматований текст (форматування у стилі post; не підтримує всі можливості авторингу Feishu/Lark) +- ✅ Інтерактивні картки (зокрема потокові оновлення) +- ⚠️ Форматований текст (форматування у стилі post; не підтримує повні можливості авторингу Feishu/Lark) Нативні аудіобульбашки Feishu/Lark використовують тип повідомлення Feishu `audio` і потребують -вивантаження медіа у форматі Ogg/Opus (`file_type: "opus"`). Наявні медіафайли `.opus` і `.ogg` -надсилаються напряму як нативне аудіо. MP3/WAV/M4A та інші ймовірні аудіоформати -транскодуються в 48kHz Ogg/Opus за допомогою `ffmpeg` лише тоді, коли відповідь запитує -голосову доставку (`audioAsVoice` / інструмент повідомлень `asVoice`, включно з голосовими -відповідями TTS). Звичайні вкладення MP3 залишаються звичайними файлами. Якщо `ffmpeg` відсутній або -конвертація завершується помилкою, OpenClaw переходить до вкладення файлу та записує причину в журнал. +медіа для завантаження Ogg/Opus (`file_type: "opus"`). Наявні медіа `.opus` і `.ogg` +надсилаються безпосередньо як нативне аудіо. MP3/WAV/M4A та інші ймовірні аудіоформати +перекодовуються у 48kHz Ogg/Opus через `ffmpeg` лише тоді, коли відповідь запитує +доставку голосом (`audioAsVoice` / інструмент повідомлень `asVoice`, зокрема відповіді +TTS у вигляді голосових нотаток). Звичайні вкладення MP3 залишаються звичайними файлами. Якщо `ffmpeg` відсутній або +конвертація не вдається, OpenClaw повертається до вкладення файлу й записує причину в журнал. ### Потоки та відповіді - ✅ Вбудовані відповіді - ✅ Відповіді в потоках -- ✅ Відповіді з медіа зберігають прив’язку до потоку при відповіді на повідомлення в потоці +- ✅ Відповіді з медіа залишаються прив’язаними до потоку під час відповіді на повідомлення в потоці Для `groupSessionScope: "group_topic"` і `"group_topic_sender"` нативні -тематичні групи Feishu/Lark використовують `thread_id` події (`omt_*`) як канонічний ключ сесії теми. -Звичайні відповіді в групі, які OpenClaw перетворює на потоки, і далі використовують ID кореневого -повідомлення відповіді (`om_*`), щоб перший хід і наступний хід залишалися в одній сесії. +тематичні групи Feishu/Lark використовують подію `thread_id` (`omt_*`) як канонічний +ключ тематичної сесії. Звичайні групові відповіді, які OpenClaw перетворює на потоки, і далі +використовують ID кореневого повідомлення відповіді (`om_*`), щоб перший хід і наступний хід +залишалися в тій самій сесії. --- ## Пов’язане - [Огляд каналів](/uk/channels) — усі підтримувані канали -- [Прив’язка](/uk/channels/pairing) — автентифікація особистих повідомлень і процес прив’язки -- [Групи](/uk/channels/groups) — поведінка групових чатів і керування через згадки +- [Сполучення](/uk/channels/pairing) — автентифікація DM і процес сполучення +- [Групи](/uk/channels/groups) — поведінка групового чату й обмеження за згадками - [Маршрутизація каналів](/uk/channels/channel-routing) — маршрутизація сесій для повідомлень -- [Безпека](/uk/gateway/security) — модель доступу та захист системи +- [Безпека](/uk/gateway/security) — модель доступу й посилення захисту diff --git a/docs/uk/channels/pairing.md b/docs/uk/channels/pairing.md index 8b7528959..4d988a3b4 100644 --- a/docs/uk/channels/pairing.md +++ b/docs/uk/channels/pairing.md @@ -1,51 +1,56 @@ --- read_when: - Налаштування контролю доступу до особистих повідомлень - - Сполучення нового iOS/Android Node - - Перегляд стану безпеки OpenClaw -summary: 'Огляд сполучення: схваліть, хто може надсилати вам приватні повідомлення + які вузли можуть приєднуватися' + - Сполучення нового вузла iOS/Android + - Огляд стану безпеки OpenClaw +summary: 'Огляд спарювання: схваліть, хто може надсилати вам приватні повідомлення + які вузли можуть приєднуватися' title: Сполучення x-i18n: - generated_at: "2026-04-28T22:44:27Z" + generated_at: "2026-04-29T05:57:19Z" model: gpt-5.5 provider: openai - source_hash: 123d1dccfab0a2ed8a415934eb508e373c4fe85e3d07adb5eb8aa9f3cf8a3fc9 + source_hash: cfdcaf831aedb122ea85200518b8dc1c6f42eff365444dee6c4b740050b1ce26 source_path: channels/pairing.md workflow: 16 --- -«Спарювання» — це явний крок підтвердження доступу в OpenClaw. +«Сполучення» — це явний крок підтвердження доступу в OpenClaw. Воно використовується у двох місцях: -1. **Спарювання DM** (кому дозволено спілкуватися з ботом) -2. **Спарювання Node** (яким пристроям/Node дозволено приєднуватися до мережі Gateway) +1. **Сполучення DM** (кому дозволено спілкуватися з ботом) +2. **Сполучення Node** (яким пристроям/вузлам дозволено приєднуватися до мережі Gateway) Контекст безпеки: [Безпека](/uk/gateway/security) -## 1) Спарювання DM (вхідний доступ до чату) +## 1) Сполучення DM (вхідний доступ до чату) -Коли канал налаштовано з політикою DM `pairing`, невідомі відправники отримують короткий код, а їхнє повідомлення **не обробляється**, доки ви його не підтвердите. +Коли канал налаштовано з політикою DM `pairing`, невідомі відправники отримують короткий код, а їхнє повідомлення **не обробляється**, доки ви не схвалите доступ. Типові політики DM задокументовано тут: [Безпека](/uk/gateway/security) -Коди спарювання: +`dmPolicy: "open"` є публічною лише тоді, коли ефективний список дозволених DM містить `"*"`. +Налаштування й перевірка вимагають цей wildcard для публічно відкритих конфігурацій. Якщо наявний +стан містить `open` з конкретними записами `allowFrom`, runtime все одно допускає +лише цих відправників, а схвалення в pairing-store не розширюють доступ `open`. + +Коди сполучення: - 8 символів, великі літери, без неоднозначних символів (`0O1I`). -- **Спливають через 1 годину**. Бот надсилає повідомлення про спарювання лише тоді, коли створюється новий запит (приблизно раз на годину для кожного відправника). -- Очікувані запити на спарювання DM типово обмежені **3 на канал**; додаткові запити ігноруються, доки один не спливе або не буде схвалений. +- **Завершують дію через 1 годину**. Бот надсилає повідомлення про сполучення лише коли створюється новий запит (приблизно раз на годину для кожного відправника). +- Очікувані запити на сполучення DM типово обмежено **3 на канал**; додаткові запити ігноруються, доки один із них не завершить дію або не буде схвалений. -### Схвалити відправника +### Схвалення відправника ```bash openclaw pairing list telegram openclaw pairing approve telegram ``` -Якщо власника команд ще не налаштовано, схвалення коду спарювання DM також ініціалізує +Якщо власника команд ще не налаштовано, схвалення коду сполучення DM також початково заповнює `commands.ownerAllowFrom` схваленим відправником, наприклад `telegram:123456789`. Це дає початковим налаштуванням явного власника для привілейованих команд і запитів -на схвалення exec. Після появи власника наступні схвалення спарювання надають лише -доступ до DM; вони не додають більше власників. +підтвердження exec. Після появи власника подальші схвалення сполучення надають лише +доступ до DM; вони не додають нових власників. Підтримувані канали: `bluebubbles`, `discord`, `feishu`, `googlechat`, `imessage`, `irc`, `line`, `matrix`, `mattermost`, `msteams`, `nextcloud-talk`, `nostr`, `openclaw-weixin`, `signal`, `slack`, `synology-chat`, `telegram`, `twitch`, `whatsapp`, `zalo`, `zalouser`. @@ -54,60 +59,60 @@ openclaw pairing approve telegram Зберігається в `~/.openclaw/credentials/`: - Очікувані запити: `-pairing.json` -- Схвалене сховище allowlist: - - Типовий акаунт: `-allowFrom.json` - - Нетиповий акаунт: `--allowFrom.json` +- Сховище схваленого списку дозволених: + - Типовий обліковий запис: `-allowFrom.json` + - Нетиповий обліковий запис: `--allowFrom.json` -Поведінка області акаунта: +Поведінка області дії облікового запису: -- Нетипові акаунти читають/записують лише свій файл allowlist з областю. -- Типовий акаунт використовує каналовий файл allowlist без області. +- Нетипові облікові записи читають/записують лише свій scoped файл списку дозволених. +- Типовий обліковий запис використовує channel-scoped unscoped файл списку дозволених. -Вважайте ці дані чутливими (вони контролюють доступ до вашого асистента). +Ставтеся до них як до чутливих даних (вони керують доступом до вашого асистента). -Сховище allowlist для спарювання призначене для доступу до DM. Авторизація груп окрема. -Схвалення коду спарювання DM не дозволяє автоматично цьому відправнику запускати групові -команди або керувати ботом у групах. Початкова ініціалізація першого власника є окремим станом -конфігурації в `commands.ownerAllowFrom`, а доставка в групові чати й надалі підпорядковується -груповим allowlist каналу (наприклад `groupAllowFrom`, `groups` або перевизначенням для окремої групи -чи окремої теми залежно від каналу). +Сховище списку дозволених для сполучення призначене для доступу до DM. Авторизація груп є окремою. +Схвалення коду сполучення DM не дозволяє цьому відправнику автоматично виконувати групові +команди або керувати ботом у групах. Початкове налаштування першого власника є окремим станом конфігурації +в `commands.ownerAllowFrom`, а доставка групових чатів і надалі дотримується +списків дозволених груп каналу (наприклад `groupAllowFrom`, `groups` або перевизначень для окремих груп +чи окремих тем залежно від каналу). -## 2) Спарювання пристрою Node (iOS/Android/macOS/headless Node) +## 2) Сполучення пристрою Node (iOS/Android/macOS/headless вузли) -Node підключаються до Gateway як **пристрої** з `role: node`. Gateway -створює запит на спарювання пристрою, який потрібно схвалити. +Вузли підключаються до Gateway як **пристрої** з `role: node`. Gateway +створює запит на сполучення пристрою, який потрібно схвалити. -### Спарювання через Telegram (рекомендовано для iOS) +### Сполучення через Telegram (рекомендовано для iOS) -Якщо ви використовуєте Plugin `device-pair`, можна виконати перше спарювання пристрою повністю з Telegram: +Якщо ви використовуєте Plugin `device-pair`, перше сполучення пристрою можна повністю виконати з Telegram: -1. У Telegram напишіть своєму боту: `/pair` -2. Бот відповість двома повідомленнями: повідомленням з інструкціями та окремим повідомленням із **кодом налаштування** (його легко скопіювати/вставити в Telegram). -3. На телефоні відкрийте застосунок OpenClaw для iOS → Settings → Gateway. +1. У Telegram напишіть вашому боту: `/pair` +2. Бот відповідає двома повідомленнями: повідомленням з інструкцією та окремим повідомленням із **кодом налаштування** (його легко скопіювати/вставити в Telegram). +3. На телефоні відкрийте застосунок OpenClaw iOS → Settings → Gateway. 4. Вставте код налаштування та підключіться. -5. Поверніться в Telegram: `/pair pending` (перегляньте ID запитів, роль і області), потім схваліть. +5. Поверніться в Telegram: `/pair pending` (перегляньте ідентифікатори запитів, роль і області дії), потім схваліть. -Код налаштування — це base64-кодоване JSON-навантаження, яке містить: +Код налаштування — це JSON-пакет, закодований у base64, який містить: -- `url`: URL WebSocket для Gateway (`ws://...` або `wss://...`) -- `bootstrapToken`: короткоживучий bootstrap-токен для одного пристрою, що використовується для початкового handshake спарювання +- `url`: WebSocket URL Gateway (`ws://...` або `wss://...`) +- `bootstrapToken`: короткочасний bootstrap-токен для одного пристрою, який використовується для початкового handshake сполучення -Цей bootstrap-токен містить вбудований bootstrap-профіль спарювання: +Цей bootstrap-токен несе вбудований bootstrap-профіль сполучення: - основний переданий токен `node` залишається з `scopes: []` -- будь-який переданий токен `operator` залишається обмеженим bootstrap allowlist: +- будь-який переданий токен `operator` залишається обмеженим bootstrap-списком дозволених: `operator.approvals`, `operator.read`, `operator.talk.secrets`, `operator.write` -- перевірки bootstrap-областей мають префікс ролі, а не один плоский пул областей: - записи області operator задовольняють лише запити operator, а ролі не-operator - усе одно мають запитувати області під власним префіксом ролі -- подальша ротація/відкликання токенів залишається обмеженою як схваленим - контрактом ролі пристрою, так і областями operator сесії викликача +- перевірки bootstrap-областей мають префікс ролі, а не один плаский пул областей: + записи області operator задовольняють лише запити operator, а не-operator ролі + все одно мають запитувати області під власним префіксом ролі +- подальша ротація/відкликання токена залишається обмеженою як схваленим + рольовим контрактом пристрою, так і operator-областями сесії викликача -Ставтеся до коду налаштування як до пароля, поки він чинний. +Ставтеся до коду налаштування як до пароля, доки він чинний. -### Схвалити пристрій Node +### Схвалення пристрою Node ```bash openclaw devices list @@ -115,17 +120,17 @@ openclaw devices approve openclaw devices reject ``` -Якщо той самий пристрій повторює спробу з іншими даними автентифікації (наприклад з іншими -роллю/областями/публічним ключем), попередній очікуваний запит замінюється, і створюється новий +Якщо той самий пристрій повторює спробу з іншими деталями автентифікації (наприклад іншими +роллю/областями/публічним ключем), попередній очікуваний запит замінюється і створюється новий `requestId`. -Уже спарений пристрій не отримує ширший доступ непомітно. Якщо він перепідключається і просить більше областей або ширшу роль, OpenClaw залишає наявне схвалення без змін і створює новий очікуваний запит на підвищення доступу. Використовуйте `openclaw devices list`, щоб порівняти поточний схвалений доступ із новим запитаним доступом перед схваленням. +Уже сполучений пристрій не отримує ширший доступ непомітно. Якщо він повторно підключається і просить більше областей або ширшу роль, OpenClaw залишає наявне схвалення без змін і створює новий очікуваний запит на підвищення доступу. Використовуйте `openclaw devices list`, щоб порівняти поточний схвалений доступ із новим запитаним доступом перед схваленням. ### Необов’язкове автоматичне схвалення Node за довіреним CIDR -Спарювання пристроїв типово залишається ручним. Для суворо контрольованих мереж Node +Сполучення пристроїв типово залишається ручним. Для суворо контрольованих мереж Node можна ввімкнути автоматичне схвалення першого підключення Node з явними CIDR або точними IP: ```json5 @@ -140,24 +145,24 @@ openclaw devices reject } ``` -Це застосовується лише до нових запитів спарювання `role: node` без запитаних -областей. Клієнти operator, browser, Control UI і WebChat усе одно потребують ручного -схвалення. Зміни ролі, області, metadata та публічного ключа також потребують ручного +Це застосовується лише до нових запитів на сполучення `role: node` без запитаних +областей. Клієнти Operator, браузера, Control UI та WebChat усе одно потребують ручного +схвалення. Зміни ролі, області, метаданих і публічного ключа також потребують ручного схвалення. -### Сховище стану спарювання Node +### Зберігання стану сполучення Node Зберігається в `~/.openclaw/devices/`: -- `pending.json` (короткоживучий; очікувані запити спливають) -- `paired.json` (спарені пристрої + токени) +- `pending.json` (короткочасний; очікувані запити завершують дію) +- `paired.json` (сполучені пристрої + токени) ### Примітки - Застарілий API `node.pair.*` (CLI: `openclaw nodes pending|approve|reject|remove|rename`) є - окремим сховищем спарювання, яким володіє Gateway. WS Node усе одно потребують спарювання пристрою. -- Запис спарювання є довговічним джерелом істини для схвалених ролей. Активні - токени пристрою залишаються обмеженими цим набором схвалених ролей; випадковий запис токена + окремим сховищем сполучення, власником якого є Gateway. WS-вузли все одно потребують сполучення пристрою. +- Запис сполучення є довговічним джерелом істини для схвалених ролей. Активні + токени пристроїв залишаються обмеженими цим схваленим набором ролей; випадковий запис токена поза схваленими ролями не створює нового доступу. ## Пов’язані документи diff --git a/docs/uk/channels/synology-chat.md b/docs/uk/channels/synology-chat.md index c13b9a3a1..81197c5eb 100644 --- a/docs/uk/channels/synology-chat.md +++ b/docs/uk/channels/synology-chat.md @@ -5,24 +5,24 @@ read_when: summary: Налаштування Webhook Synology Chat і конфігурація OpenClaw title: Synology Chat x-i18n: - generated_at: "2026-04-23T20:44:53Z" - model: gpt-5.4 + generated_at: "2026-04-29T05:57:06Z" + model: gpt-5.5 provider: openai - source_hash: 5135e9aa1fd86437a635378dfbbde321bbd2e5f6fef7a3cc740ea54ebf4b76d5 + source_hash: c3d6d7a56bd15d29de38c6ae29ae496b491c2e75df5e0a0a15410b0fbdc55a00 source_path: channels/synology-chat.md - workflow: 15 + workflow: 16 --- -Стан: вбудований Plugin каналу приватних повідомлень, що використовує Webhook-и Synology Chat. -Plugin приймає вхідні повідомлення з вихідних Webhook-ів Synology Chat і надсилає відповіді -через вхідний Webhook Synology Chat. +Стан: вбудований Plugin каналу прямих повідомлень, що використовує webhooks Synology Chat. +Plugin приймає вхідні повідомлення від вихідних webhooks Synology Chat і надсилає відповіді +через вхідний webhook Synology Chat. ## Вбудований Plugin -Synology Chat постачається як вбудований Plugin у поточних релізах OpenClaw, тому звичайні -пакетовані збірки не потребують окремого встановлення. +Synology Chat постачається як вбудований Plugin у поточних випусках OpenClaw, тому звичайні +пакетні збірки не потребують окремого встановлення. -Якщо у вас старіша збірка або кастомне встановлення без Synology Chat, +Якщо ви використовуєте старішу збірку або кастомне встановлення, яке виключає Synology Chat, встановіть його вручну: Встановлення з локального checkout: @@ -31,36 +31,36 @@ Synology Chat постачається як вбудований Plugin у по openclaw plugins install ./path/to/local/synology-chat-plugin ``` -Докладніше: [Plugin-и](/uk/tools/plugin) +Докладніше: [Plugins](/uk/tools/plugin) ## Швидке налаштування 1. Переконайтеся, що Plugin Synology Chat доступний. - - У поточних пакетованих релізах OpenClaw він уже вбудований. - - У старіших/кастомних встановленнях його можна додати вручну з source checkout командою вище. + - Поточні пакетні випуски OpenClaw вже включають його. + - Старіші/кастомні встановлення можуть додати його вручну з checkout вихідного коду за допомогою команди вище. - `openclaw onboard` тепер показує Synology Chat у тому самому списку налаштування каналів, що й `openclaw channels add`. - Неінтерактивне налаштування: `openclaw channels add --channel synology-chat --token --url ` 2. В інтеграціях Synology Chat: - - Створіть вхідний Webhook і скопіюйте його URL. - - Створіть вихідний Webhook зі своїм секретним токеном. -3. Спрямуйте URL вихідного Webhook до вашого Gateway OpenClaw: - - `https://gateway-host/webhook/synology` типово. + - Створіть вхідний webhook і скопіюйте його URL. + - Створіть вихідний webhook із вашим секретним токеном. +3. Спрямуйте URL вихідного webhook до вашого OpenClaw gateway: + - `https://gateway-host/webhook/synology` за замовчуванням. - Або ваш кастомний `channels.synology-chat.webhookPath`. 4. Завершіть налаштування в OpenClaw. - - Покроково: `openclaw onboard` + - Інтерактивно: `openclaw onboard` - Напряму: `openclaw channels add --channel synology-chat --token --url ` -5. Перезапустіть Gateway і надішліть DM боту Synology Chat. +5. Перезапустіть gateway і надішліть DM боту Synology Chat. -Деталі автентифікації Webhook: +Деталі автентифікації webhook: -- OpenClaw приймає токен вихідного Webhook спочатку з `body.token`, потім - з `?token=...`, а потім із заголовків. -- Прийняті форми заголовків: +- OpenClaw приймає токен вихідного webhook з `body.token`, потім + `?token=...`, потім із заголовків. +- Прийнятні форми заголовків: - `x-synology-token` - `x-webhook-token` - `x-openclaw-token` - `Authorization: Bearer ` -- Порожні або відсутні токени закривають доступ за замовчуванням. +- Порожні або відсутні токени закривають доступ. Мінімальна конфігурація: @@ -83,7 +83,7 @@ openclaw plugins install ./path/to/local/synology-chat-plugin ## Змінні середовища -Для типового акаунта можна використовувати env-змінні: +Для типового облікового запису можна використовувати змінні середовища: - `SYNOLOGY_CHAT_TOKEN` - `SYNOLOGY_CHAT_INCOMING_URL` @@ -92,25 +92,25 @@ openclaw plugins install ./path/to/local/synology-chat-plugin - `SYNOLOGY_RATE_LIMIT` - `OPENCLAW_BOT_NAME` -Значення конфігурації мають пріоритет над env-змінними. +Значення конфігурації перевизначають змінні середовища. -`SYNOLOGY_CHAT_INCOMING_URL` не можна задавати з workspace `.env`; див. [Файли workspace `.env`](/uk/gateway/security). +`SYNOLOGY_CHAT_INCOMING_URL` не можна встановити з workspace `.env`; див. [Файли workspace `.env`](/uk/gateway/security). -## Політика DM і керування доступом +## Політика DM і контроль доступу -- `dmPolicy: "allowlist"` — рекомендоване типове значення. -- `allowedUserIds` приймає список (або рядок, розділений комами) Synology user ID. -- У режимі `allowlist` порожній список `allowedUserIds` вважається неправильною конфігурацією, і маршрут Webhook не буде запущено (використовуйте `dmPolicy: "open"` для дозволу всім). -- `dmPolicy: "open"` дозволяє будь-якого відправника. +- `dmPolicy: "allowlist"` є рекомендованим типовим значенням. +- `allowedUserIds` приймає список (або рядок, розділений комами) ідентифікаторів користувачів Synology. +- У режимі `allowlist` порожній список `allowedUserIds` вважається помилковою конфігурацією, і маршрут webhook не запуститься (використовуйте `dmPolicy: "open"` з `allowedUserIds: ["*"]` для дозволу всім). +- `dmPolicy: "open"` дозволяє публічні DM лише коли `allowedUserIds` містить `"*"`; з обмежувальними записами спілкуватися можуть лише відповідні користувачі. - `dmPolicy: "disabled"` блокує DM. -- Прив’язка отримувача відповіді типово залишається на стабільному числовому `user_id`. `channels.synology-chat.dangerouslyAllowNameMatching: true` — це аварійний режим сумісності, який знову вмикає пошук за змінними username/nickname для доставки відповідей. -- Схвалення pairing працює з: +- Прив’язка одержувача відповіді за замовчуванням лишається на стабільному числовому `user_id`. `channels.synology-chat.dangerouslyAllowNameMatching: true` — це режим сумісності на крайній випадок, який повторно вмикає пошук за змінюваним username/nickname для доставки відповідей. +- Схвалення сполучення працюють із: - `openclaw pairing list synology-chat` - `openclaw pairing approve synology-chat ` ## Вихідна доставка -Використовуйте числові Synology Chat user ID як цілі. +Використовуйте числові ідентифікатори користувачів Synology Chat як цілі. Приклади: @@ -120,19 +120,19 @@ openclaw message send --channel synology-chat --target synology-chat:123456 --te ``` Надсилання медіа підтримується через доставку файлів за URL. -URL вихідних файлів мають використовувати `http` або `https`, а приватні чи іншим чином заблоковані мережеві цілі відхиляються до того, як OpenClaw передасть URL до Webhook NAS. +Вихідні URL файлів мають використовувати `http` або `https`, а приватні або інакше заблоковані мережеві цілі відхиляються до того, як OpenClaw передасть URL до webhook NAS. -## Кілька акаунтів +## Кілька облікових записів -Підтримується кілька акаунтів Synology Chat у `channels.synology-chat.accounts`. -Кожен акаунт може перевизначати токен, вхідний URL, шлях Webhook, політику DM і ліміти. -Сесії приватних повідомлень ізольовані для кожного акаунта та користувача, тому той самий числовий `user_id` -на двох різних акаунтах Synology не ділить спільний стан транскрипту. -Надайте кожному ввімкненому акаунту окремий `webhookPath`. OpenClaw тепер відхиляє дубльовані точні шляхи -і відмовляється запускати іменовані акаунти, які лише успадковують спільний шлях Webhook у конфігураціях із кількома акаунтами. -Якщо вам навмисно потрібне застаріле успадкування для іменованого акаунта, задайте -`dangerouslyAllowInheritedWebhookPath: true` для цього акаунта або в `channels.synology-chat`, -але дубльовані точні шляхи все одно відхиляються із закриттям доступу за замовчуванням. Надавайте перевагу явним шляхам для кожного акаунта. +Кілька облікових записів Synology Chat підтримуються в `channels.synology-chat.accounts`. +Кожен обліковий запис може перевизначати токен, вхідний URL, шлях webhook, політику DM і ліміти. +Сесії прямих повідомлень ізольовані за обліковим записом і користувачем, тому той самий числовий `user_id` +у двох різних облікових записах Synology не спільно використовує стан transcript. +Надайте кожному ввімкненому обліковому запису окремий `webhookPath`. OpenClaw тепер відхиляє дублікати точних шляхів +і відмовляється запускати іменовані облікові записи, які лише успадковують спільний шлях webhook у налаштуваннях із кількома обліковими записами. +Якщо вам навмисно потрібне застаріле успадкування для іменованого облікового запису, встановіть +`dangerouslyAllowInheritedWebhookPath: true` для цього облікового запису або в `channels.synology-chat`, +але дублікати точних шляхів усе одно відхиляються із закриттям доступу. Надавайте перевагу явним шляхам для кожного облікового запису. ```json5 { @@ -157,37 +157,37 @@ URL вихідних файлів мають використовувати `htt } ``` -## Примітки щодо безпеки +## Нотатки щодо безпеки -- Тримайте `token` у секреті та змінюйте його, якщо він витік. -- Залишайте `allowInsecureSsl: false`, якщо тільки ви явно не довіряєте самопідписаному локальному сертифікату NAS. -- Вхідні запити Webhook перевіряються за токеном і обмежуються за частотою для кожного відправника. -- Перевірки некоректного токена використовують порівняння секретів за сталий час і закривають доступ за замовчуванням. +- Зберігайте `token` у секреті та ротуйте його в разі витоку. +- Залишайте `allowInsecureSsl: false`, якщо ви явно не довіряєте самопідписаному локальному сертифікату NAS. +- Вхідні запити webhook перевіряються за токеном і обмежуються за частотою для кожного відправника. +- Перевірки недійсного токена використовують порівняння секретів зі сталим часом виконання та закривають доступ. - Для production надавайте перевагу `dmPolicy: "allowlist"`. -- Тримайте `dangerouslyAllowNameMatching` вимкненим, якщо тільки вам явно не потрібна застаріла доставка відповідей за username. -- Тримайте `dangerouslyAllowInheritedWebhookPath` вимкненим, якщо тільки ви явно не приймаєте ризик маршрутизації зі спільним шляхом у конфігурації з кількома акаунтами. +- Тримайте `dangerouslyAllowNameMatching` вимкненим, якщо вам явно не потрібна застаріла доставка відповідей на основі username. +- Тримайте `dangerouslyAllowInheritedWebhookPath` вимкненим, якщо ви явно не приймаєте ризик маршрутизації через спільний шлях у налаштуванні з кількома обліковими записами. ## Усунення несправностей - `Missing required fields (token, user_id, text)`: - - у payload вихідного Webhook відсутнє одне з обов’язкових полів - - якщо Synology надсилає токен у заголовках, переконайтеся, що gateway/проксі зберігає ці заголовки + - у payload вихідного webhook бракує одного з обов’язкових полів + - якщо Synology надсилає токен у заголовках, переконайтеся, що gateway/proxy зберігає ці заголовки - `Invalid token`: - - секрет вихідного Webhook не збігається з `channels.synology-chat.token` - - запит потрапляє не в той акаунт/шлях Webhook - - reverse proxy прибрав заголовок токена до того, як запит дійшов до OpenClaw + - секрет вихідного webhook не відповідає `channels.synology-chat.token` + - запит потрапляє в неправильний обліковий запис/шлях webhook + - reverse proxy видалив заголовок токена до того, як запит досяг OpenClaw - `Rate limit exceeded`: - - забагато спроб із некоректним токеном з одного джерела можуть тимчасово заблокувати це джерело - - для автентифікованих відправників також діє окремий ліміт частоти повідомлень для кожного користувача -- `Allowlist is empty. Configure allowedUserIds or use dmPolicy=open.`: - - увімкнено `dmPolicy="allowlist"`, але жодного користувача не налаштовано + - забагато спроб із недійсним токеном з одного джерела можуть тимчасово заблокувати це джерело + - автентифіковані відправники також мають окремий ліміт повідомлень для кожного користувача +- `Allowlist is empty. Configure allowedUserIds or use dmPolicy=open with allowedUserIds=["*"].`: + - `dmPolicy="allowlist"` увімкнено, але користувачів не налаштовано - `User not authorized`: - - числовий `user_id` відправника відсутній у `allowedUserIds` + - числовий `user_id` відправника не входить до `allowedUserIds` ## Пов’язане - [Огляд каналів](/uk/channels) — усі підтримувані канали -- [Pairing](/uk/channels/pairing) — автентифікація DM і потік pairing -- [Групи](/uk/channels/groups) — поведінка групового чату та шлюзування за згадками +- [Сполучення](/uk/channels/pairing) — автентифікація DM і потік сполучення +- [Групи](/uk/channels/groups) — поведінка групового чату та gating згадок - [Маршрутизація каналів](/uk/channels/channel-routing) — маршрутизація сесій для повідомлень -- [Безпека](/uk/gateway/security) — модель доступу та зміцнення безпеки +- [Безпека](/uk/gateway/security) — модель доступу та посилення безпеки diff --git a/docs/uk/channels/telegram.md b/docs/uk/channels/telegram.md index e360b4520..5145543b4 100644 --- a/docs/uk/channels/telegram.md +++ b/docs/uk/channels/telegram.md @@ -1,28 +1,28 @@ --- read_when: - Робота над функціями Telegram або Webhook -summary: Стан підтримки Telegram-бота, можливості та конфігурація +summary: Статус підтримки, можливості та налаштування бота Telegram title: Telegram x-i18n: - generated_at: "2026-04-28T23:41:24Z" + generated_at: "2026-04-29T05:56:58Z" model: gpt-5.5 provider: openai - source_hash: aecd9edba56d0689a5823536a92171fa6e0c3ef56656f4699bb1e5793e248751 + source_hash: 0bf75d82f21658a1ca547b2e4ab229f7b6e47537a2379bf52bd7a18f0677664b source_path: channels/telegram.md workflow: 16 --- -Готово до production для DM ботів і груп через grammY. Long polling є режимом за замовчуванням; режим webhook необов’язковий. +Готово для production для DM ботів і груп через grammY. Long polling є режимом за замовчуванням; режим Webhook є необов’язковим. - - Типова політика DM для Telegram — створення пари. + + Політика DM за замовчуванням для Telegram — сполучення. - Міжканальні діагностика та сценарії відновлення. + Міжканальна діагностика та інструкції з відновлення. - Повні шаблони та приклади конфігурації каналів. + Повні шаблони й приклади конфігурації каналів. @@ -30,7 +30,7 @@ x-i18n: - Відкрийте Telegram і поспілкуйтеся з **@BotFather** (переконайтеся, що handle точно `@BotFather`). + Відкрийте Telegram і почніть чат із **@BotFather** (переконайтеся, що handle точно `@BotFather`). Виконайте `/newbot`, дотримуйтеся підказок і збережіть токен. @@ -51,12 +51,12 @@ x-i18n: } ``` - Резервний env: `TELEGRAM_BOT_TOKEN=...` (лише обліковий запис за замовчуванням). - Telegram **не** використовує `openclaw channels login telegram`; налаштуйте токен у конфігурації/env, потім запустіть gateway. + Резервний варіант через env: `TELEGRAM_BOT_TOKEN=...` (лише обліковий запис за замовчуванням). + Telegram **не** використовує `openclaw channels login telegram`; налаштуйте токен у config/env, потім запустіть Gateway. - + ```bash openclaw gateway @@ -64,38 +64,38 @@ openclaw pairing list telegram openclaw pairing approve telegram ``` - Коди створення пари спливають через 1 годину. + Коди сполучення спливають через 1 годину. - Додайте бота до своєї групи, потім задайте `channels.telegram.groups` і `groupPolicy` відповідно до вашої моделі доступу. + Додайте бота до своєї групи, потім налаштуйте `channels.telegram.groups` і `groupPolicy` відповідно до вашої моделі доступу. -Порядок визначення токена враховує обліковий запис. На практиці значення конфігурації мають пріоритет над резервним env, а `TELEGRAM_BOT_TOKEN` застосовується лише до облікового запису за замовчуванням. +Порядок визначення токена враховує облікові записи. На практиці значення config мають пріоритет над резервним env, а `TELEGRAM_BOT_TOKEN` застосовується лише до облікового запису за замовчуванням. -## Налаштування на стороні Telegram +## Налаштування на боці Telegram - Боти Telegram за замовчуванням використовують **режим приватності**, який обмежує, які повідомлення груп вони отримують. + Боти Telegram за замовчуванням використовують **Privacy Mode**, який обмежує, які групові повідомлення вони отримують. - Якщо бот має бачити всі повідомлення групи, або: + Якщо бот має бачити всі повідомлення групи, виконайте одне з такого: - вимкніть режим приватності через `/setprivacy`, або - зробіть бота адміністратором групи. - Після перемикання режиму приватності видаліть і повторно додайте бота в кожну групу, щоб Telegram застосував зміну. + Після перемикання режиму приватності видаліть і повторно додайте бота в кожній групі, щоб Telegram застосував зміну. Статус адміністратора керується в налаштуваннях групи Telegram. - Адміністративні боти отримують усі повідомлення групи, що корисно для постійної поведінки в групі. + Боти-адміністратори отримують усі повідомлення групи, що корисно для постійно активної поведінки в групі. @@ -107,37 +107,38 @@ openclaw pairing approve telegram -## Контроль доступу та активація +## Контроль доступу й активація - `channels.telegram.dmPolicy` керує доступом до прямих повідомлень: + `channels.telegram.dmPolicy` керує доступом до особистих повідомлень: - `pairing` (за замовчуванням) - - `allowlist` (потрібен принаймні один ID відправника в `allowFrom`) - - `open` (потрібно, щоб `allowFrom` містив `"*"`) + - `allowlist` (потребує принаймні одного ID відправника в `allowFrom`) + - `open` (потребує, щоб `allowFrom` містив `"*"`) - `disabled` - `dmPolicy: "open"` з `allowFrom: ["*"]` дозволяє будь-якому обліковому запису Telegram, який знайде або вгадає ім’я користувача бота, керувати ботом. Використовуйте це лише для навмисно публічних ботів із жорстко обмеженими інструментами; боти з одним власником мають використовувати `allowlist` із числовими ID користувачів. + `dmPolicy: "open"` з `allowFrom: ["*"]` дозволяє будь-якому обліковому запису Telegram, який знайде або вгадає ім’я користувача бота, керувати ботом. Використовуйте це лише для навмисно публічних ботів із суворо обмеженими інструментами; боти з одним власником мають використовувати `allowlist` із числовими ID користувачів. - `channels.telegram.allowFrom` приймає числові ID користувачів Telegram. Префікси `telegram:` / `tg:` приймаються та нормалізуються. - `dmPolicy: "allowlist"` з порожнім `allowFrom` блокує всі DM і відхиляється валідацією конфігурації. + `channels.telegram.allowFrom` приймає числові ID користувачів Telegram. Префікси `telegram:` / `tg:` приймаються й нормалізуються. + У конфігураціях із кількома обліковими записами обмежувальний верхньорівневий `channels.telegram.allowFrom` розглядається як межа безпеки: записи рівня облікового запису `allowFrom: ["*"]` не роблять цей обліковий запис публічним, якщо ефективний allowlist облікового запису після злиття все ще не містить явний wildcard. + `dmPolicy: "allowlist"` з порожнім `allowFrom` блокує всі DM і відхиляється валідацією config. Налаштування запитує лише числові ID користувачів. - Якщо ви оновилися і ваша конфігурація містить записи allowlist виду `@username`, виконайте `openclaw doctor --fix`, щоб їх розв’язати (best-effort; потрібен токен бота Telegram). - Якщо раніше ви покладалися на файли allowlist зі сховища створення пари, `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`, щоб політика доступу була сталою в конфігурації (а не залежала від попередніх схвалень створення пари). + Для ботів з одним власником надавайте перевагу `dmPolicy: "allowlist"` з явними числовими ID `allowFrom`, щоб політика доступу залишалася сталою в config (замість залежності від попередніх схвалень сполучення). - Поширене непорозуміння: схвалення створення пари для DM не означає «цей відправник авторизований усюди». - Створення пари надає доступ до DM. Якщо власника команд ще немає, перше схвалене створення пари також задає `commands.ownerAllowFrom`, щоб команди лише для власника й схвалення exec мали явний обліковий запис оператора. - Авторизація відправників у групах усе ще береться з явних allowlist у конфігурації. + Поширена плутанина: схвалення сполучення DM не означає «цей відправник авторизований усюди». + Сполучення надає доступ до DM. Якщо власник команд ще не існує, перше схвалене сполучення також встановлює `commands.ownerAllowFrom`, щоб команди лише для власника та схвалення exec мали явний обліковий запис оператора. + Авторизація відправника в групі все ще походить з явних allowlist у config. Якщо ви хочете «я авторизований один раз, і працюють як DM, так і групові команди», додайте свій числовий ID користувача Telegram у `channels.telegram.allowFrom`; для команд лише для власника переконайтеся, що `commands.ownerAllowFrom` містить `telegram:`. ### Як знайти свій ID користувача Telegram Безпечніше (без стороннього бота): - 1. Надішліть DM своєму боту. + 1. Напишіть DM своєму боту. 2. Виконайте `openclaw logs --follow`. 3. Прочитайте `from.id`. @@ -155,27 +156,27 @@ curl "https://api.telegram.org/bot/getUpdates" Два елементи керування застосовуються разом: 1. **Які групи дозволені** (`channels.telegram.groups`) - - немає конфігурації `groups`: + - немає config `groups`: - з `groupPolicy: "open"`: будь-яка група може пройти перевірки ID групи - - з `groupPolicy: "allowlist"` (за замовчуванням): групи заблоковані, доки ви не додасте записи `groups` (або `"*"`) + - з `groupPolicy: "allowlist"` (за замовчуванням): групи блокуються, доки ви не додасте записи `groups` (або `"*"`) - `groups` налаштовано: працює як allowlist (явні ID або `"*"`) - 2. **Які відправники дозволені в групах** (`channels.telegram.groupPolicy`) + 2. **Яким відправникам дозволено в групах** (`channels.telegram.groupPolicy`) - `open` - `allowlist` (за замовчуванням) - `disabled` `groupAllowFrom` використовується для фільтрації відправників у групах. Якщо не задано, Telegram повертається до `allowFrom`. Записи `groupAllowFrom` мають бути числовими ID користувачів Telegram (префікси `telegram:` / `tg:` нормалізуються). - Не додавайте ID чатів груп або супергруп Telegram у `groupAllowFrom`. Від’ємні ID чатів належать до `channels.telegram.groups`. - Нечислові записи ігноруються для авторизації відправників. - Межа безпеки (`2026.2.25+`): авторизація відправників у групах **не** успадковує схвалення зі сховища створення пари DM. - Створення пари лишається лише для DM. Для груп задайте `groupAllowFrom` або per-group/per-topic `allowFrom`. - Якщо `groupAllowFrom` не задано, Telegram повертається до конфігураційного `allowFrom`, а не до сховища створення пари. + Не додавайте ID чатів груп або супергруп Telegram у `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` не задано явно. + Примітка щодо runtime: якщо `channels.telegram` повністю відсутній, runtime за замовчуванням fail-closed до `groupPolicy="allowlist"`, якщо `channels.defaults.groupPolicy` не задано явно. - Приклад: дозволити будь-якого учасника в одній конкретній групі: + Приклад: дозволити будь-якому учаснику в одній конкретній групі: ```json5 { @@ -192,7 +193,7 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - Приклад: дозволити лише конкретних користувачів усередині однієї конкретної групи: + Приклад: дозволити лише конкретних користувачів в одній конкретній групі: ```json5 { @@ -212,9 +213,9 @@ 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: ["*"]` лише коли хочете, щоб будь-який учасник дозволеної групи міг говорити з ботом. @@ -230,14 +231,14 @@ curl "https://api.telegram.org/bot/getUpdates" - `agents.list[].groupChat.mentionPatterns` - `messages.groupChat.mentionPatterns` - Перемикачі команд на рівні сесії: + Перемикачі команд рівня сесії: - `/activation always` - `/activation mention` - Вони оновлюють лише стан сесії. Для збереження використовуйте конфігурацію. + Вони оновлюють лише стан сесії. Для збереження використовуйте config. - Приклад сталої конфігурації: + Приклад сталої config: ```json5 { @@ -253,42 +254,42 @@ curl "https://api.telegram.org/bot/getUpdates" Як отримати ID групового чату: - - перешліть повідомлення групи до `@userinfobot` / `@getidsbot` - - або прочитайте `chat.id` з `openclaw logs --follow` - - або перегляньте Bot API `getUpdates` + - переслати повідомлення групи до `@userinfobot` / `@getidsbot` + - або прочитати `chat.id` з `openclaw logs --follow` + - або переглянути Bot API `getUpdates` ## Поведінка runtime -- Telegram належить процесу gateway. +- Telegram належить процесу Gateway. - Маршрутизація детермінована: вхідні повідомлення Telegram отримують відповідь у Telegram (модель не вибирає канали). -- Вхідні повідомлення нормалізуються в спільний envelope каналу з метаданими відповіді та placeholders для медіа. -- Групові сесії ізольовані за ID групи. Теми форуму додають `:topic:`, щоб теми лишалися ізольованими. -- DM-повідомлення можуть містити `message_thread_id`; OpenClaw маршрутизує їх із ключами сесій, що враховують thread, і зберігає ID thread для відповідей. -- Long polling використовує grammY runner із послідовністю per-chat/per-thread. Загальна конкурентність runner sink використовує `agents.defaults.maxConcurrent`. -- Long polling захищений всередині кожного процесу gateway, тож лише один активний poller може використовувати токен бота одночасно. Якщо ви все ще бачите конфлікти `getUpdates` 409, ймовірно, інший gateway OpenClaw, script або зовнішній poller використовує той самий токен. -- Перезапуски watchdog для long-polling за замовчуванням запускаються після 120 секунд без завершеної liveness `getUpdates`. Збільшуйте `channels.telegram.pollingStallThresholdMs` лише якщо ваше розгортання все ще бачить хибні перезапуски через polling-stall під час тривалої роботи. Значення вказується в мілісекундах і дозволене від `30000` до `600000`; підтримуються перевизначення per-account. -- Telegram Bot API не підтримує read receipts (`sendReadReceipts` не застосовується). +- Вхідні повідомлення нормалізуються в спільний конверт каналу з метаданими відповіді та placeholder для медіа. +- Групові сесії ізольовані за ID групи. Теми форуму додають `:topic:`, щоб теми залишалися ізольованими. +- DM повідомлення можуть містити `message_thread_id`; OpenClaw маршрутизує їх із thread-aware ключами сесій і зберігає ID thread для відповідей. +- Long polling використовує grammY runner з послідовністю на рівні чату/thread. Загальна конкурентність runner sink використовує `agents.defaults.maxConcurrent`. +- Long polling захищений усередині кожного процесу Gateway, щоб лише один активний poller міг використовувати токен бота одночасно. Якщо ви все ще бачите конфлікти `getUpdates` 409, інший OpenClaw Gateway, script або зовнішній poller, імовірно, використовує той самий токен. +- Перезапуски watchdog для long-polling за замовчуванням запускаються після 120 секунд без завершеної liveness `getUpdates`. Збільшуйте `channels.telegram.pollingStallThresholdMs` лише якщо ваше розгортання все ще бачить хибні перезапуски через polling-stall під час тривалої роботи. Значення в мілісекундах і дозволене від `30000` до `600000`; підтримуються перевизначення на рівні облікового запису. +- Telegram Bot API не підтримує read-receipt (`sendReadReceipts` не застосовується). ## Довідник функцій - OpenClaw може stream часткові відповіді в реальному часі: + OpenClaw може транслювати часткові відповіді в реальному часі: - прямі чати: повідомлення попереднього перегляду + `editMessageText` - групи/теми: повідомлення попереднього перегляду + `editMessageText` Вимога: - - `channels.telegram.streaming` дорівнює `off | partial | block | progress` (за замовчуванням: `partial`) - - `progress` відображається в `partial` у Telegram (сумісність із міжканальним іменуванням) - - `streaming.preview.toolProgress` керує тим, чи оновлення інструментів/прогресу повторно використовують те саме редаговане повідомлення попереднього перегляду (за замовчуванням: `true`, коли preview streaming активний) - - застарілі `channels.telegram.streamMode` і булеві значення `streaming` виявляються; виконайте `openclaw doctor --fix`, щоб перенести їх у `channels.telegram.streaming.mode` + - `channels.telegram.streaming` є `off | partial | block | progress` (за замовчуванням: `partial`) + - `progress` зіставляється з `partial` у Telegram (сумісність із міжканальним іменуванням) + - `streaming.preview.toolProgress` керує тим, чи оновлення інструментів/прогресу повторно використовують те саме відредаговане повідомлення попереднього перегляду (за замовчуванням: `true`, коли preview streaming активний) + - застарілі значення `channels.telegram.streamMode` і boolean `streaming` виявляються; виконайте `openclaw doctor --fix`, щоб перенести їх у `channels.telegram.streaming.mode` - Оновлення попереднього перегляду прогресу інструментів — це короткі рядки «Працюємо...», які показуються під час роботи інструментів, наприклад виконання команд, читання файлів, оновлення плану або підсумки patch. Telegram залишає їх увімкненими за замовчуванням, щоб відповідати випущеній поведінці OpenClaw з `v2026.4.22` і новіших. Щоб зберегти редагований попередній перегляд для тексту відповіді, але приховати рядки прогресу інструментів, задайте: + Оновлення попереднього перегляду tool-progress — це короткі рядки "Working...", які показуються під час роботи інструментів, наприклад виконання команд, читання файлів, оновлення планування або підсумки патчів. Telegram залишає їх увімкненими за замовчуванням, щоб відповідати випущеній поведінці OpenClaw від `v2026.4.22` і пізніше. Щоб залишити відредагований попередній перегляд для тексту відповіді, але приховати рядки tool-progress, задайте: ```json { @@ -305,41 +306,41 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - Використовуйте `streaming.mode: "off"` лише коли хочете доставку тільки фінальної відповіді: редагування попереднього перегляду Telegram вимкнені, а загальні повідомлення інструментів/прогресу приглушуються замість надсилання як окремих повідомлень «Працюємо...». Запити на схвалення, media payloads і помилки все ще маршрутизуються через звичайну фінальну доставку. Використовуйте `streaming.preview.toolProgress: false`, коли хочете лише зберегти редагування попереднього перегляду відповіді, приховуючи рядки статусу прогресу інструментів. + Використовуйте `streaming.mode: "off"` лише коли хочете доставку тільки фінального повідомлення: редагування попереднього перегляду Telegram вимикаються, а загальні повідомлення інструментів/прогресу пригнічуються замість надсилання окремими повідомленнями "Working...". Запити на схвалення, media payloads і помилки все ще маршрутизуються через звичайну фінальну доставку. Використовуйте `streaming.preview.toolProgress: false`, коли хочете залишити лише редагування попереднього перегляду відповіді, приховавши рядки статусу tool-progress. Для відповідей лише з текстом: - - короткі попередні перегляди DM/груп/тем: OpenClaw зберігає те саме повідомлення попереднього перегляду й виконує фінальне редагування на місці - - попередні перегляди старші приблизно за одну хвилину: OpenClaw надсилає завершену відповідь як нове фінальне повідомлення, а потім очищає попередній перегляд, тож видима часова мітка Telegram відображає час завершення, а не час створення попереднього перегляду + - короткі попередні перегляди в DM/групі/топіку: OpenClaw зберігає те саме повідомлення попереднього перегляду й виконує фінальне редагування на місці + - попередні перегляди, старші приблизно за одну хвилину: OpenClaw надсилає завершену відповідь як нове фінальне повідомлення, а потім очищає попередній перегляд, тому видима позначка часу в Telegram відображає час завершення, а не час створення попереднього перегляду - Для складних відповідей (наприклад медіа-payload) OpenClaw повертається до звичайної остаточної доставки, а потім очищає повідомлення попереднього перегляду. + Для складних відповідей (наприклад, медіанавантажень) OpenClaw повертається до звичайної фінальної доставки, а потім очищає повідомлення попереднього перегляду. - Потокове передавання попереднього перегляду відокремлене від потокового передавання блоків. Коли потокове передавання блоків явно ввімкнено для Telegram, OpenClaw пропускає потік попереднього перегляду, щоб уникнути подвійного потокового передавання. + Потокове передавання попереднього перегляду відокремлене від блокового потокового передавання. Коли блокове потокове передавання явно ввімкнене для Telegram, OpenClaw пропускає потік попереднього перегляду, щоб уникнути подвійного потокового передавання. Якщо нативний транспорт чернеток недоступний або відхилений, OpenClaw автоматично повертається до `sendMessage` + `editMessageText`. Потік міркувань лише для Telegram: - - `/reasoning stream` надсилає міркування до живого попереднього перегляду під час генерування - - остаточна відповідь надсилається без тексту міркувань + - `/reasoning stream` надсилає міркування до живого попереднього перегляду під час генерації + - фінальна відповідь надсилається без тексту міркувань - + Вихідний текст використовує Telegram `parse_mode: "HTML"`. - - Markdown-подібний текст рендериться у безпечний для Telegram HTML. - - Сирий HTML моделі екранується, щоб зменшити кількість помилок парсингу Telegram. + - Текст, подібний до Markdown, рендериться в безпечний для Telegram HTML. + - Сирий HTML від моделі екранується, щоб зменшити кількість помилок парсингу Telegram. - Якщо Telegram відхиляє розібраний HTML, OpenClaw повторює спробу як звичайний текст. - Попередні перегляди посилань увімкнено за замовчуванням; їх можна вимкнути через `channels.telegram.linkPreview: false`. + Попередні перегляди посилань увімкнені за замовчуванням і можуть бути вимкнені через `channels.telegram.linkPreview: false`. - Реєстрація меню команд Telegram виконується під час запуску через `setMyCommands`. + Реєстрація меню команд Telegram обробляється під час запуску за допомогою `setMyCommands`. - Стандартні параметри нативних команд: + Типові значення нативних команд: - `commands.native: "auto"` вмикає нативні команди для Telegram @@ -360,40 +361,40 @@ curl "https://api.telegram.org/bot/getUpdates" Правила: - - імена нормалізуються (прибирається початковий `/`, переводяться в нижній регістр) + - імена нормалізуються (видаляється початковий `/`, переводяться в нижній регістр) - допустимий шаблон: `a-z`, `0-9`, `_`, довжина `1..32` - користувацькі команди не можуть перевизначати нативні команди - - конфлікти/дублікати пропускаються й логуються + - конфлікти/дублікати пропускаються й записуються в журнал Примітки: - - користувацькі команди є лише пунктами меню; вони не реалізують поведінку автоматично - - команди Plugin/Skills можуть працювати під час введення, навіть якщо їх не показано в меню Telegram + - користувацькі команди є лише записами меню; вони не реалізують поведінку автоматично + - команди plugin/skill усе ще можуть працювати під час введення, навіть якщо їх не показано в меню Telegram - Якщо нативні команди вимкнено, вбудовані команди видаляються. Користувацькі команди або команди Plugin можуть усе ще реєструватися, якщо налаштовані. + Якщо нативні команди вимкнено, вбудовані команди видаляються. Користувацькі/plugin-команди все ще можуть реєструватися, якщо це налаштовано. - Типові збої налаштування: + Поширені помилки налаштування: - - `setMyCommands failed` з `BOT_COMMANDS_TOO_MUCH` означає, що меню Telegram усе ще перевищило ліміт після обрізання; зменште кількість команд Plugin/Skills/користувацьких команд або вимкніть `channels.telegram.commands.native`. - - Збій `deleteWebhook`, `deleteMyCommands` або `setMyCommands` з `404: Not Found`, коли прямі команди curl до Bot API працюють, може означати, що `channels.telegram.apiRoot` було встановлено на повну кінцеву точку `/bot`. `apiRoot` має бути лише коренем Bot API, а `openclaw doctor --fix` видаляє випадковий кінцевий `/bot`. - - `getMe returned 401` означає, що Telegram відхилив налаштований токен бота. Оновіть `botToken`, `tokenFile` або `TELEGRAM_BOT_TOKEN` поточним токеном BotFather; OpenClaw зупиняється до опитування, тому це не повідомляється як збій очищення Webhook. - - `setMyCommands failed` з мережевими помилками або помилками fetch зазвичай означає, що вихідні DNS/HTTPS до `api.telegram.org` заблоковані. + - `setMyCommands failed` з `BOT_COMMANDS_TOO_MUCH` означає, що меню Telegram усе ще переповнене після обрізання; зменште кількість plugin/skill/користувацьких команд або вимкніть `channels.telegram.commands.native`. + - Помилка `deleteWebhook`, `deleteMyCommands` або `setMyCommands` з `404: Not Found`, тоді як прямі команди curl до Bot API працюють, може означати, що `channels.telegram.apiRoot` було встановлено на повну кінцеву точку `/bot`. `apiRoot` має бути лише коренем Bot API, а `openclaw doctor --fix` видаляє випадковий кінцевий `/bot`. + - `getMe returned 401` означає, що Telegram відхилив налаштований токен бота. Оновіть `botToken`, `tokenFile` або `TELEGRAM_BOT_TOKEN` поточним токеном BotFather; OpenClaw зупиняється перед опитуванням, тому це не повідомляється як помилка очищення Webhook. + - `setMyCommands failed` з помилками мережі/fetch зазвичай означає, що вихідний DNS/HTTPS до `api.telegram.org` заблокований. - ### Команди сполучення пристроїв (Plugin `device-pair`) + ### Команди сполучення пристрою (plugin `device-pair`) - Коли встановлено Plugin `device-pair`: + Коли plugin `device-pair` встановлено: 1. `/pair` генерує код налаштування 2. вставте код у застосунок iOS - 3. `/pair pending` показує очікувані запити (зокрема роль/області дії) + 3. `/pair pending` показує список запитів, що очікують (включно з роллю/областями доступу) 4. схваліть запит: - `/pair approve ` для явного схвалення - - `/pair approve`, коли є лише один очікуваний запит + - `/pair approve`, коли є лише один запит, що очікує - `/pair approve latest` для найновішого - Код налаштування переносить короткоживучий bootstrap-токен. Вбудована bootstrap-передача залишає основний токен Node на `scopes: []`; будь-який переданий токен оператора лишається обмеженим до `operator.approvals`, `operator.read`, `operator.talk.secrets` і `operator.write`. Перевірки bootstrap-областей дії мають префікс ролі, тому цей список дозволеного оператора задовольняє лише запити оператора; неоператорським ролям усе ще потрібні області дії під власним префіксом ролі. + Код налаштування містить короткочасний bootstrap-токен. Вбудована передача bootstrap зберігає токен основного вузла на `scopes: []`; будь-який переданий токен оператора залишається обмеженим `operator.approvals`, `operator.read`, `operator.talk.secrets` і `operator.write`. Перевірки областей доступу bootstrap мають префікс ролі, тому цей список дозволів оператора задовольняє лише запити оператора; ролі, що не є операторськими, усе ще потребують областей доступу під власним префіксом ролі. - Якщо пристрій повторює спробу зі зміненими даними автентифікації (наприклад роль/області дії/публічний ключ), попередній очікуваний запит замінюється, а новий запит використовує інший `requestId`. Повторно виконайте `/pair pending` перед схваленням. + Якщо пристрій повторює спробу зі зміненими деталями автентифікації (наприклад, роль/області доступу/публічний ключ), попередній запит, що очікує, замінюється, а новий запит використовує інший `requestId`. Повторно виконайте `/pair pending` перед схваленням. Докладніше: [Сполучення](/uk/channels/pairing#pair-via-telegram-recommended-for-ios). @@ -442,7 +443,7 @@ curl "https://api.telegram.org/bot/getUpdates" Застаріле `capabilities: ["inlineButtons"]` зіставляється з `inlineButtons: "all"`. - Приклад дії з повідомленням: + Приклад дії повідомлення: ```json5 { @@ -465,36 +466,36 @@ curl "https://api.telegram.org/bot/getUpdates" - + Дії інструментів Telegram включають: - - `sendMessage` (`to`, `content`, optional `mediaUrl`, `replyToMessageId`, `messageThreadId`) + - `sendMessage` (`to`, `content`, необов’язково `mediaUrl`, `replyToMessageId`, `messageThreadId`) - `react` (`chatId`, `messageId`, `emoji`) - `deleteMessage` (`chatId`, `messageId`) - `editMessage` (`chatId`, `messageId`, `content`) - - `createForumTopic` (`chatId`, `name`, optional `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` (за замовчуванням: вимкнено) - Примітка: `edit` і `topic-create` наразі ввімкнено за замовчуванням, і вони не мають окремих перемикачів `channels.telegram.actions.*`. - Надсилання під час виконання використовують активний знімок конфігурації/секретів (запуск/перезавантаження), тому шляхи дій не виконують ad-hoc повторне розв’язання SecretRef для кожного надсилання. + Примітка: `edit` і `topic-create` наразі ввімкнені за замовчуванням і не мають окремих перемикачів `channels.telegram.actions.*`. + Надсилання під час виконання використовують активний знімок конфігурації/секретів (запуск/перезавантаження), тому шляхи дій не виконують спеціального повторного розв’язання SecretRef для кожного надсилання. Семантика видалення реакцій: [/tools/reactions](/uk/tools/reactions) - - Telegram підтримує явні теги потоків відповідей у згенерованому виводі: + + Telegram підтримує явні теги гілкування відповідей у згенерованому виводі: - - `[[reply_to_current]]` відповідає на повідомлення, яке запустило обробку - - `[[reply_to:]]` відповідає на конкретний ID повідомлення Telegram + - `[[reply_to_current]]` відповідає на повідомлення, що запустило обробку + - `[[reply_to:]]` відповідає на конкретний ідентифікатор повідомлення Telegram `channels.telegram.replyToMode` керує обробкою: @@ -502,29 +503,29 @@ curl "https://api.telegram.org/bot/getUpdates" - `first` - `all` - Коли потоки відповідей увімкнено і доступний оригінальний текст або підпис Telegram, OpenClaw автоматично включає фрагмент нативної цитати Telegram. Telegram обмежує нативний текст цитати 1024 кодовими одиницями UTF-16, тому довші повідомлення цитуються з початку й повертаються до звичайної відповіді, якщо Telegram відхиляє цитату. + Коли гілкування відповідей увімкнене й оригінальний текст або підпис Telegram доступний, OpenClaw автоматично включає нативний фрагмент цитати Telegram. Telegram обмежує нативний текст цитати 1024 кодовими одиницями UTF-16, тому довші повідомлення цитуються з початку й повертаються до звичайної відповіді, якщо Telegram відхиляє цитату. - Примітка: `off` вимикає неявні потоки відповідей. Явні теги `[[reply_to_*]]` усе одно враховуються. + Примітка: `off` вимикає неявне гілкування відповідей. Явні теги `[[reply_to_*]]` усе ще враховуються. - + Форумні супергрупи: - - ключі сеансів тем додають `:topic:` - - відповіді й індикатор набору спрямовуються в гілку теми - - шлях конфігурації теми: + - ключі сесій топіків додають `:topic:` + - відповіді й індикатор набору спрямовуються в гілку топіка + - шлях конфігурації топіка: `channels.telegram.groups..topics.` - Спеціальний випадок загальної теми (`threadId=1`): + Особливий випадок загального топіка (`threadId=1`): - - під час надсилання повідомлень опускається `message_thread_id` (Telegram відхиляє `sendMessage(...thread_id=1)`) - - дії набору все одно включають `message_thread_id` + - надсилання повідомлень пропускає `message_thread_id` (Telegram відхиляє `sendMessage(...thread_id=1)`) + - дії набору тексту все ще включають `message_thread_id` - Наслідування тем: записи тем успадковують налаштування групи, якщо їх не перевизначено (`requireMention`, `allowFrom`, `skills`, `systemPrompt`, `enabled`, `groupPolicy`). - `agentId` застосовується лише на рівні теми й не успадковується зі стандартних параметрів групи. + Успадкування топіків: записи топіків успадковують налаштування групи, якщо їх не перевизначено (`requireMention`, `allowFrom`, `skills`, `systemPrompt`, `enabled`, `groupPolicy`). + `agentId` застосовується лише до топіка й не успадковується з типових значень групи. - **Маршрутизація агентів за темами**: Кожна тема може маршрутизуватися до іншого агента через встановлення `agentId` у конфігурації теми. Це дає кожній темі власний ізольований робочий простір, пам’ять і сеанс. Приклад: + **Маршрутизація агентів для кожного топіка**: кожен топік може маршрутизуватися до іншого агента через встановлення `agentId` у конфігурації топіка. Це дає кожному топіку власний ізольований робочий простір, пам’ять і сесію. Приклад: ```json5 { @@ -544,28 +545,28 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - Після цього кожна тема має власний ключ сеансу: `agent:zu:telegram:group:-1001234567890:topic:3` + Тоді кожен топік має власний ключ сесії: `agent:zu:telegram:group:-1001234567890:topic:3` - **Постійне прив’язування тем ACP**: Теми форуму можуть закріплювати сеанси обв’язки ACP через типізовані прив’язування ACP верхнього рівня (`bindings[]` з `type: "acp"` і `match.channel: "telegram"`, `peer.kind: "group"` та ідентифікатором із кваліфікатором теми, як-от `-1001234567890:topic:42`). Наразі обмежено темами форумів у групах/супергрупах. Див. [Агенти ACP](/uk/tools/acp-agents). + **Постійна прив’язка ACP-топіка**: форумні топіки можуть закріплювати сесії стенда ACP через типізовані ACP-прив’язки верхнього рівня (`bindings[]` з `type: "acp"` і `match.channel: "telegram"`, `peer.kind: "group"` та ідентифікатором із кваліфікатором топіка, як-от `-1001234567890:topic:42`). Наразі область дії обмежена форумними топіками в групах/супергрупах. Див. [Агенти ACP](/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]]` у відповіді агента для примусового надсилання як голосової нотатки + - транскрипти вхідних голосових нотаток оформлюються як машинно згенерований, + ненадійний текст у контексті агента; виявлення згадок усе ще використовує сирий + транскрипт, тому voice-повідомлення з доступом через згадку продовжують працювати. - Приклад дії з повідомленням: + Приклад дії повідомлення: ```json5 { @@ -581,7 +582,7 @@ curl "https://api.telegram.org/bot/getUpdates" Telegram розрізняє відеофайли та відеонотатки. - Приклад дії з повідомленням: + Приклад дії повідомлення: ```json5 { @@ -599,9 +600,9 @@ curl "https://api.telegram.org/bot/getUpdates" Обробка вхідних стікерів: - - статичні WEBP: завантажуються й обробляються (placeholder ``) - - анімовані TGS: пропускаються - - відео WEBM: пропускаються + - статичний WEBP: завантажується й обробляється (заповнювач ``) + - анімований TGS: пропускається + - відео WEBM: пропускається Поля контексту стікера: @@ -615,9 +616,9 @@ curl "https://api.telegram.org/bot/getUpdates" - `~/.openclaw/telegram/sticker-cache.json` - Стікери описуються один раз (коли можливо) і кешуються, щоб зменшити кількість повторних викликів візуального аналізу. + Стікери описуються один раз (коли можливо) і кешуються, щоб зменшити повторні виклики vision. - Увімкніть дії зі стікерами: + Увімкнути дії зі стікерами: ```json5 { @@ -656,7 +657,7 @@ curl "https://api.telegram.org/bot/getUpdates" - Реакції Telegram надходять як оновлення `message_reaction` (окремо від payload повідомлень). + Реакції Telegram надходять як оновлення `message_reaction` (окремо від навантажень повідомлень). Коли ввімкнено, OpenClaw ставить у чергу системні події на кшталт: @@ -669,17 +670,17 @@ curl "https://api.telegram.org/bot/getUpdates" Примітки: - - `own` означає лише реакції користувачів на повідомлення, надіслані ботом (наскільки можливо через кеш надісланих повідомлень). + - `own` означає лише реакції користувача на повідомлення, надіслані ботом (у міру можливостей через кеш надісланих повідомлень). - Події реакцій усе одно дотримуються контролів доступу Telegram (`dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`); неавторизовані відправники відкидаються. - - Telegram не надає ідентифікатори тредів в оновленнях реакцій. - - групи без форуму спрямовуються до сесії групового чату - - форумні групи спрямовуються до сесії загальної теми групи (`:topic:1`), а не до точної початкової теми + - Telegram не надає ідентифікатори потоків в оновленнях реакцій. + - групи без форуму спрямовуються до сеансу групового чату + - форумні групи спрямовуються до сеансу загальної теми групи (`:topic:1`), а не до точної початкової теми - `allowed_updates` для polling/webhook автоматично включає `message_reaction`. + `allowed_updates` для polling/webhook автоматично містить `message_reaction`. - + `ackReaction` надсилає емодзі підтвердження, поки OpenClaw обробляє вхідне повідомлення. Порядок визначення: @@ -697,12 +698,12 @@ curl "https://api.telegram.org/bot/getUpdates" - Записи конфігурації каналу ввімкнені за замовчуванням (`configWrites !== false`). + Записи конфігурації каналу ввімкнено за замовчуванням (`configWrites !== false`). Записи, ініційовані Telegram, включають: - - події міграції груп (`migrate_to_chat_id`) для оновлення `channels.telegram.groups` - - `/config set` і `/config unset` (потребує ввімкнення команд) + - події міграції групи (`migrate_to_chat_id`) для оновлення `channels.telegram.groups` + - `/config set` і `/config unset` (потребує ввімкнення команди) Вимкнення: @@ -721,26 +722,26 @@ 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`). - Локальний слухач прив’язується до `127.0.0.1:8787`. Для публічного ingress або поставте reverse proxy перед локальним портом, або свідомо задайте `webhookHost: "0.0.0.0"`. + Локальний слухач прив’язується до `127.0.0.1:8787`. Для публічного входу або розмістіть reverse proxy перед локальним портом, або свідомо задайте `webhookHost: "0.0.0.0"`. - Режим webhook перевіряє захисти запиту, секретний токен Telegram і JSON-тіло перед поверненням `200` до Telegram. - Потім OpenClaw обробляє оновлення асинхронно через ті самі bot lanes для кожного чату/теми, що й long polling, тому повільні ходи агента не затримують delivery ACK Telegram. + Режим webhook перевіряє захисти запиту, секретний токен Telegram і JSON-тіло, перш ніж повернути `200` до Telegram. + Потім OpenClaw обробляє оновлення асинхронно через ті самі смуги бота для кожного чату/теми, що використовуються long polling, тому повільні ходи агента не затримують ACK доставки Telegram. - Типове значення `channels.telegram.textChunkLimit` — 4000. - - `channels.telegram.chunkMode="newline"` надає перевагу межам абзаців (порожнім рядкам) перед розбиттям за довжиною. - - `channels.telegram.mediaMaxMb` (типово 100) обмежує розмір вхідних і вихідних медіа Telegram. + - `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` вимикає. - - додатковий контекст відповіді/цитати/пересилання наразі передається як отриманий. - - allowlist Telegram передусім обмежують, хто може запускати агента, а не є повною межею редагування додаткового контексту. - - Керування історією DM: + - `channels.telegram.pollingStallThresholdMs` за замовчуванням дорівнює `120000`; налаштовуйте між `30000` і `600000` лише для хибнопозитивних перезапусків через зупинку polling. + - історія контексту групи використовує `channels.telegram.historyLimit` або `messages.groupChat.historyLimit` (за замовчуванням 50); `0` вимикає. + - додатковий контекст відповіді/цитати/пересилання наразі передається як отримано. + - allowlist Telegram переважно обмежують, хто може запускати агента, а не є повною межею редагування додаткового контексту. + - Елементи керування історією DM: - `channels.telegram.dmHistoryLimit` - `channels.telegram.dms[""].historyLimit` - - Конфігурація `channels.telegram.retry` застосовується до helper-ів надсилання Telegram (CLI/tools/actions) для відновлюваних вихідних помилок API. + - конфігурація `channels.telegram.retry` застосовується до допоміжних засобів надсилання Telegram (CLI/інструменти/дії) для відновлюваних помилок вихідного API. Ціль надсилання CLI може бути числовим ідентифікатором чату або іменем користувача: @@ -769,8 +770,8 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ Надсилання Telegram також підтримує: - `--presentation` з блоками `buttons` для inline-клавіатур, коли `channels.telegram.capabilities.inlineButtons` це дозволяє - - `--pin` або `--delivery '{"pin":true}'`, щоб запитати закріплену доставку, коли бот може закріплювати в цьому чаті - - `--force-document`, щоб надсилати вихідні зображення та GIF як документи замість стиснених фото або завантажень animated-media + - `--pin` або `--delivery '{"pin":true}'`, щоб запросити закріплену доставку, коли бот може закріплювати в цьому чаті + - `--force-document`, щоб надсилати вихідні зображення та GIF як документи замість стиснених фото або завантажень анімованих медіа Обмеження дій: @@ -780,36 +781,36 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ - Telegram підтримує підтвердження exec у DM затверджувачів і може необов’язково публікувати запити в початковому чаті або темі. Затверджувачі мають бути числовими ідентифікаторами користувачів Telegram. + Telegram підтримує підтвердження exec у DM підтверджувачів і може за бажанням публікувати запити у вихідному чаті або темі. Підтверджувачі мають бути числовими ідентифікаторами користувачів Telegram. Шлях конфігурації: - - `channels.telegram.execApprovals.enabled` (автоматично вмикається, коли можна визначити принаймні одного затверджувача) - - `channels.telegram.execApprovals.approvers` (резервно використовує числові ідентифікатори власників з `commands.ownerAllowFrom`) + - `channels.telegram.execApprovals.enabled` (автоматично вмикається, коли можна визначити принаймні одного підтверджувача) + - `channels.telegram.execApprovals.approvers` (резервно використовує числові ID власників із `commands.ownerAllowFrom`) - `channels.telegram.execApprovals.target`: `dm` (типово) | `channel` | `both` - `agentFilter`, `sessionFilter` - `channels.telegram.allowFrom`, `groupAllowFrom` і `defaultTo` керують тим, хто може говорити з ботом і куди він надсилає звичайні відповіді. Вони не роблять когось затверджувачем exec. Перша підтверджена DM-пара ініціалізує `commands.ownerAllowFrom`, коли власника команд ще немає, тому налаштування з одним власником усе одно працює без дублювання ідентифікаторів у `execApprovals.approvers`. + `channels.telegram.allowFrom`, `groupAllowFrom` і `defaultTo` керують тим, хто може спілкуватися з ботом і куди він надсилає звичайні відповіді. Вони не роблять когось підтверджувачем exec. Перше схвалене DM-сполучення ініціалізує `commands.ownerAllowFrom`, коли власника команд ще немає, тому налаштування з одним власником і далі працює без дублювання ID у `execApprovals.approvers`. - Доставка в канал показує текст команди в чаті; вмикайте `channel` або `both` лише в довірених групах/темах. Коли запит потрапляє у форумну тему, OpenClaw зберігає тему для запиту підтвердження та подальшої відповіді. Термін дії підтверджень exec за замовчуванням спливає через 30 хвилин. + Доставка в канал показує текст команди в чаті; вмикайте `channel` або `both` лише в довірених групах/темах. Коли запит потрапляє в тему форуму, OpenClaw зберігає тему для запиту підтвердження та подальшої відповіді. Підтвердження exec типово спливають через 30 хвилин. - Inline-кнопки підтвердження також потребують, щоб `channels.telegram.capabilities.inlineButtons` дозволяв цільову поверхню (`dm`, `group` або `all`). Ідентифікатори підтверджень із префіксом `plugin:` визначаються через підтвердження Plugin; інші спершу визначаються через підтвердження exec. + Кнопки вбудованого підтвердження також потребують, щоб `channels.telegram.capabilities.inlineButtons` дозволяв цільову поверхню (`dm`, `group` або `all`). ID підтверджень із префіксом `plugin:` обробляються через підтвердження plugin; інші спершу обробляються через підтвердження exec. Див. [Підтвердження exec](/uk/tools/exec-approvals). -## Керування відповідями на помилки +## Керування відповідями про помилки -Коли агент стикається з помилкою доставки або провайдера, Telegram може або відповісти текстом помилки, або приховати її. Цю поведінку контролюють два ключі конфігурації: +Коли агент стикається з помилкою доставки або провайдера, Telegram може або відповісти текстом помилки, або приховати її. Цю поведінку керують два ключі конфігурації: -| Ключ | Значення | Типово | Опис | -| ----------------------------------- | ----------------- | ------- | ------------------------------------------------------------------------------------------------- | -| `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` | Мінімальний час між відповідями про помилки в той самий чат. Запобігає спаму помилок під час збоїв. | -Підтримуються перевизначення для облікового запису, групи та теми (таке саме успадкування, як і для інших ключів конфігурації Telegram). +Підтримуються перевизначення для окремих облікових записів, груп і тем (з таким самим успадкуванням, як в інших ключів конфігурації Telegram). ```json5 { @@ -832,48 +833,48 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ - - Якщо `requireMention=false`, режим privacy Telegram має дозволяти повну видимість. + - Якщо `requireMention=false`, режим приватності Telegram має дозволяти повну видимість. - BotFather: `/setprivacy` -> Disable - потім видаліть і повторно додайте бота до групи - `openclaw channels status` попереджає, коли конфігурація очікує групові повідомлення без згадки. - - `openclaw channels status --probe` може перевіряти явні числові ідентифікатори груп; wildcard `"*"` не можна перевірити на членство. + - `openclaw channels status --probe` може перевіряти явні числові ID груп; wildcard `"*"` не можна перевірити на членство. - швидкий тест сесії: `/activation always`. - - коли існує `channels.telegram.groups`, групу має бути вказано (або включено `"*"`) + - коли існує `channels.telegram.groups`, група має бути в списку (або містити `"*"`) - перевірте членство бота в групі - - перегляньте логи: `openclaw logs --follow` для причин пропуску + - перегляньте журнали: `openclaw logs --follow` щодо причин пропуску - - авторизуйте свою ідентичність відправника (pairing та/або числовий `allowFrom`) - - авторизація команд усе одно застосовується, навіть коли політика групи — `open` - - `setMyCommands failed` з `BOT_COMMANDS_TOO_MUCH` означає, що native menu має забагато записів; зменште кількість команд Plugin/Skills/custom або вимкніть native menu - - `setMyCommands failed` з помилками network/fetch зазвичай вказує на проблеми доступності DNS/HTTPS до `api.telegram.org` + - авторизуйте ідентичність свого відправника (сполучення та/або числовий `allowFrom`) + - авторизація команд усе одно застосовується, навіть коли політика групи має значення `open` + - `setMyCommands failed` з `BOT_COMMANDS_TOO_MUCH` означає, що в нативному меню забагато записів; зменште кількість команд plugin/skill/користувацьких команд або вимкніть нативні меню + - `setMyCommands failed` із помилками network/fetch зазвичай вказує на проблеми доступності DNS/HTTPS до `api.telegram.org` - - `getMe returned 401` — це помилка автентифікації Telegram для налаштованого токена бота. - - Повторно скопіюйте або згенеруйте токен бота в BotFather, потім оновіть `channels.telegram.botToken`, `channels.telegram.tokenFile`, `channels.telegram.accounts..botToken` або `TELEGRAM_BOT_TOKEN` для типового облікового запису. - - `deleteWebhook 401 Unauthorized` під час запуску також є помилкою автентифікації; трактування цього як "webhook не існує" лише відклало б той самий збій через поганий токен до пізніших викликів API. + - `getMe returned 401` — це збій автентифікації Telegram для налаштованого токена бота. + - Заново скопіюйте або згенеруйте токен бота в BotFather, потім оновіть `channels.telegram.botToken`, `channels.telegram.tokenFile`, `channels.telegram.accounts..botToken` або `TELEGRAM_BOT_TOKEN` для типового облікового запису. + - `deleteWebhook 401 Unauthorized` під час запуску також є збоєм автентифікації; трактування цього як "webhook не існує" лише відклало б той самий збій через поганий токен до пізніших викликів API. - + - - Node 22+ + custom fetch/proxy може спричиняти негайну поведінку abort, якщо типи AbortSignal не збігаються. - - Деякі хости спершу визначають `api.telegram.org` як IPv6; зламаний IPv6 egress може спричиняти періодичні збої Telegram API. - - Якщо логи містять `TypeError: fetch failed` або `Network request for 'getUpdates' failed!`, OpenClaw тепер повторює їх як відновлювані мережеві помилки. - - Якщо логи містять `Polling stall detected`, OpenClaw перезапускає polling і перебудовує транспорт Telegram після 120 секунд без завершеної перевірки liveness long-poll за замовчуванням. - - Збільшуйте `channels.telegram.pollingStallThresholdMs` лише коли довготривалі виклики `getUpdates` справні, але ваш хост усе одно повідомляє про хибні перезапуски через зупинку polling. Постійні зупинки зазвичай вказують на проблеми proxy, DNS, IPv6 або TLS egress між хостом і `api.telegram.org`. - - На VPS-хостах із нестабільним прямим egress/TLS спрямовуйте виклики Telegram API через `channels.telegram.proxy`: + - Node 22+ + користувацький fetch/proxy може спричинити негайну поведінку abort, якщо типи AbortSignal не збігаються. + - Деякі хости спершу перетворюють `api.telegram.org` на IPv6; несправний вихідний IPv6-трафік може спричиняти періодичні збої API Telegram. + - Якщо журнали містять `TypeError: fetch failed` або `Network request for 'getUpdates' failed!`, OpenClaw тепер повторює ці помилки як відновлювані мережеві помилки. + - Якщо журнали містять `Polling stall detected`, OpenClaw перезапускає опитування й перебудовує транспорт Telegram після 120 секунд без завершеного long-poll liveness за замовчуванням. + - Збільшуйте `channels.telegram.pollingStallThresholdMs` лише тоді, коли довготривалі виклики `getUpdates` справні, але ваш хост усе одно повідомляє про хибні перезапуски через polling-stall. Постійні зависання зазвичай вказують на проблеми proxy, DNS, IPv6 або TLS egress між хостом і `api.telegram.org`. + - На VPS-хостах із нестабільним прямим egress/TLS маршрутизуйте виклики API Telegram через `channels.telegram.proxy`: ```yaml channels: @@ -881,8 +882,8 @@ channels: proxy: socks5://:@proxy-host:1080 ``` - - Node 22+ за замовчуванням використовує `autoSelectFamily=true` (крім WSL2) і `dnsResultOrder=ipv4first`. - - Якщо ваш хост — WSL2 або явно краще працює з поведінкою лише IPv4, примусово задайте вибір family: + - Node 22+ типово використовує `autoSelectFamily=true` (крім WSL2) і `dnsResultOrder=ipv4first`. + - Якщо ваш хост є WSL2 або явно працює краще з поведінкою лише IPv4, примусово задайте вибір family: ```yaml channels: @@ -891,11 +892,11 @@ channels: autoSelectFamily: false ``` - - Відповіді діапазону benchmark RFC 2544 (`198.18.0.0/15`) уже дозволені + - Відповіді з benchmark-діапазону RFC 2544 (`198.18.0.0/15`) уже дозволені для завантажень медіа Telegram за замовчуванням. Якщо довірений fake-IP або - прозорий proxy переписує `api.telegram.org` на іншу - приватну/внутрішню/спеціального використання адресу під час завантажень медіа, ви можете явно - ввімкнути обхід лише для Telegram: + transparent proxy переписує `api.telegram.org` на іншу + приватну/внутрішню/спеціального використання адресу під час завантажень медіа, ви можете + увімкнути обхід лише для Telegram: ```yaml channels: @@ -904,19 +905,19 @@ channels: dangerouslyAllowPrivateNetwork: true ``` - - Такий самий opt-in доступний для кожного облікового запису за шляхом + - Таке саме явне ввімкнення доступне для кожного облікового запису за адресою `channels.telegram.accounts..network.dangerouslyAllowPrivateNetwork`. - - Якщо ваш proxy визначає медіахости Telegram як `198.18.x.x`, спершу залиште - небезпечний прапорець вимкненим. Медіа Telegram уже дозволяє діапазон - benchmark RFC 2544 за замовчуванням. + - Якщо ваш proxy перетворює хости медіа Telegram на `198.18.x.x`, спершу залиште + небезпечний прапорець вимкненим. Медіа Telegram уже дозволяє benchmark-діапазон + RFC 2544 за замовчуванням. - `channels.telegram.network.dangerouslyAllowPrivateNetwork` послаблює захист - медіа Telegram від SSRF. Використовуйте його лише для довірених проксі-середовищ, - контрольованих оператором, як-от Clash, Mihomo або fake-IP маршрутизація Surge, - коли вони синтезують приватні або спеціального призначення відповіді поза - діапазоном бенчмарків RFC 2544. Залишайте його вимкненим для звичайного - доступу Telegram через публічний інтернет. + `channels.telegram.network.dangerouslyAllowPrivateNetwork` послаблює захист медіа Telegram + від SSRF. Використовуйте це лише в довірених проксі-середовищах під контролем + оператора, як-от Clash, Mihomo або маршрутизація fake-IP Surge, коли вони + синтезують приватні або спеціального використання відповіді поза діапазоном + тестування RFC 2544. Для звичайного публічного доступу Telegram через інтернет + залишайте це вимкненим. - Перевизначення середовища (тимчасові): @@ -939,18 +940,18 @@ dig +short api.telegram.org AAAA Основний довідник: [Довідник конфігурації - Telegram](/uk/gateway/config-channels#telegram). - + -- запуск/автентифікація: `enabled`, `botToken`, `tokenFile`, `accounts.*` (`tokenFile` має вказувати на звичайний файл; символічні посилання відхиляються) +- запуск/автентифікація: `enabled`, `botToken`, `tokenFile`, `accounts.*` (`tokenFile` має вказувати на звичайний файл; символьні посилання відхиляються) - контроль доступу: `dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`, `groups`, `groups.*.topics.*`, `bindings[]` верхнього рівня (`type: "acp"`) -- схвалення exec: `execApprovals`, `accounts.*.execApprovals` +- підтвердження виконання: `execApprovals`, `accounts.*.execApprovals` - команди/меню: `commands.native`, `commands.nativeSkills`, `customCommands` - потоки/відповіді: `replyToMode` - потокове передавання: `streaming` (попередній перегляд), `streaming.preview.toolProgress`, `blockStreaming` -- форматування/доставлення: `textChunkLimit`, `chunkMode`, `linkPreview`, `responsePrefix` +- форматування/доставка: `textChunkLimit`, `chunkMode`, `linkPreview`, `responsePrefix` - медіа/мережа: `mediaMaxMb`, `timeoutSeconds`, `pollingStallThresholdMs`, `retry`, `network.autoSelectFamily`, `network.dangerouslyAllowPrivateNetwork`, `proxy` - власний корінь API: `apiRoot` (лише корінь Bot API; не додавайте `/bot`) -- Webhook: `webhookUrl`, `webhookSecret`, `webhookPath`, `webhookHost` +- webhook: `webhookUrl`, `webhookSecret`, `webhookPath`, `webhookHost` - дії/можливості: `capabilities.inlineButtons`, `actions.sendMessage|editMessage|deleteMessage|reactions|sticker` - реакції: `reactionNotifications`, `reactionLevel` - помилки: `errorPolicy`, `errorCooldownMs` @@ -959,23 +960,23 @@ dig +short api.telegram.org AAAA -Пріоритет кількох облікових записів: коли налаштовано два або більше ID облікових записів, установіть `channels.telegram.defaultAccount` (або додайте `channels.telegram.accounts.default`), щоб зробити маршрутизацію за замовчуванням явною. Інакше OpenClaw повертається до першого нормалізованого ID облікового запису, а `openclaw doctor` попереджає. Іменовані облікові записи успадковують `channels.telegram.allowFrom` / `groupAllowFrom`, але не значення `accounts.default.*`. +Пріоритет кількох облікових записів: коли налаштовано два або більше ідентифікаторів облікових записів, задайте `channels.telegram.defaultAccount` (або додайте `channels.telegram.accounts.default`), щоб явно визначити типову маршрутизацію. Інакше OpenClaw повертається до першого нормалізованого ідентифікатора облікового запису, а `openclaw doctor` попереджає про це. Іменовані облікові записи успадковують `channels.telegram.allowFrom` / `groupAllowFrom`, але не значення `accounts.default.*`. ## Пов’язане - Сполучіть користувача Telegram із Gateway. + Сполучіть користувача Telegram із gateway. Поведінка списку дозволених груп і тем. - Маршрутизуйте вхідні повідомлення агентам. + Маршрутизуйте вхідні повідомлення до агентів. - Модель загроз і зміцнення захисту. + Модель загроз і посилення захисту. Зіставляйте групи й теми з агентами. diff --git a/docs/uk/ci.md b/docs/uk/ci.md index 3c961fae4..35530537e 100644 --- a/docs/uk/ci.md +++ b/docs/uk/ci.md @@ -1,142 +1,141 @@ --- read_when: - - Вам потрібно зрозуміти, чому завдання CI запустилося або не запустилося - - Ви налагоджуєте перевірки GitHub Actions, що не проходять -summary: Граф завдань CI, перевірки області дії та локальні еквіваленти команд -title: CI-конвеєр + - Потрібно зрозуміти, чому завдання CI запустилося або не запустилося + - Ви налагоджуєте перевірки GitHub Actions, що завершуються помилкою +summary: Граф завдань CI, перевірки за областю охоплення та локальні еквіваленти команд +title: Конвеєр CI x-i18n: - generated_at: "2026-04-29T05:38:08Z" + generated_at: "2026-04-29T05:57:09Z" model: gpt-5.5 provider: openai - source_hash: 07839136693d9bfa72da1bb24a2839e0b249882795fa939dbc79a35436572b01 + source_hash: 67d20b149b2b294646652ff412a8e1c611af812a33cc4b95acef6073370f7388 source_path: ci.md workflow: 16 --- -CI запускається під час кожного push до `main` і кожного pull request. Вона використовує розумне обмеження області, щоб пропускати дорогі завдання, коли змінено лише непов’язані ділянки. Ручні запуски `workflow_dispatch` навмисно оминають розумне обмеження області й розгортають повний звичайний граф CI для реліз-кандидатів або широкої валідації. Лінії prerelease для Plugin, призначені лише для релізу, залишаються вимкненими, якщо `Full Release Validation` не запускає CI з `full_release_validation=true`. +CI запускається під час кожного push до `main` і кожного pull request. Вона використовує розумне визначення області, щоб пропускати дорогі завдання, коли змінилися лише непов’язані ділянки. Ручні запуски `workflow_dispatch` навмисно обходять розумне визначення області та розгортають повний звичайний граф CI для реліз-кандидатів або широкої перевірки. Доріжки попередніх випусків плагінів лише для релізу залишаються вимкненими, якщо `Full Release Validation` не запускає CI з `full_release_validation=true`. -`Full Release Validation` — це ручний парасольковий workflow для "запустити все -перед релізом." Він приймає гілку, тег або повний commit SHA, запускає -ручний workflow `CI` з цією ціллю та запускає `OpenClaw Release Checks` -для перевірки встановлення, приймання пакета, наборів Docker для релізного шляху, live/E2E, -OpenWebUI, паритету QA Lab, Matrix і ліній Telegram. Він також може запускати -workflow після публікації `NPM Telegram Beta E2E`, коли надано специфікацію -опублікованого пакета. `release_profile=minimum|stable|full` керує шириною -live/provider, переданою в release checks: `minimum` залишає найшвидші -критично важливі для релізу лінії OpenAI/core, `stable` додає стабільний набір -provider/backend, а `full` запускає широку рекомендаційну матрицю provider/media. -Парасольковий workflow записує ідентифікатори запущених дочірніх запусків, а фінальне завдання -`Verify full validation` повторно перевіряє поточні результати дочірніх запусків і додає -таблиці найповільніших завдань для кожного дочірнього запуску. Якщо дочірній workflow перезапущено -і він став зеленим, перезапустіть лише батьківське завдання перевірки, щоб оновити результат -парасолькового workflow і підсумок часу. +`Full Release Validation` — це ручний парасольковий workflow для «запустити все +перед релізом». Він приймає гілку, тег або повний SHA коміту, запускає ручний +workflow `CI` із цією ціллю та запускає `OpenClaw Release Checks` для install smoke, +package acceptance, наборів Docker release-path, live/E2E, OpenWebUI, QA Lab parity, +Matrix і доріжок Telegram. Він також може запускати post-publish workflow +`NPM Telegram Beta E2E`, коли надано специфікацію опублікованого пакета. +`release_profile=minimum|stable|full` керує широтою live/provider, переданою до +перевірок релізу: `minimum` залишає найшвидші критичні для релізу доріжки +OpenAI/core, `stable` додає стабільний набір provider/backend, а `full` запускає +широку advisory-матрицю provider/media. Парасолька записує ідентифікатори +запущених дочірніх запусків, а фінальне завдання `Verify full validation` повторно +перевіряє поточні висновки дочірніх запусків і додає таблиці найповільніших завдань +для кожного дочірнього запуску. Якщо дочірній workflow перезапущено і він став +зеленим, перезапустіть лише батьківське завдання перевірки, щоб оновити результат +парасольки й підсумок часу. Для відновлення `Full Release Validation` і `OpenClaw Release Checks` обидва приймають `rerun_group`. Використовуйте `all` для реліз-кандидата, `ci` лише для -звичайного повного дочірнього CI, `release-checks` для кожного релізного дочірнього workflow -або вужчу релізну групу: `install-smoke`, `cross-os`, `live-e2e`, `package`, `qa`, -`qa-parity`, `qa-live` або `npm-telegram` у парасольковому workflow. Це утримує перезапуск -невдалого релізного бокса в межах після сфокусованого виправлення. +звичайного повного дочірнього CI, `release-checks` для кожного дочірнього релізного +workflow або вужчу релізну групу: `install-smoke`, `cross-os`, `live-e2e`, `package`, +`qa`, `qa-parity`, `qa-live` чи `npm-telegram` у парасольці. Це утримує перезапуск +невдалого релізного блока в межах після цілеспрямованого виправлення. Дочірній release live/E2E зберігає широке нативне покриття `pnpm test:live`, але -запускає його як іменовані shard (`native-live-src-agents`, -`native-live-src-gateway-core`, завдання з фільтрацією за provider -`native-live-src-gateway-profiles`, -`native-live-src-gateway-backends`, `native-live-test`, -`native-live-extensions-a-k`, `native-live-extensions-l-n`, +запускає його як іменовані шарди (`native-live-src-agents`, +`native-live-src-gateway-core`, відфільтровані за provider завдання +`native-live-src-gateway-profiles`, `native-live-src-gateway-backends`, +`native-live-test`, `native-live-extensions-a-k`, `native-live-extensions-l-n`, `native-live-extensions-openai`, `native-live-extensions-o-z-other`, -`native-live-extensions-xai`, розділені media shard для audio/video та -music shard з фільтрацією за provider) через `scripts/test-live-shard.mjs` -замість одного послідовного завдання. Це зберігає те саме покриття файлів, водночас роблячи повільні -збої live provider простішими для перезапуску й діагностики. Агреговані назви shard +`native-live-extensions-xai`, розділені media audio/video шарди та відфільтровані +за provider music шарди) через `scripts/test-live-shard.mjs` замість одного +послідовного завдання. Це зберігає те саме файлове покриття, водночас полегшуючи +перезапуск і діагностику повільних збоїв live provider. Агреговані назви шардів `native-live-extensions-o-z`, `native-live-extensions-media` і -`native-live-extensions-media-music` залишаються чинними для ручних -одноразових перезапусків. +`native-live-extensions-media-music` залишаються чинними для ручних одноразових +перезапусків. -Нативні live media shard запускаються в +Нативні live media шарди запускаються в `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04`, зібраному workflow -`Live Media Runner Image`. Цей образ попередньо встановлює `ffmpeg` і -`ffprobe`; media завдання лише перевіряють бінарні файли перед налаштуванням. Тримайте live набори -з підтримкою Docker на звичайних Blacksmith runner, бо контейнерні завдання — неправильне -місце для запуску вкладених Docker тестів. +`Live Media Runner Image`. Цей образ попередньо встановлює `ffmpeg` і `ffprobe`; +media-завдання лише перевіряють бінарні файли перед налаштуванням. Тримайте +Docker-backed live набори на звичайних раннерах Blacksmith, бо container jobs — +неправильне місце для запуску вкладених Docker-тестів. -Live model/backend shard з підтримкою Docker використовують окремий спільний -образ `ghcr.io/openclaw/openclaw-live-test:` для кожного вибраного коміту. Live -релізний workflow збирає й публікує цей образ один раз, після чого Docker live model, -gateway, CLI backend, ACP bind і Codex harness shard запускаються з -`OPENCLAW_SKIP_DOCKER_BUILD=1`. Якщо ці shard перебудовують повну source Docker -ціль незалежно, релізний запуск неправильно налаштований і марнуватиме загальний час -на дубльовані збірки образів. +Docker-backed шарди live model/backend використовують окремий спільний образ +`ghcr.io/openclaw/openclaw-live-test:` для кожного вибраного коміту. Workflow +live release збирає й публікує цей образ один раз, після чого шарди Docker live +model, gateway, CLI backend, ACP bind і Codex harness запускаються з +`OPENCLAW_SKIP_DOCKER_BUILD=1`. Якщо ці шарди незалежно перебудовують повну source +Docker target, релізний запуск налаштовано неправильно, і він марнуватиме wall clock +на дублікати збірок образів. -`OpenClaw Release Checks` використовує довірений workflow ref, щоб один раз розв’язати вибраний -ref у tarball `release-package-under-test`, а потім передає цей artifact -і в live/E2E Docker workflow релізного шляху, і в shard приймання пакета. -Це підтримує узгодженість байтів пакета між релізними боксами й уникає -повторного пакування того самого кандидата в кількох дочірніх завданнях. +`OpenClaw Release Checks` використовує довірений workflow ref, щоб один раз +розв’язати вибраний ref у tarball `release-package-under-test`, а потім передає цей +артефакт і до Docker workflow live/E2E release-path, і до шарда package acceptance. +Це зберігає байти пакета узгодженими між релізними блоками та уникає повторного +пакування того самого кандидата в кількох дочірніх завданнях. -`Package Acceptance` — це side-run workflow для валідації artifact пакета -без блокування релізного workflow. Він розв’язує одного кандидата з -опублікованої npm специфікації, довіреного `package_ref`, зібраного з вибраним -harness `workflow_ref`, HTTPS URL tarball із SHA-256 або artifact tarball -з іншого запуску GitHub Actions, завантажує його як `package-under-test`, а потім повторно використовує -планувальник Docker release/E2E із цим tarball замість повторного пакування -checkout workflow. Профілі охоплюють smoke, package, product, full і custom -вибори Docker ліній. Профіль `package` використовує offline покриття Plugin, щоб -валідація опублікованого пакета не залежала від доступності live ClawHub. Необов’язкова -лінія Telegram повторно використовує artifact -`package-under-test` у workflow `NPM Telegram Beta E2E`, зберігаючи шлях -опублікованої npm специфікації для самостійних запусків. +`Package Acceptance` — це side-run workflow для перевірки артефакту пакета без +блокування релізного workflow. Він розв’язує одного кандидата з опублікованої npm +специфікації, довіреного `package_ref`, зібраного з вибраним harness `workflow_ref`, +HTTPS URL tarball із SHA-256 або tarball-артефакту з іншого запуску GitHub Actions, +завантажує його як `package-under-test`, а потім повторно використовує Docker +release/E2E scheduler із цим tarball замість повторного пакування checkout workflow. +Профілі покривають smoke, package, product, full і custom вибори Docker-доріжок. +Профіль `package` використовує офлайн-покриття плагінів, щоб перевірка +опублікованого пакета не залежала від доступності live ClawHub. Необов’язкова +доріжка Telegram повторно використовує артефакт `package-under-test` у workflow +`NPM Telegram Beta E2E`, а шлях опублікованої npm специфікації зберігається для +самостійних запусків. ## Приймання пакета -Використовуйте `Package Acceptance`, коли питання звучить як "чи працює цей installable пакет OpenClaw -як продукт?" Це відрізняється від звичайної CI: звичайна CI перевіряє -дерево source, тоді як package acceptance перевіряє один tarball через той самий -Docker E2E harness, який користувачі виконують після встановлення або оновлення. +Використовуйте `Package Acceptance`, коли питання звучить так: «чи працює цей +встановлюваний пакет OpenClaw як продукт?» Це відрізняється від звичайної CI: +звичайна CI перевіряє дерево джерел, тоді як package acceptance перевіряє один +tarball через той самий Docker E2E harness, який користувачі проходять після +встановлення або оновлення. Workflow має чотири завдання: -1. `resolve_package` робить checkout `workflow_ref`, розв’язує одного кандидата пакета, +1. `resolve_package` виконує checkout `workflow_ref`, розв’язує одного кандидата пакета, записує `.artifacts/docker-e2e-package/openclaw-current.tgz`, записує - `.artifacts/docker-e2e-package/package-candidate.json`, завантажує обидва як artifact - `package-under-test` і виводить source, workflow ref, package - ref, версію, SHA-256 і профіль у підсумку кроку GitHub. + `.artifacts/docker-e2e-package/package-candidate.json`, завантажує обидва як + артефакт `package-under-test` і виводить source, workflow ref, package ref, + версію, SHA-256 і профіль у підсумок кроку GitHub. 2. `docker_acceptance` викликає `openclaw-live-and-e2e-checks-reusable.yml` з `ref=workflow_ref` і - `package_artifact_name=package-under-test`. Повторно використовуваний workflow завантажує - цей artifact, перевіряє inventory tarball, готує Docker образи package-digest - за потреби й запускає вибрані Docker лінії проти цього - пакета замість пакування checkout workflow. Коли профіль вибирає - кілька цільових `docker_lanes`, повторно використовуваний workflow готує пакет - і спільні образи один раз, а потім розгортає ці лінії як паралельні цільові Docker - завдання з унікальними artifact. -3. `package_telegram` необов’язково викликає `NPM Telegram Beta E2E`. Він запускається, коли - `telegram_mode` не `none`, і встановлює той самий artifact `package-under-test`, - коли Package Acceptance розв’язав його; самостійний запуск Telegram - усе ще може встановити опубліковану npm специфікацію. + `package_artifact_name=package-under-test`. Повторно використовуваний workflow + завантажує цей артефакт, перевіряє інвентар tarball, за потреби готує Docker-образи + package-digest і запускає вибрані Docker-доріжки проти цього пакета замість + пакування checkout workflow. Коли профіль вибирає кілька цільових `docker_lanes`, + повторно використовуваний workflow готує пакет і спільні образи один раз, а потім + розгортає ці доріжки як паралельні цільові Docker-завдання з унікальними артефактами. +3. `package_telegram` необов’язково викликає `NPM Telegram Beta E2E`. Він запускається, + коли `telegram_mode` не дорівнює `none`, і встановлює той самий артефакт + `package-under-test`, коли Package Acceptance розв’язав його; самостійний запуск + Telegram все ще може встановити опубліковану npm специфікацію. 4. `summary` провалює workflow, якщо розв’язання пакета, Docker acceptance або - необов’язкова лінія Telegram завершилися невдало. + необов’язкова доріжка Telegram завершилися невдало. Джерела кандидатів: -- `source=npm`: приймає лише `openclaw@beta`, `openclaw@latest` або точну - релізну версію OpenClaw, наприклад `openclaw@2026.4.27-beta.2`. Використовуйте це для +- `source=npm`: приймає лише `openclaw@beta`, `openclaw@latest` або точну версію + релізу OpenClaw, наприклад `openclaw@2026.4.27-beta.2`. Використовуйте це для acceptance опублікованих beta/stable. -- `source=ref`: пакує довірену гілку, тег або повний commit SHA `package_ref`. - Resolver отримує гілки/теги OpenClaw, перевіряє, що вибраний коміт - досяжний з історії гілок репозиторію або релізного тегу, встановлює залежності в - від’єднаному worktree і пакує його за допомогою `scripts/package-openclaw-for-docker.mjs`. +- `source=ref`: пакує довірену гілку, тег або повний SHA коміту `package_ref`. + Resolver отримує гілки/теги OpenClaw, перевіряє, що вибраний коміт досяжний з + історії гілок репозиторію або релізного тегу, встановлює залежності в detached + worktree і пакує його через `scripts/package-openclaw-for-docker.mjs`. - `source=url`: завантажує HTTPS `.tgz`; `package_sha256` є обов’язковим. -- `source=artifact`: завантажує один `.tgz` з `artifact_run_id` і - `artifact_name`; `package_sha256` необов’язковий, але його варто надати для - зовнішньо поширених artifact. +- `source=artifact`: завантажує один `.tgz` з `artifact_run_id` і `artifact_name`; + `package_sha256` необов’язковий, але його варто надати для зовнішньо поширених + артефактів. -Тримайте `workflow_ref` і `package_ref` окремо. `workflow_ref` — це довірений -код workflow/harness, який запускає тест. `package_ref` — це source commit, -який пакується, коли `source=ref`. Це дає змогу поточному test harness перевіряти -старіші довірені source commits без запуску старої логіки workflow. +Тримайте `workflow_ref` і `package_ref` окремо. `workflow_ref` — це довірений код +workflow/harness, який запускає тест. `package_ref` — це source-коміт, який пакується, +коли `source=ref`. Це дає змогу поточному test harness перевіряти старіші довірені +source-коміти без запуску старої логіки workflow. -Профілі відповідають Docker покриттю: +Профілі зіставляються з Docker-покриттям: - `smoke`: `npm-onboard-channel-agent`, `gateway-network`, `config-reload` - `package`: `npm-onboard-channel-agent`, `doctor-switch`, @@ -144,37 +143,37 @@ Workflow має чотири завдання: `plugin-update` - `product`: `package` плюс `mcp-channels`, `cron-mcp-cleanup`, `openai-web-search-minimal`, `openwebui` -- `full`: повні Docker chunks релізного шляху з OpenWebUI +- `full`: повні chunks Docker release-path з OpenWebUI - `custom`: точні `docker_lanes`; обов’язково, коли `suite_profile=custom` Release checks викликають Package Acceptance з `source=ref`, `package_ref=`, `workflow_ref=`, `suite_profile=custom`, `docker_lanes='bundled-channel-deps-compat plugins-offline'` і -`telegram_mode=mock-openai`. Docker chunks релізного шляху -покривають перетин ліній package/update/plugin, тоді як Package -Acceptance зберігає artifact-native доказ bundled-channel compat, offline Plugin і -Telegram проти того самого розв’язаного package tarball. -Cross-OS release checks усе ще покривають специфічні для ОС onboarding, installer і -platform behavior; валідацію продукту package/update слід починати з Package -Acceptance. Windows packaged і installer fresh лінії також перевіряють, що -встановлений пакет може імпортувати browser-control override з необробленого абсолютного +`telegram_mode=mock-openai`. Docker chunks release-path покривають перетин +доріжок package/update/plugin, тоді як Package Acceptance зберігає artifact-native +доказ bundled-channel compat, offline plugin і Telegram проти того самого розв’язаного +tarball пакета. +Cross-OS release checks усе ще покривають OS-specific onboarding, installer і +platform behavior; перевірку product для package/update слід починати з Package +Acceptance. Windows packaged і installer fresh доріжки також перевіряють, що +встановлений пакет може імпортувати browser-control override із raw absolute Windows path. -Package Acceptance має обмежені вікна сумісності зі спадщиною для вже -опублікованих пакетів. Пакети до `2026.4.25` включно, зокрема `2026.4.25-beta.*`, -можуть використовувати compatibility path для відомих private QA entries у -`dist/postinstall-inventory.json`, які вказують на файли, пропущені в tarball, -`doctor-switch` може пропустити підвипадок persistence `gateway install --wrapper`, -коли пакет не expose цей flag, `update-channel-switch` може prune -відсутні `pnpm.patchedDependencies` з fake git fixture, похідної від tarball, і -може log відсутній persisted `update.channel`, plugin smokes можуть читати legacy -locations install-record або приймати відсутність marketplace install-record -persistence, а `plugin-update` може дозволити міграцію config metadata, водночас усе ще -вимагаючи, щоб install record і поведінка no-reinstall залишалися незмінними. Опублікований -пакет `2026.4.26` також може попереджати про локальні файли штампа build metadata, -які вже були shipped. Пізніші пакети мають задовольняти сучасні contracts; ті самі -умови завершуються помилкою замість warning або skip. +Package Acceptance має обмежені вікна legacy-compatibility для вже опублікованих +пакетів. Пакети до `2026.4.25` включно, зокрема `2026.4.25-beta.*`, можуть +використовувати compatibility path для відомих приватних QA записів у +`dist/postinstall-inventory.json`, які вказують на файли, пропущені в tarball; +`doctor-switch` може пропускати підвипадок збереження `gateway install --wrapper`, +коли пакет не надає цей прапорець; `update-channel-switch` може обрізати відсутні +`pnpm.patchedDependencies` із tarball-derived fake git fixture і може логувати +відсутній збережений `update.channel`; plugin smokes можуть читати legacy locations +install-record або приймати відсутність persistence marketplace install-record; а +`plugin-update` може дозволяти міграцію metadata config, водночас усе ще вимагаючи, +щоб install record і поведінка no-reinstall залишалися незмінними. Опублікований +пакет `2026.4.26` також може попереджати про файли local build metadata stamp, які +вже були відвантажені. Пізніші пакети мають задовольняти сучасні контракти; ті самі +умови завершуються помилкою замість попередження або пропуску. Приклади: @@ -217,53 +216,53 @@ gh workflow run package-acceptance.yml \ -f docker_lanes='install-e2e plugin-update' ``` -Під час налагодження невдалого запуску package acceptance починайте з підсумку `resolve_package`, -щоб підтвердити source пакета, версію та SHA-256. Потім перевірте -дочірній запуск `docker_acceptance` і його Docker artifact: +Під час налагодження невдалого запуску package acceptance починайте з підсумку +`resolve_package`, щоб підтвердити source пакета, версію та SHA-256. Потім перевірте +дочірній запуск `docker_acceptance` і його Docker-артефакти: `.artifacts/docker-tests/**/summary.json`, `failures.json`, lane logs, phase -timings і rerun commands. Надавайте перевагу перезапуску невдалого package profile або -точних Docker lanes замість перезапуску повної release validation. +timings і rerun commands. Віддавайте перевагу перезапуску невдалого package profile +або точних Docker lanes замість повторного запуску full release validation. -QA Lab має окремі CI-лінії поза основним workflow зі smart-scoped областю. Workflow -`Parity gate` запускається для відповідних змін у PR і вручну; він -збирає приватне QA-середовище виконання та порівнює агентні пакети mock GPT-5.5 і Opus 4.6. -Workflow `QA-Lab - All Lanes` запускається щоночі на `main` і вручну; він -розгалужує mock parity gate, live-лінію Matrix, а також live-лінії -Telegram і Discord як паралельні jobs. Live jobs використовують середовище -`qa-live-shared`, а Telegram/Discord використовують оренди Convex. Release +QA Lab має окремі CI-лінії поза основним smart-scoped workflow. Workflow +`Parity gate` запускається для відповідних змін у PR і ручного dispatch; він +збирає приватний QA runtime і порівнює mock GPT-5.5 та Opus 4.6 +агентні пакети. Workflow `QA-Lab - All Lanes` запускається щоночі на `main` і за +ручним dispatch; він розгалужує mock parity gate, live-лінію Matrix, а також live +лінії Telegram і Discord як паралельні завдання. Live-завдання використовують +середовище `qa-live-shared`, а Telegram/Discord використовують оренди Convex. Release checks запускають live-лінії транспорту Matrix і Telegram з детермінованим mock -provider і mock-кваліфікованими моделями (`mock-openai/gpt-5.5` і +провайдером і mock-кваліфікованими моделями (`mock-openai/gpt-5.5` і `mock-openai/gpt-5.5-alt`), щоб контракт каналу був ізольований від затримки live-моделі -та звичайного запуску provider plugin. Live transport Gateway також -вимикає пошук памʼяті, оскільки QA parity окремо покриває поведінку памʼяті; +та звичайного запуску provider-plugin. Live transport gateway також +вимикає пошук у пам’яті, оскільки QA parity окремо покриває поведінку пам’яті; підключення провайдерів покривається окремими наборами live model, native provider і Docker provider. Matrix використовує `--profile fast` для запланованих і release gates, -додаючи `--fail-fast` лише тоді, коли checked-out CLI це підтримує. Типове значення CLI -і ручне введення workflow залишаються `all`; ручний dispatch `matrix_profile=all` -завжди розбиває повне покриття Matrix на jobs `transport`, `media`, +додаючи `--fail-fast` лише коли checked-out CLI це підтримує. Значення CLI за замовчуванням +і ручний workflow input залишаються `all`; ручний dispatch `matrix_profile=all` +завжди шардить повне покриття Matrix на завдання `transport`, `media`, `e2ee-smoke`, `e2ee-deep` і `e2ee-cli`. `OpenClaw Release Checks` також -запускає release-критичні лінії QA Lab перед схваленням релізу; його QA parity -gate запускає кандидатний і базовий пакети як паралельні lane jobs, потім завантажує -обидва артефакти в невеликий report job для фінального порівняння parity. -Не ставте шлях landing для PR за `Parity gate`, якщо зміна насправді не -торкається QA runtime, parity model-pack або поверхні, якою володіє parity workflow. -Для звичайних виправлень каналів, конфігурації, документації або unit tests вважайте це необовʼязковим -сигналом і натомість дотримуйтеся scoped CI/check evidence. +запускає критичні для релізу лінії QA Lab перед затвердженням релізу; його QA parity +gate запускає candidate і baseline packs як паралельні lane jobs, а потім завантажує +обидва артефакти в невелике report job для фінального parity comparison. +Не ставте шлях landing для PR за `Parity gate`, якщо зміна фактично не +зачіпає QA runtime, model-pack parity або поверхню, якою володіє parity workflow. +Для звичайних виправлень каналів, конфігурації, документації або unit-тестів вважайте це optional +signal і дотримуйтеся scoped CI/check evidence. -Workflow `Duplicate PRs After Merge` — це ручний workflow для maintainer після -land для очищення дублікатів. Типово він працює як dry-run і закриває лише явно +Workflow `Duplicate PRs After Merge` — це ручний workflow для maintainer +для очищення дублікатів після land. За замовчуванням він працює в dry-run і закриває лише явно перелічені PR, коли `apply=true`. Перед зміною GitHub він перевіряє, що -landed PR змерджено і що кожен дублікат має або спільне referenced issue, -або перетин змінених hunks. +landed PR змерджено і що кожен дублікат має або спільну referenced issue, +або перетин змінених hunk. -Workflow `CodeQL` навмисно є вузьким security scanner першого проходу, -а не повним скануванням репозиторію. Щоденні та ручні запуски сканують Actions workflow code -плюс найризикованіші поверхні JavaScript/TypeScript auth, secrets, sandbox, Cron і -Gateway за допомогою high-precision security queries. Job -channel-runtime-boundary окремо сканує контракти core channel implementation -плюс channel Plugin runtime, Gateway, Plugin SDK, secrets і +Workflow `CodeQL` навмисно є вузьким сканером безпеки першого проходу, +а не повним sweep репозиторію. Щоденні та ручні запуски сканують код Actions workflow +плюс найризикованіші JavaScript/TypeScript поверхні auth, secrets, sandbox, cron і +gateway з high-precision security queries. Завдання +channel-runtime-boundary окремо сканує core channel implementation +contracts плюс channel plugin runtime, gateway, Plugin SDK, secrets і audit touchpoints у категорії `/codeql-critical-security/channel-runtime-boundary`, -щоб security signal каналів міг масштабуватися без розширення базової +щоб сигнал безпеки каналів міг масштабуватися без розширення базової категорії JS/TS. Workflow `CodeQL Android Critical Security` — це запланований Android @@ -275,59 +274,60 @@ Workflow `CodeQL macOS Critical Security` — це щотижневий/ручн security shard. Він вручну збирає macOS app для CodeQL на Blacksmith macOS, відфільтровує результати збірки залежностей із завантаженого SARIF і завантажує результати в категорію `/codeql-critical-security/macos`. Тримайте його поза щоденним -типовим workflow, оскільки збірка macOS домінує за часом виконання навіть коли вона чиста. +default workflow, оскільки macOS build домінує за runtime навіть коли все чисто. -Робочий процес `CodeQL Critical Quality` є відповідним несек’юріті-шардом. Він -запускає лише запити якості JavaScript/TypeScript із рівнем серйозності error, -не пов’язані з безпекою, для вузьких цінних поверхонь на меншому Blacksmith Linux runner. Його -базове завдання сканує ті самі поверхні auth, secrets, sandbox, cron і gateway, -що й робочий процес безпеки. Завдання config-boundary -сканує схему конфігурації, міграцію, нормалізацію та контракти IO в межах -окремої категорії `/codeql-critical-quality/config-boundary`. Завдання -gateway-runtime-boundary сканує схеми протоколу gateway і контракти серверних методів -у межах окремої -категорії `/codeql-critical-quality/gateway-runtime-boundary`. Завдання -channel-runtime-boundary сканує контракти реалізації основних каналів у межах -окремої категорії `/codeql-critical-quality/channel-runtime-boundary`. Завдання -agent-runtime-boundary сканує виконання команд, диспетчеризацію моделей/провайдерів, -диспетчеризацію та черги автовідповідей, а також runtime-контракти control-plane ACP у межах -окремої категорії `/codeql-critical-quality/agent-runtime-boundary`. Завдання -ui-control-plane сканує початкове завантаження Control UI, локальне збереження, потоки керування gateway -і runtime-контракти control-plane завдань у межах окремої +Workflow `CodeQL Critical Quality` — це відповідний non-security shard. Він +запускає лише error-severity, non-security JavaScript/TypeScript quality queries +на вузьких high-value surfaces на меншому Blacksmith Linux runner. Його +завдання core-auth-secrets сканує код auth, secrets, sandbox, cron і gateway security +boundary в окремій категорії `/codeql-critical-quality/core-auth-secrets`. +Завдання config-boundary +сканує config schema, migration, normalization і IO contracts в окремій +категорії `/codeql-critical-quality/config-boundary`. Завдання +gateway-runtime-boundary сканує gateway protocol schemas і server method +contracts в окремій категорії +`/codeql-critical-quality/gateway-runtime-boundary`. Завдання +channel-runtime-boundary сканує core channel implementation contracts в +окремій категорії `/codeql-critical-quality/channel-runtime-boundary`. Завдання +agent-runtime-boundary сканує command execution, model/provider dispatch, +auto-reply dispatch і queues, а також ACP control-plane runtime contracts в +окремій категорії `/codeql-critical-quality/agent-runtime-boundary`. Завдання +ui-control-plane сканує Control UI bootstrap, local persistence, gateway +control flows і task control-plane runtime contracts в окремій категорії `/codeql-critical-quality/ui-control-plane`. Завдання -web-media-runtime-boundary сканує основні runtime-контракти веботримання/пошуку, media IO, -розуміння медіа, генерації зображень і генерації медіа в межах -окремої категорії `/codeql-critical-quality/web-media-runtime-boundary`. Завдання -plugin-boundary сканує контракти завантажувача, реєстру, публічної поверхні та точок входу Plugin SDK -у межах окремої категорії `/codeql-critical-quality/plugin-boundary`. -Тримайте цей робочий процес окремо від безпеки, щоб знахідки якості можна було -планувати, вимірювати, вимикати або розширювати без розмивання сигналу безпеки. -Розширення CodeQL для Swift, Python і вбудованих Plugin слід додавати назад як -обмежену або шардовану подальшу роботу лише після того, як вузькі профілі матимуть стабільний -runtime і сигнал. +web-media-runtime-boundary сканує core web fetch/search, media IO, media +understanding, image-generation і media-generation runtime contracts в +окремій категорії `/codeql-critical-quality/web-media-runtime-boundary`. Завдання +plugin-boundary сканує loader, registry, public-surface і Plugin SDK +entrypoint contracts в окремій категорії `/codeql-critical-quality/plugin-boundary`. +Тримайте workflow окремо від security, щоб quality findings можна було +планувати, вимірювати, вимикати або розширювати без затінення security signal. +Розширення CodeQL для Swift, Python і bundled-plugin слід додавати назад як +scoped або sharded follow-up work лише після того, як вузькі профілі матимуть стабільні +runtime і signal. -Робочий процес `Docs Agent` — це подієво-керована смуга обслуговування Codex для підтримання -наявної документації узгодженою з нещодавно внесеними змінами. Він не має чистого розкладу: успішний -CI-запуск після push не від бота на `main` може його запустити, а ручний dispatch може -запустити його напряму. Виклики workflow-run пропускаються, коли `main` уже змістився далі або коли -інший не пропущений запуск Docs Agent було створено за останню годину. Коли він працює, він -переглядає діапазон комітів від попереднього не пропущеного source SHA Docs Agent до -поточного `main`, тож один погодинний запуск може покрити всі зміни main, накопичені від -останнього проходу документації. +Workflow `Docs Agent` — це event-driven Codex maintenance lane для підтримання +наявної документації узгодженою з нещодавно залендованими змінами. Він не має pure schedule: +успішний non-bot push CI run на `main` може його запустити, а manual dispatch може +запустити його напряму. Workflow-run invocations пропускаються, коли `main` зсунувся вперед або коли +інший non-skipped Docs Agent run був створений протягом останньої години. Коли він запускається, він +переглядає commit range від попереднього non-skipped Docs Agent source SHA до +поточного `main`, тож один погодинний run може покрити всі main changes, накопичені з +останнього docs pass. -Робочий процес `Test Performance Agent` — це подієво-керована смуга обслуговування Codex -для повільних тестів. Він не має чистого розкладу: успішний CI-запуск після push не від бота на -`main` може його запустити, але він пропускається, якщо інший виклик workflow-run уже -виконувався або виконується цього UTC-дня. Ручний dispatch обходить цей щоденний -обмежувач активності. Смуга створює згрупований звіт продуктивності Vitest для повного набору, -дозволяє Codex вносити лише невеликі виправлення продуктивності тестів зі збереженням покриття замість широких -рефакторингів, потім повторно запускає звіт повного набору й відхиляє зміни, які зменшують -базову кількість успішних тестів. Якщо в базовому стані є тести з помилками, Codex може виправляти -лише очевидні збої, а звіт повного набору після агента має пройти перед тим, -як щось буде закомічено. Коли `main` просувається до того, як push бота потрапить у репозиторій, смуга -робить rebase перевіреного патча, повторно запускає `pnpm check:changed` і повторює push; -конфліктні застарілі патчі пропускаються. Вона використовує GitHub-hosted Ubuntu, щоб дія Codex -могла зберігати ту саму safety posture drop-sudo, що й docs agent. +Workflow `Test Performance Agent` — це event-driven Codex maintenance lane +для повільних тестів. Він не має pure schedule: успішний non-bot push CI run на +`main` може його запустити, але він пропускається, якщо інший workflow-run invocation вже +запускався або виконується цього UTC дня. Manual dispatch обходить цей daily activity +gate. Лінія будує full-suite grouped Vitest performance report, дозволяє Codex +вносити лише невеликі coverage-preserving test performance fixes замість broad +refactors, потім повторно запускає full-suite report і відхиляє зміни, які зменшують +passing baseline test count. Якщо baseline має failing tests, Codex може виправити +лише очевидні failures, а after-agent full-suite report має пройти перед +будь-яким commit. Коли `main` просувається до того, як bot push буде залендовано, лінія +ребейзить validated patch, повторно запускає `pnpm check:changed` і повторює push; +conflicting stale patches пропускаються. Вона використовує GitHub-hosted Ubuntu, щоб Codex +action міг зберегти ту саму drop-sudo safety posture, що й docs agent. ```bash gh workflow run duplicate-after-merge.yml \ @@ -340,30 +340,39 @@ gh workflow run duplicate-after-merge.yml \ | Завдання | Призначення | Коли запускається | | -------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- | -| `preflight` | Виявляє зміни лише в документації, змінені області, змінені plugins і будує CI-маніфест | Завжди для push і PR не в draft | -| `security-scm-fast` | Виявлення приватних ключів і аудит workflow через `zizmor` | Завжди для push і PR не в draft | -| `security-dependency-audit` | Аудит production lockfile без залежностей за advisories npm | Завжди для push і PR не в draft | -| `security-fast` | Обов’язковий агрегат для швидких завдань безпеки | Завжди для push і PR не в draft | -| `build-artifacts` | Збірка `dist/`, Control UI, перевірки built-artifact і повторно використовувані downstream-артефакти | Зміни, релевантні Node | -| `checks-fast-core` | Швидкі Linux-смуги коректності, як-от перевірки bundled/plugin-contract/protocol | Зміни, релевантні Node | -| `checks-fast-contracts-channels` | Шардовані перевірки контрактів каналів зі стабільним агрегованим результатом перевірки | Зміни, релевантні Node | -| `checks-node-extensions` | Повні шарди тестів вбудованих Plugin у всьому наборі extension | Зміни, релевантні Node | -| `checks-node-core-test` | Шарди основних тестів Node, без смуг каналів, bundled, contract і extension | Зміни, релевантні Node | -| `check` | Шардований еквівалент основного локального gate: prod types, lint, guards, test types і strict smoke | Зміни, релевантні Node | -| `check-additional` | Шарди архітектури, boundary, guards extension-surface, package-boundary і gateway-watch | Зміни, релевантні Node | -| `build-smoke` | Smoke-тести зібраного CLI і smoke startup-memory | Зміни, релевантні Node | -| `checks` | Перевіряльник для тестів каналів built-artifact | Зміни, релевантні Node | -| `checks-node-compat-node22` | Смуга збірки й smoke для сумісності Node 22 | Ручний CI dispatch для релізів | -| `plugin-prerelease-suite` | Агрегат для prerelease статичних перевірок plugin і Docker product lanes | Дочірній Full Release Validation CI | -| `check-docs` | Форматування документації, lint і перевірки broken-link | Документацію змінено | -| `skills-python` | Ruff + pytest для Skills на базі Python | Зміни, релевантні Python-skill | -| `checks-windows` | Специфічні для Windows тести процесів/шляхів плюс спільні регресії runtime import specifier | Зміни, релевантні Windows | -| `macos-node` | Смуга тестів TypeScript для macOS із використанням спільних built artifacts | Зміни, релевантні macOS | -| `macos-swift` | Swift lint, збірка й тести для застосунку macOS | Зміни, релевантні macOS | -| `android` | Unit-тести Android для обох flavor плюс одна debug APK збірка | Зміни, релевантні Android | -| `test-performance-agent` | Щоденна оптимізація повільних тестів Codex після довіреної активності | Успіх Main CI або ручний dispatch | +| `preflight` | Виявляє docs-only changes, changed scopes, changed extensions і будує CI manifest | Завжди на non-draft pushes і PRs | +| `security-scm-fast` | Виявлення приватних ключів і аудит workflow через `zizmor` | Завжди на non-draft pushes і PRs | +| `security-dependency-audit` | Dependency-free production lockfile audit against npm advisories | Завжди на non-draft pushes і PRs | +| `security-fast` | Required aggregate для fast security jobs | Завжди на non-draft pushes і PRs | +| `build-artifacts` | Збирає `dist/`, Control UI, built-artifact checks і reusable downstream artifacts | Node-relevant changes | +| `checks-fast-core` | Fast Linux correctness lanes, як-от bundled/plugin-contract/protocol checks | Node-relevant changes | +| `checks-fast-contracts-channels` | Sharded channel contract checks зі stable aggregate check result | Node-relevant changes | +| `checks-node-extensions` | Full bundled-plugin test shards across the extension suite | Node-relevant changes | +| `checks-node-core-test` | Core Node test shards, за винятком channel, bundled, contract і extension lanes | Node-relevant changes | +| `check` | Sharded main local gate equivalent: prod types, lint, guards, test types і strict smoke | Node-relevant changes | +| `check-additional` | Architecture, boundary, extension-surface guards, package-boundary і gateway-watch shards | Node-relevant changes | +| `build-smoke` | Built-CLI smoke tests і startup-memory smoke | Node-relevant changes | +| `checks` | Verifier для built-artifact channel tests | Node-relevant changes | +| `checks-node-compat-node22` | Node 22 compatibility build і smoke lane | Manual CI dispatch для releases | +| `plugin-prerelease-suite` | Aggregate для plugin prerelease static checks і Docker product lanes | Full Release Validation CI child | +| `check-docs` | Docs formatting, lint і broken-link checks | Docs changed | +| `skills-python` | Ruff + pytest для Python-backed skills | Python-skill-relevant changes | +| `checks-windows` | Windows-specific process/path tests plus shared runtime import specifier regressions | Windows-relevant changes | +| `macos-node` | macOS TypeScript test lane із використанням shared built artifacts | macOS-relevant changes | +| `macos-swift` | Swift lint, build і tests для macOS app | macOS-relevant changes | +| `android` | Android unit tests для обох flavors plus one debug APK build | Android-relevant changes | +| `test-performance-agent` | Daily Codex slow-test optimization after trusted activity | Main CI success або manual dispatch | -Ручні запуски CI виконують той самий граф завдань, що й звичайний CI, але примусово вмикають кожну scoped lane: Linux Node shards, bundled-plugin shards, channel contracts, сумісність із Node 22, `check`, `check-additional`, build smoke, перевірки документації, Python skills, Windows, macOS, Android і Control UI i18n. Набір plugin prerelease виключено з окремого ручного CI й увімкнено лише тоді, коли повна release umbrella проходить із `full_release_validation=true`. Ручні запуски використовують унікальну concurrency group, тож повний набір release-candidate не скасовується іншим push або PR-запуском на тому самому ref. Необов'язковий вхідний параметр `target_ref` дає змогу довіреному виклику виконати цей граф для branch, tag або повного commit SHA, використовуючи файл workflow з вибраного dispatch ref. +Ручні запуски CI виконують той самий граф завдань, що й звичайний CI, але примусово вмикають кожну +обмежену за областю доріжку: шарди Linux Node, шарди вбудованих Plugin, контракти каналів, +сумісність із Node 22, `check`, `check-additional`, димову перевірку збірки, перевірки документації, +Python Skills, Windows, macOS, Android і Control UI i18n. Набір попереднього випуску Plugin +виключено з автономного ручного CI й увімкнено лише тоді, коли +повна парасолька випуску проходить із `full_release_validation=true`. Ручні запуски використовують +унікальну групу конкурентності, тому повний набір перевірок кандидата на випуск не скасовується +іншим запуском push або PR на тому самому ref. Необов’язковий вхідний параметр `target_ref` дає +довіреному виклику змогу запустити цей граф для гілки, тегу або повного SHA коміту, водночас +використовуючи файл workflow з вибраного dispatch ref. ```bash gh workflow run ci.yml --ref release/YYYY.M.D @@ -371,64 +380,64 @@ gh workflow run ci.yml --ref main -f target_ref= gh workflow run full-release-validation.yml --ref main -f ref= ``` -## Порядок fail-fast +## Порядок швидкого припинення Завдання впорядковано так, щоб дешеві перевірки падали до запуску дорогих: -1. `preflight` вирішує, які lanes взагалі існують. Логіка `docs-scope` і `changed-scope` є кроками всередині цього завдання, а не окремими завданнями. -2. `security-scm-fast`, `security-dependency-audit`, `security-fast`, `check`, `check-additional`, `check-docs` і `skills-python` швидко падають, не чекаючи на важчі завдання матриці artifacts і platform. -3. `build-artifacts` перекривається зі швидкими Linux lanes, щоб downstream consumers могли стартувати, щойно shared build буде готовий. -4. Важчі platform і runtime lanes розгалужуються після цього: `checks-fast-core`, `checks-fast-contracts-channels`, `checks-node-extensions`, `checks-node-core-test`, `checks`, `checks-windows`, `macos-node`, `macos-swift` і `android`. +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, щоб нижчі споживачі могли стартувати щойно спільна збірка буде готова. +4. Після цього розгалужуються важчі платформні й runtime-доріжки: `checks-fast-core`, `checks-fast-contracts-channels`, `checks-node-extensions`, `checks-node-core-test`, `checks`, `checks-windows`, `macos-node`, `macos-swift` і `android`. -Логіка scope міститься в `scripts/ci-changed-scope.mjs` і покрита unit tests у `src/scripts/ci-changed-scope.test.ts`. -Ручний dispatch пропускає changed-scope detection і змушує preflight manifest -поводитися так, ніби кожна scoped area змінилася. -Редагування CI workflow перевіряють Node CI graph плюс workflow linting, але самі по собі не змушують запускати native builds для Windows, Android або macOS; ці platform lanes залишаються scoped до змін platform source. -Редагування лише CI routing, вибрані дешеві core-test fixture edits і вузькі plugin contract helper/test-routing edits використовують швидкий Node-only manifest path: preflight, security і одне завдання `checks-fast-core`. Цей шлях уникає build artifacts, сумісності з Node 22, channel contracts, повних core shards, bundled-plugin shards і додаткових guard matrices, коли змінені файли обмежені routing або helper surfaces, які fast task перевіряє напряму. -Windows Node checks scoped до Windows-specific process/path wrappers, npm/pnpm/UI runner helpers, package manager config і CI workflow surfaces, що виконують цю lane; непов'язані source, plugin, install-smoke і test-only changes залишаються на Linux Node lanes, щоб вони не резервували 16-vCPU Windows worker для покриття, яке вже перевіряється звичайними test shards. -Окремий workflow `install-smoke` повторно використовує той самий scope script через власне завдання `preflight`. Він розділяє smoke coverage на `run_fast_install_smoke` і `run_full_install_smoke`. Pull requests запускають fast path для Docker/package surfaces, bundled plugin package/manifest changes і core plugin/channel/gateway/Plugin SDK surfaces, які перевіряють Docker smoke jobs. Source-only bundled plugin changes, test-only edits і docs-only edits не резервують Docker workers. Fast path один раз збирає root Dockerfile image, перевіряє CLI, запускає agents delete shared-workspace CLI smoke, запускає container gateway-network e2e, перевіряє bundled extension build arg і запускає bounded bundled-plugin Docker profile із 240-секундним aggregate command timeout, причому Docker run кожного scenario обмежено окремо. Full path зберігає QR package install і installer Docker/update coverage для nightly scheduled runs, manual dispatches, workflow-call release checks і pull requests, які справді торкаються installer/package/Docker surfaces. `main` pushes, включно з merge commits, не змушують запускати full path; коли changed-scope logic запитує full coverage на push, workflow зберігає fast Docker smoke і залишає full install smoke для nightly або release validation. Повільний Bun global install image-provider smoke окремо gated через `run_bun_global_install_smoke`; він запускається за nightly schedule і з release checks workflow, а manual `install-smoke` dispatches можуть увімкнути його, але pull requests і `main` pushes його не запускають. QR і installer Docker tests зберігають власні install-focused Dockerfiles. Локальний `test:docker:all` попередньо збирає один shared live-test image, один раз пакує OpenClaw як npm tarball і збирає два shared images `scripts/e2e/Dockerfile`: bare Node/Git runner для installer/update/plugin-dependency lanes і functional image, який установлює той самий tarball у `/app` для normal functionality lanes. Визначення Docker lanes містяться в `scripts/lib/docker-e2e-scenarios.mjs`, planner logic міститься в `scripts/lib/docker-e2e-plan.mjs`, а runner виконує лише вибраний plan. Scheduler вибирає image для кожної lane через `OPENCLAW_DOCKER_E2E_BARE_IMAGE` і `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE`, потім запускає lanes із `OPENCLAW_SKIP_DOCKER_BUILD=1`; налаштуйте default main-pool slot count 10 через `OPENCLAW_DOCKER_ALL_PARALLELISM` і provider-sensitive tail-pool slot count 10 через `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM`. Heavy lane caps типово мають значення `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`, `OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` і `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`, щоб npm install і multi-service lanes не перевантажували Docker, поки легші lanes усе ще заповнюють доступні slots. Одна lane, важча за effective caps, усе одно може стартувати з порожнього pool, а потім виконується сама, доки не звільнить capacity. Старт lanes типово staggered на 2 секунди, щоб уникнути local Docker daemon create storms; перевизначте через `OPENCLAW_DOCKER_ALL_START_STAGGER_MS=0` або інше значення в мілісекундах. Local aggregate виконує preflights Docker, видаляє stale OpenClaw E2E containers, виводить active-lane status, зберігає lane timings для longest-first ordering і підтримує `OPENCLAW_DOCKER_ALL_DRY_RUN=1` для scheduler inspection. Він типово припиняє планування new pooled lanes після першої failure, і кожна lane має 120-minute fallback timeout, який можна перевизначити через `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS`; вибрані live/tail lanes використовують tighter per-lane caps. `OPENCLAW_DOCKER_ALL_LANES=` запускає exact scheduler lanes, включно з release-only lanes, такими як `install-e2e`, і split bundled update lanes, такими як `bundled-channel-update-acpx`, пропускаючи cleanup smoke, щоб agents могли відтворити одну failed lane. Reusable live/E2E workflow запитує `scripts/test-docker-all.mjs --plan-json`, яке package, image kind, live image, lane і credential coverage потрібні, а потім `scripts/docker-e2e.mjs` перетворює цей plan на GitHub outputs і summaries. Він або пакує OpenClaw через `scripts/package-openclaw-for-docker.mjs`, завантажує current-run package artifact, або завантажує package artifact із `package_artifact_run_id`; перевіряє tarball inventory; збирає й публікує package-digest-tagged bare/functional GHCR Docker E2E images через Blacksmith's Docker layer cache, коли plan потребує package-installed lanes; і повторно використовує надані inputs `docker_e2e_bare_image`/`docker_e2e_functional_image` або existing package-digest images замість rebuild. Workflow `Package Acceptance` є high-level package gate: він resolves candidate з npm, довіреного `package_ref`, HTTPS tarball plus SHA-256 або prior workflow artifact, а потім передає цей єдиний artifact `package-under-test` у reusable Docker E2E workflow. Він тримає `workflow_ref` окремо від `package_ref`, щоб current acceptance logic могла перевіряти older trusted commits без checkout old workflow code. Release checks запускають custom Package Acceptance delta для target ref: bundled-channel compat, offline plugin fixtures і Telegram package QA проти resolved tarball. Release-path Docker suite запускає smaller chunked jobs із `OPENCLAW_SKIP_DOCKER_BUILD=1`, щоб кожен chunk завантажував лише потрібний image kind і виконував кілька lanes через той самий weighted scheduler (`OPENCLAW_DOCKER_ALL_PROFILE=release-path`, `OPENCLAW_DOCKER_ALL_CHUNK=core|package-update-openai|package-update-anthropic|package-update-core|plugins-runtime-plugins|plugins-runtime-services|plugins-runtime-install-a|plugins-runtime-install-b|plugins-runtime-install-c|plugins-runtime-install-d|bundled-channels`). OpenWebUI включено до `plugins-runtime-services`, коли full release-path coverage запитує його, і він зберігає standalone chunk `openwebui` лише для OpenWebUI-only dispatches. Legacy aggregate chunk names `package-update`, `plugins-runtime-core`, `plugins-runtime` і `plugins-integrations` досі працюють для manual reruns, але release workflow використовує split chunks, щоб installer E2E і bundled plugin install/uninstall sweeps не домінували critical path. Lane alias `install-e2e` залишається aggregate manual rerun alias для обох provider installer lanes. Chunk `bundled-channels` запускає split lanes `bundled-channel-*` і `bundled-channel-update-*`, а не serial all-in-one lane `bundled-channel-deps`. Кожен chunk вивантажує `.artifacts/docker-tests/` з lane logs, timings, `summary.json`, `failures.json`, phase timings, scheduler plan JSON, slow-lane tables і per-lane rerun commands. Вхід workflow `docker_lanes` запускає selected lanes проти prepared images замість chunk jobs, що обмежує failed-lane debugging одним targeted Docker job і готує, завантажує або повторно використовує package artifact для цього run; якщо selected lane є live Docker lane, targeted job локально збирає live-test image для цього rerun. Згенеровані per-lane GitHub rerun commands містять `package_artifact_run_id`, `package_artifact_name` і prepared image inputs, коли ці значення існують, тож failed lane може повторно використати exact package та images із failed run. Використовуйте `pnpm test:docker:rerun `, щоб завантажити Docker artifacts із GitHub run і вивести combined/per-lane targeted rerun commands; використовуйте `pnpm test:docker:timings ` для slow-lane і phase critical-path summaries. Scheduled live/E2E workflow щодня запускає full release-path Docker suite. Bundled update matrix розділено за update target, щоб repeated npm update і doctor repair passes могли shard with other bundled checks. +Логіка області міститься в `scripts/ci-changed-scope.mjs` і покрита модульними тестами в `src/scripts/ci-changed-scope.test.ts`. +Ручний dispatch пропускає виявлення changed-scope і змушує маніфест preflight +поводитися так, ніби змінилася кожна обмежена за областю ділянка. +Редагування workflow CI перевіряють граф Node CI разом із linting workflow, але самі по собі не примушують Windows, Android або macOS native builds; ці платформні доріжки залишаються прив’язаними до змін платформного вихідного коду. +Редагування лише маршрутизації CI, вибрані дешеві редагування fixtures core-test і вузькі редагування helper/test-routing для контрактів Plugin використовують швидкий шлях маніфесту лише для Node: preflight, security і одне завдання `checks-fast-core`. Цей шлях уникає артефактів збірки, сумісності з Node 22, контрактів каналів, повних core shards, шардів вбудованих Plugin і додаткових guard-матриць, коли змінені файли обмежені поверхнями маршрутизації або helper, які швидке завдання перевіряє напряму. +Перевірки Windows Node обмежені специфічними для Windows process/path wrappers, helpers npm/pnpm/UI runner, конфігурацією менеджера пакетів і поверхнями workflow CI, які виконують цю доріжку; непов’язані зміни джерел, Plugin, install-smoke і лише тестові зміни залишаються на доріжках Linux Node, щоб вони не резервували 16-vCPU Windows worker для покриття, яке вже виконується звичайними тестовими шардами. +Окремий workflow `install-smoke` повторно використовує той самий scope script через власне завдання `preflight`. Він розділяє smoke-покриття на `run_fast_install_smoke` і `run_full_install_smoke`. Pull requests запускають швидкий шлях для поверхонь Docker/package, змін package/manifest вбудованих Plugin і поверхонь core plugin/channel/gateway/Plugin SDK, які перевіряють Docker smoke jobs. Зміни лише джерел вбудованих Plugin, редагування лише тестів і редагування лише документації не резервують Docker workers. Швидкий шлях один раз збирає образ кореневого Dockerfile, перевіряє CLI, запускає CLI smoke для agents delete shared-workspace, запускає container gateway-network e2e, перевіряє build arg вбудованого extension і запускає обмежений Docker profile вбудованих Plugin із сукупним таймаутом команди 240 секунд, причому Docker run кожного сценарію обмежено окремо. Повний шлях зберігає QR package install і installer Docker/update coverage для нічних запланованих запусків, ручних dispatches, workflow-call release checks і pull requests, які справді торкаються поверхонь installer/package/Docker. Pushes у `main`, включно з merge commits, не примушують повний шлях; коли логіка changed-scope просила б повне покриття на push, workflow зберігає fast Docker smoke і залишає full install smoke нічним або release validation. Повільний Bun global install image-provider smoke окремо керується через `run_bun_global_install_smoke`; він запускається за нічним розкладом і з workflow release checks, а ручні dispatches `install-smoke` можуть увімкнути його, але pull requests і pushes у `main` його не запускають. QR і installer Docker tests зберігають власні install-focused Dockerfiles. Локальний `test:docker:all` попередньо збирає один спільний live-test image, один раз пакує OpenClaw як npm tarball і збирає два спільні образи `scripts/e2e/Dockerfile`: bare Node/Git runner для доріжок installer/update/plugin-dependency і functional image, який встановлює той самий tarball у `/app` для звичайних functional lanes. Визначення Docker lanes містяться в `scripts/lib/docker-e2e-scenarios.mjs`, planner logic міститься в `scripts/lib/docker-e2e-plan.mjs`, а runner виконує лише вибраний план. Scheduler вибирає образ для кожної lane за допомогою `OPENCLAW_DOCKER_E2E_BARE_IMAGE` і `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE`, а потім запускає lanes з `OPENCLAW_SKIP_DOCKER_BUILD=1`; налаштуйте стандартну кількість слотів main-pool 10 через `OPENCLAW_DOCKER_ALL_PARALLELISM`, а чутливу до provider кількість слотів tail-pool 10 через `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM`. Caps для важких lanes за замовчуванням дорівнюють `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`, `OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` і `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`, щоб npm install і multi-service lanes не перевантажували Docker, поки легші lanes усе ще заповнюють доступні слоти. Одна lane, важча за ефективні caps, усе одно може стартувати з порожнього pool, а потім працює сама, доки не звільнить місткість. Запуски lanes за замовчуванням рознесені на 2 секунди, щоб уникнути локальних create storms Docker daemon; перевизначте це через `OPENCLAW_DOCKER_ALL_START_STAGGER_MS=0` або інше значення в мілісекундах. Локальний aggregate виконує preflight для Docker, видаляє застарілі OpenClaw E2E containers, виводить active-lane status, зберігає lane timings для longest-first ordering і підтримує `OPENCLAW_DOCKER_ALL_DRY_RUN=1` для інспекції scheduler. За замовчуванням він припиняє планувати нові pooled lanes після першої помилки, а кожна lane має 120-хвилинний fallback timeout, який можна перевизначити через `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS`; вибрані live/tail lanes використовують жорсткіші per-lane caps. `OPENCLAW_DOCKER_ALL_LANES=` запускає точні scheduler lanes, включно з release-only lanes, як-от `install-e2e`, і розділеними bundled update lanes, як-от `bundled-channel-update-acpx`, пропускаючи cleanup smoke, щоб agents могли відтворити одну невдалу lane. Повторно використовуваний live/E2E workflow запитує в `scripts/test-docker-all.mjs --plan-json`, яке package, image kind, live image, lane і credential coverage потрібні, після чого `scripts/docker-e2e.mjs` перетворює цей план на GitHub outputs і summaries. Він або пакує OpenClaw через `scripts/package-openclaw-for-docker.mjs`, завантажує package artifact поточного run, або завантажує package artifact з `package_artifact_run_id`; перевіряє inventory tarball; збирає й пушить package-digest-tagged bare/functional GHCR Docker E2E images через Docker layer cache Blacksmith, коли плану потрібні package-installed lanes; і повторно використовує надані inputs `docker_e2e_bare_image`/`docker_e2e_functional_image` або наявні package-digest images замість повторної збірки. Workflow `Package Acceptance` є високорівневим package gate: він визначає кандидата з npm, довіреного `package_ref`, HTTPS tarball плюс SHA-256 або попереднього workflow artifact, а потім передає цей єдиний artifact `package-under-test` у повторно використовуваний Docker E2E workflow. Він тримає `workflow_ref` окремо від `package_ref`, щоб поточна acceptance logic могла перевіряти старіші довірені commits без checkout старого workflow code. Release checks запускають спеціальну delta Package Acceptance для target ref: bundled-channel compat, offline plugin fixtures і Telegram package QA для визначеного tarball. Docker suite release-path запускає менші chunked jobs з `OPENCLAW_SKIP_DOCKER_BUILD=1`, щоб кожен chunk завантажував лише потрібний image kind і виконував кілька lanes через той самий weighted scheduler (`OPENCLAW_DOCKER_ALL_PROFILE=release-path`, `OPENCLAW_DOCKER_ALL_CHUNK=core|package-update-openai|package-update-anthropic|package-update-core|plugins-runtime-plugins|plugins-runtime-services|plugins-runtime-install-a|plugins-runtime-install-b|plugins-runtime-install-c|plugins-runtime-install-d|bundled-channels`). OpenWebUI включається в `plugins-runtime-services`, коли повне release-path coverage цього вимагає, і зберігає окремий chunk `openwebui` лише для dispatches тільки OpenWebUI. Застарілі aggregate chunk names `package-update`, `plugins-runtime-core`, `plugins-runtime` і `plugins-integrations` усе ще працюють для ручних повторних запусків, але release workflow використовує split chunks, щоб installer E2E і bundled plugin install/uninstall sweeps не домінували на критичному шляху. Alias lane `install-e2e` залишається aggregate manual rerun alias для обох provider installer lanes. Chunk `bundled-channels` запускає split lanes `bundled-channel-*` і `bundled-channel-update-*` замість послідовної all-in-one lane `bundled-channel-deps`. Кожен chunk вивантажує `.artifacts/docker-tests/` з lane logs, timings, `summary.json`, `failures.json`, phase timings, scheduler plan JSON, slow-lane tables і per-lane rerun commands. Вхідний параметр workflow `docker_lanes` запускає вибрані lanes для підготовлених images замість chunk jobs, що утримує debugging failed-lane в межах одного targeted Docker job і готує, завантажує або повторно використовує package artifact для цього run; якщо вибрана lane є live Docker lane, targeted job локально збирає live-test image для цього rerun. Згенеровані per-lane GitHub rerun commands включають `package_artifact_run_id`, `package_artifact_name` і prepared image inputs, коли такі значення існують, щоб failed lane могла повторно використати точні package і images з failed run. Використовуйте `pnpm test:docker:rerun `, щоб завантажити Docker artifacts з GitHub run і вивести combined/per-lane targeted rerun commands; використовуйте `pnpm test:docker:timings ` для slow-lane і phase critical-path summaries. Запланований live/E2E workflow щодня запускає повний release-path Docker suite. Матрицю bundled update розділено за update target, щоб повторні проходи npm update і doctor repair могли шардитися з іншими bundled checks. -Поточні release Docker chunks: `core`, `package-update-openai`, `package-update-anthropic`, `package-update-core`, `plugins-runtime-plugins`, `plugins-runtime-services`, `plugins-runtime-install-a`, `plugins-runtime-install-b`, `plugins-runtime-install-c`, `plugins-runtime-install-d`, `bundled-channels-core`, `bundled-channels-update-a`, `bundled-channels-update-b` і `bundled-channels-contracts`. Aggregate chunk `bundled-channels` залишається доступним для manual one-shot reruns, а `plugins-runtime-core`, `plugins-runtime` і `plugins-integrations` залишаються aggregate plugin/runtime aliases, але release workflow використовує split chunks, щоб channel smokes, update targets, plugin runtime checks і bundled plugin install/uninstall sweeps могли виконуватися паралельно. Targeted `docker_lanes` dispatches також розділяють кілька selected lanes на parallel jobs після одного shared package/image preparation step, а bundled-channel update lanes повторюють спробу один раз для transient npm network failures. +Поточні release Docker chunks: `core`, `package-update-openai`, `package-update-anthropic`, `package-update-core`, `plugins-runtime-plugins`, `plugins-runtime-services`, `plugins-runtime-install-a`, `plugins-runtime-install-b`, `plugins-runtime-install-c`, `plugins-runtime-install-d`, `bundled-channels-core`, `bundled-channels-update-a`, `bundled-channels-update-b` і `bundled-channels-contracts`. Aggregate chunk `bundled-channels` лишається доступним для ручних one-shot reruns, а `plugins-runtime-core`, `plugins-runtime` і `plugins-integrations` лишаються aggregate plugin/runtime aliases, але release workflow використовує split chunks, щоб channel smokes, update targets, plugin runtime checks і bundled plugin install/uninstall sweeps могли виконуватися паралельно. Targeted dispatches `docker_lanes` також розділяють кілька вибраних lanes на parallel jobs після одного спільного кроку package/image preparation, а bundled-channel update lanes повторюють спробу один раз у разі transient npm network failures. -Локальна логіка changed-lane міститься в `scripts/changed-lanes.mjs` і виконується через `scripts/check-changed.mjs`. Цей локальний check gate суворіше перевіряє архітектурні межі, ніж широкий обсяг платформи CI: зміни в production-коді ядра запускають typecheck для core prod і core test плюс core lint/guards, зміни лише в тестах ядра запускають тільки core test typecheck плюс core lint, зміни в production-коді розширень запускають extension prod і extension test typecheck плюс extension lint, а зміни лише в тестах розширень запускають extension test typecheck плюс extension lint. Зміни в публічному Plugin SDK або plugin-contract розширюються до typecheck розширень, бо розширення залежать від цих контрактів ядра, але Vitest-перевірки розширень є явною тестовою роботою. Зміни лише в метаданих релізної версії запускають цільові перевірки version/config/root-dependency. Невідомі зміни root/config безпечно провалюються до всіх check lanes. +Локальна логіка changed-lane міститься в `scripts/changed-lanes.mjs` і виконується через `scripts/check-changed.mjs`. Цей локальний контрольний шлюз суворіший щодо архітектурних меж, ніж широкий обсяг платформи CI: зміни у продукційному коді ядра запускають typecheck для core prod і core test, а також lint/guards ядра; зміни лише в тестах ядра запускають тільки typecheck для core test і lint ядра; зміни у продукційному коді розширень запускають typecheck для extension prod і extension test, а також lint розширень; зміни лише в тестах розширень запускають typecheck для extension test і lint розширень. Зміни в публічному Plugin SDK або контрактах плагінів розширюються до typecheck розширень, бо розширення залежать від цих контрактів ядра, але Vitest-перевірки розширень є явною тестовою роботою. Зміни версій лише в релізних метаданих запускають цільові перевірки версій, конфігурації та кореневих залежностей. Невідомі зміни кореня/конфігурації безпечно переходять до всіх check-ланів. Локальна маршрутизація changed-test міститься в `scripts/test-projects.test-support.mjs` і навмисно дешевша за `check:changed`: прямі зміни тестів запускають самі себе, -зміни джерел віддають перевагу явним мапінгам, потім sibling tests та import-graph -dependents. Shared group-room delivery config є одним із явних мапінгів: -зміни до group visible-reply config, source reply delivery mode або -message-tool system prompt проходять через core reply tests плюс регресії доставки Discord і -Slack, тож зміна shared default падає до першого push PR. +зміни джерел віддають перевагу явним мапінгам, потім sibling-тестам і залежним +елементам графа імпортів. Спільна конфігурація доставки групових кімнат є одним із явних мапінгів: +зміни у конфігурації видимої групової відповіді, режимі доставки відповіді з джерела або +маршруті системного prompt для message-tool проходять через тести відповідей ядра, а також регресії доставки Discord і +Slack, щоб зміна спільного значення за замовчуванням падала до першого push PR. Використовуйте `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed` лише тоді, коли зміна -достатньо широка для harness, що дешевий mapped set не є надійним proxy. +настільки широка для harness, що дешевий зіставлений набір не є надійним proxy. -Для валідації Testbox запускайте з кореня репозиторію і віддавайте перевагу свіжому прогрітому box для -широкого proof. Перш ніж витрачати повільний gate на box, який було повторно використано, строк дії якого минув або -який щойно повідомив про неочікувано великий sync, запустіть `pnpm testbox:sanity` всередині -box. Sanity check швидко падає, коли обов’язкові root files, як-от +Для валідації Testbox запускайте з кореня репозиторію і для +широкого доказу віддавайте перевагу свіжо прогрітому box. Перед тим як витрачати повільний gate на box, який було повторно використано, термін дії якого минув або +який щойно повідомив про неочікувано велику синхронізацію, спершу запустіть `pnpm testbox:sanity` всередині +box. Sanity-перевірка швидко падає, коли обов’язкові кореневі файли, як-от `pnpm-lock.yaml`, зникли або коли `git status --short` показує щонайменше 200 -tracked deletions. Зазвичай це означає, що remote sync state не є надійною +відстежуваних видалень. Зазвичай це означає, що стан віддаленої синхронізації не є надійною копією PR. Зупиніть цей box і прогрійте свіжий замість налагодження -product test failure. Для навмисних PR із великим видаленням установіть -`OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1` для цього sanity run. +збою продуктового тесту. Для навмисних PR із великим обсягом видалень задайте +`OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1` для цього sanity-запуску. -Ручні dispatch CI запускають `checks-node-compat-node22` як широке compatibility coverage. `plugin-prerelease-suite` є дорожчим product/package coverage, тому він запускається лише коли `Full Release Validation` запускає CI з `full_release_validation=true`. Звичайні pull requests, push до `main` і окремі ручні dispatch CI тримають цей suite вимкненим. +Ручні CI-dispatches запускають `checks-node-compat-node22` як широке покриття сумісності. `plugin-prerelease-suite` є дорожчим продуктовим/пакетним покриттям, тому він запускається лише коли `Full Release Validation` dispatch-ить CI з `full_release_validation=true`. Звичайні pull requests, push до `main` і окремі ручні CI-dispatches залишають цей suite вимкненим. -Найповільніші сімейства тестів Node розділені або збалансовані так, щоб кожна job залишалася малою без надмірного резервування runners: channel contracts запускаються як три weighted shards, bundled plugin tests балансуються між шістьма extension workers, малі core unit lanes спарені, auto-reply запускається як чотири збалансовані workers із reply subtree, розділеним на shards agent-runner, dispatch і commands/state-routing, а agentic gateway/plugin configs розподілені між наявними source-only agentic Node jobs замість очікування built artifacts. Широкі browser, QA, media і miscellaneous plugin tests використовують свої dedicated Vitest configs замість shared plugin catch-all. Extension shard jobs запускають до двох plugin config groups одночасно з одним Vitest worker на групу і більшим Node heap, щоб import-heavy plugin batches не створювали додаткових CI jobs. Широка agents lane використовує shared Vitest file-parallel scheduler, бо вона домінована import/scheduling, а не належить одному повільному test file. `runtime-config` запускається з infra core-runtime shard, щоб shared runtime shard не володів tail. Include-pattern shards записують timing entries, використовуючи назву CI shard, тож `.artifacts/vitest-shard-timings.json` може відрізнити whole config від filtered shard. `check-additional` тримає package-boundary compile/canary роботу разом і відокремлює runtime topology architecture від gateway watch coverage; boundary guard shard запускає свої малі independent guards конкурентно в одній job. Gateway watch, channel tests і core support-boundary shard запускаються конкурентно всередині `build-artifacts` після того, як `dist/` і `dist-runtime/` уже зібрані, зберігаючи їхні старі check names як lightweight verifier jobs, уникаючи двох додаткових Blacksmith workers і другої artifact-consumer queue. -Android CI запускає і `testPlayDebugUnitTest`, і `testThirdPartyDebugUnitTest`, а потім збирає Play debug APK. Third-party flavor не має окремого source set або manifest; його unit-test lane все одно компілює цей flavor з SMS/call-log BuildConfig flags, уникаючи дубльованого debug APK packaging job на кожному Android-relevant push. -GitHub може позначати superseded jobs як `cancelled`, коли новіший push потрапляє на той самий PR або `main` ref. Сприймайте це як CI noise, якщо найновіший run для того самого ref також не падає. Aggregate shard checks використовують `!cancelled() && always()`, тому вони все ще повідомляють звичайні shard failures, але не стають у чергу після того, як увесь workflow уже superseded. -Автоматичний concurrency key CI версійований (`CI-v7-*`), щоб GitHub-side zombie у старій queue group не міг нескінченно блокувати новіші main runs. Ручні full-suite runs використовують `CI-manual-v1-*` і не скасовують in-progress runs. +Найповільніші сімейства тестів Node розділено або збалансовано так, щоб кожне job залишалося малим без надмірного резервування runner-ів: контракти каналів запускаються як три зважені shards, тести bundled plugin балансуються між шістьма workers розширень, малі лани core unit поєднуються в пари, auto-reply запускається як чотири збалансовані workers із піддеревом reply, розділеним на shards agent-runner, dispatch і commands/state-routing, а agentic gateway/plugin configs розподіляються між наявними source-only agentic Node jobs замість очікування на зібрані артефакти. Широкі browser, QA, media та різні plugin-тести використовують свої dedicated Vitest configs замість спільного plugin catch-all. Extension shard jobs запускають до двох груп plugin config одночасно з одним Vitest worker на групу і більшим heap Node, щоб import-heavy plugin batches не створювали додаткові CI jobs. Широкий agents lane використовує спільний Vitest file-parallel scheduler, бо він домінується імпортами/плануванням, а не належить одному повільному тестовому файлу. `runtime-config` запускається з infra core-runtime shard, щоб спільний runtime shard не володів хвостом. Include-pattern shards записують timing entries з використанням імені CI shard, тому `.artifacts/vitest-shard-timings.json` може відрізнити цілий config від відфільтрованого shard. `check-additional` тримає package-boundary compile/canary work разом і відокремлює runtime topology architecture від gateway watch coverage; boundary guard shard запускає свої малі незалежні guards конкурентно в одному job. Gateway watch, channel tests і core support-boundary shard запускаються конкурентно всередині `build-artifacts` після того, як `dist/` і `dist-runtime/` вже зібрані, зберігаючи свої старі check names як легкі verifier jobs і водночас уникаючи двох додаткових Blacksmith workers та другої черги artifact-consumer. +Android CI запускає і `testPlayDebugUnitTest`, і `testThirdPartyDebugUnitTest`, а потім збирає Play debug APK. Third-party flavor не має окремого source set або manifest; його unit-test lane все одно компілює цей flavor із прапорцями SMS/call-log BuildConfig, уникаючи дублювання job пакування debug APK на кожному push, релевантному для Android. +GitHub може позначати витіснені jobs як `cancelled`, коли новіший push потрапляє на той самий PR або ref `main`. Сприймайте це як CI noise, якщо найновіший run для того самого ref також не падає. Aggregate shard checks використовують `!cancelled() && always()`, тому вони все одно повідомляють звичайні збої shard, але не стають у чергу після того, як увесь workflow уже було витіснено. +Автоматичний concurrency key CI версіоновано (`CI-v7-*`), щоб GitHub-side zombie у старій queue group не міг безстроково блокувати новіші main runs. Ручні full-suite runs використовують `CI-manual-v1-*` і не скасовують in-progress runs. ## Runners | Runner | Jobs | | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ubuntu-24.04` | `preflight`, швидкі security jobs і aggregates (`security-scm-fast`, `security-dependency-audit`, `security-fast`), швидкі protocol/contract/bundled checks, sharded channel contract checks, `check` shards окрім lint, `check-additional` shards і aggregates, Node test aggregate verifiers, docs checks, Python skills, workflow-sanity, labeler, auto-response; install-smoke preflight також використовує GitHub-hosted Ubuntu, щоб Blacksmith matrix могла стати в чергу раніше | -| `blacksmith-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`, lower-weight extension shards, `checks-fast-core`, `checks-node-compat-node22`, `check-prod-types` і `check-test-types` | +| `blacksmith-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`, lower-weight extension shards, `checks-fast-core`, `checks-node-compat-node22`, `check-prod-types` і `check-test-types` | | `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`, build-smoke, Linux Node test shards, bundled plugin test shards, `android` | -| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`, який залишається достатньо CPU-sensitive, що 8 vCPU коштували більше, ніж заощадили; install-smoke Docker builds, де час у 32-vCPU queue коштував більше, ніж заощадив | +| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`, який залишається достатньо CPU-sensitive, щоб 8 vCPU коштували більше, ніж заощаджували; install-smoke Docker builds, де час черги 32-vCPU коштував більше, ніж заощаджував | | `blacksmith-16vcpu-windows-2025` | `checks-windows` | -| `blacksmith-6vcpu-macos-latest` | `macos-node` на `openclaw/openclaw`; forks fallback до `macos-latest` | -| `blacksmith-12vcpu-macos-latest` | `macos-swift` на `openclaw/openclaw`; forks fallback до `macos-latest` | +| `blacksmith-6vcpu-macos-latest` | `macos-node` на `openclaw/openclaw`; forks повертаються до `macos-latest` | +| `blacksmith-12vcpu-macos-latest` | `macos-swift` на `openclaw/openclaw`; forks повертаються до `macos-latest` | ## Локальні еквіваленти @@ -458,5 +467,5 @@ pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifac ## Пов’язане -- [Огляд установлення](/uk/install) +- [Огляд встановлення](/uk/install) - [Канали релізів](/uk/install/development-channels) diff --git a/docs/uk/concepts/qa-matrix.md b/docs/uk/concepts/qa-matrix.md index 54798c90b..2b6518c0b 100644 --- a/docs/uk/concepts/qa-matrix.md +++ b/docs/uk/concepts/qa-matrix.md @@ -1,24 +1,24 @@ --- read_when: - - Локальний запуск pnpm openclaw qa matrix + - Запуск pnpm openclaw qa matrix локально - Додавання або вибір QA-сценаріїв Matrix - Тріаж збоїв Matrix QA, тайм-аутів або завислого очищення -summary: 'Довідник для супровідників щодо живої QA-доріжки Matrix на базі Docker: CLI, профілі, змінні середовища, сценарії та вихідні артефакти.' -title: QA Matrix +summary: 'Довідник для супровідників щодо live-лінії QA Matrix на базі Docker: CLI, профілі, змінні середовища, сценарії та вихідні артефакти.' +title: Матричне QA x-i18n: - generated_at: "2026-04-28T11:09:51Z" + generated_at: "2026-04-29T05:57:16Z" model: gpt-5.5 provider: openai - source_hash: 6282e8a65fb5af46a67f8240d5a9ce095e614b6cc68621745ffe79cf88a5131f + source_hash: 6ab862474e2abe45a1dcd66f025e3a3dd52a3417b0c1f42a26cd7944dd4053f5 source_path: concepts/qa-matrix.md workflow: 16 --- -Лейн Matrix QA запускає вбудований `@openclaw/matrix` plugin проти одноразового homeserver Tuwunel у Docker, з тимчасовими обліковими записами driver, SUT і observer, а також підготовленими кімнатами. Це покриття Matrix із реальним live-транспортом. +Лінія QA Matrix запускає вбудований Plugin `@openclaw/matrix` із одноразовим homeserver Tuwunel у Docker, з тимчасовими обліковими записами driver, SUT і observer та попередньо заповненими кімнатами. Це живе покриття Matrix із реальним транспортом. -Це інструментарій лише для мейнтейнерів. Пакетовані релізи OpenClaw навмисно не містять `qa-lab`, тому `openclaw qa` доступний лише з checkout вихідного коду. Checkout вихідного коду завантажує вбудований runner напряму — крок встановлення plugin не потрібен. +Це інструменти лише для супровідників. Пакетовані релізи OpenClaw навмисно не містять `qa-lab`, тому `openclaw qa` доступний лише з checkout вихідного коду. Checkout вихідного коду завантажує вбудований засіб запуску напряму — крок встановлення Plugin не потрібен. -Ширший контекст QA framework див. в [огляді QA](/uk/concepts/qa-e2e-automation). +Ширший контекст фреймворку QA див. в [огляді QA](/uk/concepts/qa-e2e-automation). ## Швидкий старт @@ -26,16 +26,16 @@ x-i18n: pnpm openclaw qa matrix --profile fast --fail-fast ``` -Звичайний `pnpm openclaw qa matrix` запускає `--profile all` і не зупиняється після першої помилки. Використовуйте `--profile fast --fail-fast` для release gate; розділяйте каталог на шарди за допомогою `--profile transport|media|e2ee-smoke|e2ee-deep|e2ee-cli`, коли запускаєте повний inventory паралельно. +Звичайний `pnpm openclaw qa matrix` запускає `--profile all` і не зупиняється після першої помилки. Використовуйте `--profile fast --fail-fast` для релізного gate; розбийте каталог на шарди за допомогою `--profile transport|media|e2ee-smoke|e2ee-deep|e2ee-cli`, коли запускаєте весь інвентар паралельно. -## Що робить лейн +## Що робить лінія -1. Створює одноразовий homeserver Tuwunel у Docker (стандартний образ `ghcr.io/matrix-construct/tuwunel:v1.5.1`, ім’я сервера `matrix-qa.test`, порт `28008`). -2. Реєструє трьох тимчасових користувачів — `driver` (надсилає вхідний трафік), `sut` (обліковий запис OpenClaw Matrix, що тестується), `observer` (перехоплення трафіку третьої сторони). -3. Готує кімнати, потрібні вибраним сценаріям (основну, для threading, media, restart, secondary, allowlist, E2EE, verification DM тощо). -4. Запускає дочірній OpenClaw gateway зі справжнім Matrix plugin, обмеженим обліковим записом SUT; `qa-channel` не завантажується в дочірньому процесі. -5. Виконує сценарії послідовно, спостерігаючи події через Matrix clients driver/observer. -6. Зупиняє homeserver, записує artifacts зі звітом і підсумком, потім завершує роботу. +1. Готує одноразовий homeserver Tuwunel у Docker (образ за замовчуванням `ghcr.io/matrix-construct/tuwunel:v1.5.1`, ім’я сервера `matrix-qa.test`, порт `28008`). +2. Реєструє трьох тимчасових користувачів — `driver` (надсилає вхідний трафік), `sut` (обліковий запис OpenClaw Matrix, що тестується), `observer` (захоплення стороннього трафіку). +3. Заповнює кімнати, потрібні для вибраних сценаріїв (main, threading, media, restart, secondary, allowlist, E2EE, verification DM тощо). +4. Запускає дочірній Gateway OpenClaw зі справжнім Matrix Plugin, обмеженим обліковим записом SUT; `qa-channel` у дочірньому процесі не завантажується. +5. Виконує сценарії послідовно, спостерігаючи події через Matrix-клієнти driver/observer. +6. Зупиняє homeserver, записує артефакти звіту й підсумку, потім завершує роботу. ## CLI @@ -45,101 +45,102 @@ pnpm openclaw qa matrix [options] ### Поширені прапорці -| Прапорець | Стандартно | Опис | -| --------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -| `--profile ` | `all` | Профіль сценаріїв. Див. [Профілі](#profiles). | -| `--fail-fast` | off | Зупинитися після першої невдалої перевірки або сценарію. | -| `--scenario ` | — | Запустити лише цей сценарій. Можна повторювати. Див. [Сценарії](#scenarios). | -| `--output-dir ` | `/.artifacts/qa-e2e/matrix-` | Куди записуються звіти, підсумок, спостережені події та output log. Відносні шляхи обчислюються відносно `--repo-root`. | -| `--repo-root ` | `process.cwd()` | Корінь репозиторію під час виклику з нейтрального робочого каталогу. | -| `--sut-account ` | `sut` | Ідентифікатор облікового запису Matrix у конфігурації QA gateway. | +| Прапорець | За замовчуванням | Опис | +| --------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| `--profile ` | `all` | Профіль сценаріїв. Див. [Профілі](#profiles). | +| `--fail-fast` | вимкнено | Зупинитися після першої невдалої перевірки або сценарію. | +| `--scenario ` | — | Запустити лише цей сценарій. Можна повторювати. Див. [Сценарії](#scenarios). | +| `--output-dir ` | `/.artifacts/qa-e2e/matrix-` | Куди записуються звіти, підсумок, спостережені події та журнал виводу. Відносні шляхи визначаються відносно `--repo-root`. | +| `--repo-root ` | `process.cwd()` | Корінь репозиторію під час виклику з нейтрального робочого каталогу. | +| `--sut-account ` | `sut` | Ідентифікатор облікового запису Matrix у конфігурації QA Gateway. | ### Прапорці провайдера -Лейн використовує справжній транспорт Matrix, але model provider можна налаштувати: +Лінія використовує справжній транспорт Matrix, але провайдера моделі можна налаштувати: -| Прапорець | Стандартно | Опис | -| ------------------------ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| `--provider-mode ` | `live-frontier` | `mock-openai` для deterministic mock dispatch або `live-frontier` для live frontier providers. Legacy alias `live-openai` досі працює. | -| `--model ` | provider default | Основний ref `provider/model`. | -| `--alt-model ` | provider default | Альтернативний ref `provider/model`, коли сценарії перемикаються посеред виконання. | -| `--fast` | off | Увімкнути fast mode провайдера, де це підтримується. | +| Прапорець | За замовчуванням | Опис | +| ------------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| `--provider-mode ` | `live-frontier` | `mock-openai` для детермінованої mock-диспетчеризації або `live-frontier` для живих передових провайдерів. Застарілий alias `live-openai` досі працює. | +| `--model ` | стандарт провайдера | Основне посилання `provider/model`. | +| `--alt-model ` | стандарт провайдера | Альтернативне посилання `provider/model`, коли сценарії перемикаються посеред виконання. | +| `--fast` | вимкнено | Увімкнути швидкий режим провайдера, де він підтримується. | -Matrix QA не приймає `--credential-source` або `--credential-role`. Лейн створює одноразових користувачів локально; спільного credential pool для lease немає. +Matrix QA не приймає `--credential-source` або `--credential-role`. Лінія локально створює одноразових користувачів; немає спільного пулу облікових даних, з якого можна брати lease. ## Профілі -Вибраний профіль визначає, які сценарії запускатимуться. +Вибраний профіль визначає, які сценарії виконуються. -| Профіль | Для чого використовувати | -| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `all` (default) | Повний каталог. Повільний, але вичерпний. | -| `fast` | Підмножина для release gate, яка перевіряє live transport contract: canary, mention gating, allowlist block, reply shape, restart resume, thread follow-up, thread isolation, reaction observation і delivery metadata для exec approval. | -| `transport` | Сценарії transport-level threading, DM, room, autojoin, mention/allowlist, approval і reaction. | -| `media` | Покриття вкладень image, audio, video, PDF, EPUB. | -| `e2ee-smoke` | Мінімальне покриття E2EE — базова зашифрована відповідь, thread follow-up, успішний bootstrap. | -| `e2ee-deep` | Вичерпні сценарії E2EE для state-loss, backup, key і recovery. | -| `e2ee-cli` | CLI-сценарії `openclaw matrix encryption setup` і `verify *`, керовані через QA harness. | +| Профіль | Для чого використовувати | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `all` (default) | Повний каталог. Повільний, але вичерпний. | +| `fast` | Підмножина для релізного gate, що перевіряє контракт живого транспорту: canary, mention gating, allowlist block, reply shape, restart resume, thread follow-up, thread isolation, reaction observation і доставку метаданих exec approval. | +| `transport` | Сценарії потоків, DM, кімнат, autojoin, mention/allowlist, approval і реакцій на рівні транспорту. | +| `media` | Покриття вкладень із зображеннями, аудіо, відео, PDF, EPUB. | +| `e2ee-smoke` | Мінімальне покриття E2EE — базова зашифрована відповідь, thread follow-up, успішний bootstrap. | +| `e2ee-deep` | Вичерпні сценарії E2EE для втрати стану, backup, ключів і відновлення. | +| `e2ee-cli` | Сценарії CLI `openclaw matrix encryption setup` і `verify *`, що виконуються через QA harness. | Точне зіставлення міститься в `extensions/qa-matrix/src/runners/contract/scenario-catalog.ts`. ## Сценарії -Повний список ідентифікаторів сценаріїв — це union `MatrixQaScenarioId` у `extensions/qa-matrix/src/runners/contract/scenario-catalog.ts:15`. Категорії охоплюють: +Повний список ідентифікаторів сценаріїв — це union `MatrixQaScenarioId` у `extensions/qa-matrix/src/runners/contract/scenario-catalog.ts:15`. Категорії включають: -- threading — `matrix-thread-*`, `matrix-subagent-thread-spawn` -- top-level / DM / room — `matrix-top-level-reply-shape`, `matrix-room-*`, `matrix-dm-*` -- streaming і tool progress — `matrix-room-partial-streaming-preview`, `matrix-room-quiet-streaming-preview`, `matrix-room-tool-progress-*`, `matrix-room-block-streaming` -- media — `matrix-media-type-coverage`, `matrix-room-image-understanding-attachment`, `matrix-attachment-only-ignored`, `matrix-unsupported-media-safe` -- routing — `matrix-room-autojoin-invite`, `matrix-secondary-room-*` -- reactions — `matrix-reaction-*` -- approvals — `matrix-approval-*` (exec/plugin metadata, chunked fallback, deny reactions, threads і routing `target: "both"`) +- потоки — `matrix-thread-*`, `matrix-subagent-thread-spawn` +- верхній рівень / DM / кімната — `matrix-top-level-reply-shape`, `matrix-room-*`, `matrix-dm-*` +- streaming і прогрес інструментів — `matrix-room-partial-streaming-preview`, `matrix-room-quiet-streaming-preview`, `matrix-room-tool-progress-*`, `matrix-room-block-streaming` +- медіа — `matrix-media-type-coverage`, `matrix-room-image-understanding-attachment`, `matrix-attachment-only-ignored`, `matrix-unsupported-media-safe` +- маршрутизація — `matrix-room-autojoin-invite`, `matrix-secondary-room-*` +- реакції — `matrix-reaction-*` +- approvals — `matrix-approval-*` (метадані exec/Plugin, chunked fallback, реакції deny, потоки та маршрутизація `target: "both"`) - restart і replay — `matrix-restart-*`, `matrix-stale-sync-replay-dedupe`, `matrix-room-membership-loss`, `matrix-homeserver-restart-resume`, `matrix-initial-catchup-then-incremental` - mention gating, bot-to-bot і allowlists — `matrix-mention-*`, `matrix-allowbots-*`, `matrix-allowlist-*`, `matrix-multi-actor-ordering`, `matrix-inbound-edit-*`, `matrix-mxid-prefixed-command-block`, `matrix-observer-allowlist-override` -- E2EE — `matrix-e2ee-*` (basic reply, thread follow-up, bootstrap, recovery key lifecycle, state-loss variants, server backup behavior, device hygiene, SAS / QR / DM verification, restart, artifact redaction) -- E2EE CLI — `matrix-e2ee-cli-*` (encryption setup, idempotent setup, bootstrap failure, recovery-key lifecycle, multi-account, gateway-reply round-trip, self-verification) +- E2EE — `matrix-e2ee-*` (базова відповідь, thread follow-up, bootstrap, життєвий цикл recovery key, варіанти втрати стану, поведінка server backup, гігієна пристроїв, перевірка SAS / QR / DM, restart, редагування артефактів) +- E2EE CLI — `matrix-e2ee-cli-*` (налаштування шифрування, ідемпотентне налаштування, помилка bootstrap, життєвий цикл recovery-key, кілька облікових записів, round-trip gateway-reply, self-verification) -Передайте `--scenario ` (можна повторювати), щоб запустити вручну вибраний набір; поєднуйте з `--profile all`, щоб ігнорувати profile gating. +Передайте `--scenario ` (можна повторювати), щоб запустити вручну вибраний набір; поєднуйте з `--profile all`, щоб ігнорувати фільтрацію профілю. ## Змінні середовища -| Змінна | Стандартно | Ефект | +| Змінна | Типове значення | Ефект | | --------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `OPENCLAW_QA_MATRIX_TIMEOUT_MS` | `1800000` (30 хв) | Жорстка верхня межа для всього запуску. | -| `OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS` | `8000` | Quiet window для негативних no-reply assertions. Обмежується до `≤` timeout запуску. | -| `OPENCLAW_QA_MATRIX_CLEANUP_TIMEOUT_MS` | `90000` | Обмеження для Docker teardown. Failure surfaces містять recovery-команду `docker compose ... down --remove-orphans`. | +| `OPENCLAW_QA_MATRIX_CANARY_TIMEOUT_MS` | `45000` | Межа для початкової canary-відповіді. Release CI збільшує її на спільних раннерах, щоб повільний перший хід gateway не завершувався помилкою до початку покриття сценаріїв. | +| `OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS` | `8000` | Тихе вікно для негативних тверджень про відсутність відповіді. Обмежується до `≤` таймауту запуску. | +| `OPENCLAW_QA_MATRIX_CLEANUP_TIMEOUT_MS` | `90000` | Межа для демонтажу Docker. Поверхні помилок містять команду відновлення `docker compose ... down --remove-orphans`. | | `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE` | `ghcr.io/matrix-construct/tuwunel:v1.5.1` | Перевизначає образ homeserver під час перевірки з іншою версією Tuwunel. | -| `OPENCLAW_QA_MATRIX_PROGRESS` | on | `0` вимикає progress lines `[matrix-qa] ...` у stderr. `1` примусово вмикає їх. | -| `OPENCLAW_QA_MATRIX_CAPTURE_CONTENT` | redacted | `1` зберігає message body і `formatted_body` у `matrix-qa-observed-events.json`. Типово дані редагуються, щоб CI artifacts залишалися безпечними. | -| `OPENCLAW_QA_MATRIX_DISABLE_FORCE_EXIT` | off | `1` пропускає deterministic `process.exit` після запису artifacts. Типово вихід примусовий, бо native crypto handles matrix-js-sdk можуть утримувати event loop живим після завершення artifacts. | -| `OPENCLAW_RUN_NODE_OUTPUT_LOG` | unset | Коли встановлено зовнішнім launcher (наприклад, `scripts/run-node.mjs`), Matrix QA повторно використовує цей шлях log замість запуску власного tee. | +| `OPENCLAW_QA_MATRIX_PROGRESS` | увімкнено | `0` вимикає рядки прогресу `[matrix-qa] ...` у stderr. `1` примусово вмикає їх. | +| `OPENCLAW_QA_MATRIX_CAPTURE_CONTENT` | відредаговано | `1` зберігає тіло повідомлення та `formatted_body` у `matrix-qa-observed-events.json`. Типово редагує їх, щоб CI-артефакти залишалися безпечними. | +| `OPENCLAW_QA_MATRIX_DISABLE_FORCE_EXIT` | вимкнено | `1` пропускає детермінований `process.exit` після запису артефакту. Типово вихід примусовий, бо нативні crypto-дескриптори matrix-js-sdk можуть тримати цикл подій активним після завершення артефакту. | +| `OPENCLAW_RUN_NODE_OUTPUT_LOG` | не задано | Коли задано зовнішнім запускачем (наприклад, `scripts/run-node.mjs`), Matrix QA повторно використовує цей шлях журналу замість запуску власного tee. | -## Output artifacts +## Вихідні артефакти Записуються до `--output-dir`: -- `matrix-qa-report.md` — звіт протоколу у Markdown (що пройшло, не пройшло, було пропущено і чому). -- `matrix-qa-summary.json` — структурований підсумок, придатний для парсингу в CI та панелей моніторингу. -- `matrix-qa-observed-events.json` — спостережені події Matrix від клієнтів драйвера й спостерігача. Тіла редагуються, якщо не встановлено `OPENCLAW_QA_MATRIX_CAPTURE_CONTENT=1`; метадані затвердження узагальнюються з вибраними безпечними полями та скороченим попереднім переглядом команди. -- `matrix-qa-output.log` — об’єднані stdout/stderr із запуску. Якщо встановлено `OPENCLAW_RUN_NODE_OUTPUT_LOG`, натомість повторно використовується журнал зовнішнього запускача. +- `matrix-qa-report.md` — протокольний звіт Markdown (що пройшло, не пройшло, було пропущено і чому). +- `matrix-qa-summary.json` — структурований підсумок, придатний для парсингу CI та панелей моніторингу. +- `matrix-qa-observed-events.json` — спостережені події Matrix від клієнтів драйвера й observer. Тіла редагуються, якщо не задано `OPENCLAW_QA_MATRIX_CAPTURE_CONTENT=1`; метадані схвалення підсумовуються з вибраними безпечними полями та скороченим попереднім переглядом команди. +- `matrix-qa-output.log` — об’єднані stdout/stderr із запуску. Якщо задано `OPENCLAW_RUN_NODE_OUTPUT_LOG`, натомість повторно використовується журнал зовнішнього запускника. -Типовий каталог виводу — `/.artifacts/qa-e2e/matrix-`, тому послідовні запуски не перезаписують один одного. +Типова директорія виводу — `/.artifacts/qa-e2e/matrix-`, тому послідовні запуски не перезаписують один одного. ## Поради з тріажу -- **Запуск зависає ближче до кінця:** нативні криптографічні дескриптори `matrix-js-sdk` можуть пережити harness. Типова поведінка примусово виконує чистий `process.exit` після запису артефактів; якщо ви скасували `OPENCLAW_QA_MATRIX_DISABLE_FORCE_EXIT=1`, очікуйте, що процес залишатиметься активним. -- **Помилка очищення:** знайдіть надруковану команду відновлення (виклик `docker compose ... down --remove-orphans`) і запустіть її вручну, щоб звільнити порт homeserver. -- **Нестабільні вікна негативних тверджень у CI:** зменште `OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS` (типово 8 с), коли CI швидкий; збільште його на повільних спільних runner-ах. -- **Потрібні відредаговані тіла для звіту про ваду:** перезапустіть із `OPENCLAW_QA_MATRIX_CAPTURE_CONTENT=1` і додайте `matrix-qa-observed-events.json`. Вважайте отриманий артефакт чутливим. +- **Запуск зависає ближче до кінця:** нативні crypto-дескриптори `matrix-js-sdk` можуть пережити harness. Типово після запису артефакту примусово виконується чистий `process.exit`; якщо ви прибрали `OPENCLAW_QA_MATRIX_DISABLE_FORCE_EXIT=1`, очікуйте, що процес затримається. +- **Помилка очищення:** знайдіть надруковану команду відновлення (виклик `docker compose ... down --remove-orphans`) і виконайте її вручну, щоб звільнити порт homeserver. +- **Нестабільні вікна негативних тверджень у CI:** зменште `OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS` (типово 8 с), коли CI швидкий; збільште його на повільних спільних раннерах. +- **Потрібні відредаговані тіла для звіту про помилку:** повторіть запуск із `OPENCLAW_QA_MATRIX_CAPTURE_CONTENT=1` і додайте `matrix-qa-observed-events.json`. Вважайте отриманий артефакт чутливим. - **Інша версія Tuwunel:** спрямуйте `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE` на версію, що тестується. Lane перевіряє лише закріплений типовий образ. -## Контракт live-транспорту +## Контракт живого транспорту -Matrix — один із трьох lane live-транспорту (Matrix, Telegram, Discord), які спільно використовують єдиний контрольний список контракту, визначений у [огляді QA → Покриття live-транспорту](/uk/concepts/qa-e2e-automation#live-transport-coverage). `qa-channel` залишається широким синтетичним набором і навмисно не є частиною цієї матриці. +Matrix — один із трьох live transport lanes (Matrix, Telegram, Discord), що спільно використовують єдиний контрольний список контракту, визначений у [огляді QA → покриття живого транспорту](/uk/concepts/qa-e2e-automation#live-transport-coverage). `qa-channel` залишається широким синтетичним набором і навмисно не є частиною цієї матриці. ## Пов’язане -- [Огляд QA](/uk/concepts/qa-e2e-automation) — загальний стек QA та контракт live-транспорту -- [Канал QA](/uk/channels/qa-channel) — синтетичний адаптер каналу для сценаріїв, підтримуваних репозиторієм +- [Огляд QA](/uk/concepts/qa-e2e-automation) — загальний стек QA і контракт живого транспорту +- [QA Channel](/uk/channels/qa-channel) — синтетичний адаптер каналу для сценаріїв, підтримуваних репозиторієм - [Тестування](/uk/help/testing) — запуск тестів і додавання покриття QA -- [Matrix](/uk/channels/matrix) — плагін каналу, що тестується +- [Matrix](/uk/channels/matrix) — Plugin каналу, що тестується diff --git a/docs/uk/help/testing.md b/docs/uk/help/testing.md index f805f621d..3e656bfa3 100644 --- a/docs/uk/help/testing.md +++ b/docs/uk/help/testing.md @@ -2,34 +2,34 @@ read_when: - Запуск тестів локально або в CI - Додавання регресійних тестів для помилок моделей/провайдерів - - Налагодження поведінки Gateway + агента -summary: 'Комплект для тестування: набори unit/e2e/live-тестів, ранери Docker і що охоплює кожен тест' + - Налагодження Gateway + поведінки агента +summary: 'Набір для тестування: набори тестів unit/e2e/live, ранери Docker і що охоплює кожен тест' title: Тестування x-i18n: - generated_at: "2026-04-29T05:39:26Z" + generated_at: "2026-04-29T05:57:20Z" model: gpt-5.5 provider: openai - source_hash: 883840f97ca94a4e6b64cfce414da59ad3710ddd8e5e2e3ba04e33a83e96d407 + source_hash: 9b06c2e7905ca930f0cac92d43c5902d38b9513968a68d2077ff4ef7a5a345ce source_path: help/testing.md workflow: 16 --- -OpenClaw має три набори тестів Vitest (unit/integration, e2e, live) і невеликий набір +OpenClaw має три набори Vitest (unit/integration, e2e, live) і невеликий набір Docker-ранерів. Цей документ є посібником «як ми тестуємо»: -- Що покриває кожен набір (і що він навмисно _не_ покриває). +- Що покриває кожен набір (і що він свідомо _не_ покриває). - Які команди запускати для типових робочих процесів (локально, перед push, під час налагодження). - Як live-тести знаходять облікові дані та вибирають моделі/провайдерів. -- Як додавати регресійні тести для реальних проблем моделей/провайдерів. +- Як додавати регресії для реальних проблем моделей/провайдерів. -**QA-стек (qa-lab, qa-channel, live transport lanes)** задокументовано окремо: +**QA-стек (qa-lab, qa-channel, live transport lanes)** документовано окремо: - [Огляд QA](/uk/concepts/qa-e2e-automation) — архітектура, поверхня команд, створення сценаріїв. - [Matrix QA](/uk/concepts/qa-matrix) — довідник для `pnpm openclaw qa matrix`. -- [QA channel](/uk/channels/qa-channel) — синтетичний транспортний plugin, який використовують сценарії з репозиторію. +- [QA channel](/uk/channels/qa-channel) — синтетичний транспортний plugin, який використовується сценаріями на базі репозиторію. -Ця сторінка описує запуск звичайних наборів тестів і Docker/Parallels-ранерів. Розділ QA-специфічних раннерів нижче ([QA-специфічні ранери](#qa-specific-runners)) перелічує конкретні виклики `qa` і вказує назад на наведені вище довідники. +Ця сторінка описує запуск звичайних тестових наборів і Docker/Parallels-ранерів. Розділ нижче, присвячений QA-специфічним ранерам ([QA-специфічні ранери](#qa-specific-runners)), перелічує конкретні виклики `qa` і посилається назад на наведені вище довідники. ## Швидкий старт @@ -37,151 +37,151 @@ Docker-ранерів. Цей документ є посібником «як м У більшість днів: - Повний gate (очікується перед push): `pnpm build && pnpm check && pnpm check:test-types && pnpm test` -- Швидший локальний запуск повного набору на машині з достатніми ресурсами: `pnpm test:max` -- Прямий watch-цикл Vitest: `pnpm test:watch` -- Пряме таргетування файлів тепер також маршрутизує шляхи extension/channel: `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` -- Під час ітерацій над одним падінням спершу віддавайте перевагу таргетованим запускам. +- Швидший локальний запуск повного набору на потужній машині: `pnpm test:max` +- Прямий цикл Vitest watch: `pnpm test:watch` +- Пряме націлювання на файл тепер також маршрутизує шляхи extension/channel: `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` +- Під час ітерацій над одним збоєм спочатку віддавайте перевагу цільовим запускам. - Docker-backed QA site: `pnpm qa:lab:up` - Linux VM-backed QA lane: `pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline` Коли ви змінюєте тести або хочете додаткової впевненості: -- Gate покриття: `pnpm test:coverage` -- Набір E2E: `pnpm test:e2e` +- Coverage gate: `pnpm test:coverage` +- E2E-набір: `pnpm test:e2e` -Під час налагодження реальних провайдерів/моделей (потрібні реальні облікові дані): +Під час налагодження реальних провайдерів/моделей (потрібні справжні облікові дані): -- Live-набір (моделі + перевірки інструментів/зображень Gateway): `pnpm test:live` -- Таргетувати один live-файл тихо: `pnpm test:live -- src/agents/models.profiles.live.test.ts` +- Live-набір (моделі + gateway tool/image probes): `pnpm test:live` +- Тихо націлитися на один live-файл: `pnpm test:live -- src/agents/models.profiles.live.test.ts` - Docker live model sweep: `pnpm test:docker:live-models` - - Кожна вибрана модель тепер виконує текстовий turn плюс невелику перевірку в стилі читання файлу. - Моделі, метадані яких оголошують вхід `image`, також виконують крихітний image turn. - Вимикайте додаткові перевірки через `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` або + - Кожна вибрана модель тепер виконує текстовий хід плюс невелику перевірку в стилі читання файлу. + Моделі, метадані яких оголошують вхід `image`, також виконують крихітний image-хід. + Вимкніть додаткові перевірки за допомогою `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` або `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0`, коли ізолюєте збої провайдера. - - Покриття CI: щоденний `OpenClaw Scheduled Live And E2E Checks` і ручний - `OpenClaw Release Checks` обидва викликають перевикористовуваний live/E2E workflow з + - Покриття CI: щоденні `OpenClaw Scheduled Live And E2E Checks` і ручні + `OpenClaw Release Checks` обидва викликають reusable live/E2E workflow з `include_live_suites: true`, що включає окремі Docker live model - matrix jobs, розшардовані за провайдером. - - Для сфокусованих повторних запусків CI запускайте `OpenClaw Live And E2E Checks (Reusable)` + matrix jobs, розбиті за провайдерами. + - Для сфокусованих повторних запусків CI dispatch `OpenClaw Live And E2E Checks (Reusable)` з `include_live_suites: true` і `live_models_only: true`. - - Додавайте нові високосигнальні секрети провайдера до `scripts/ci-hydrate-live-auth.sh` + - Додавайте нові high-signal provider secrets до `scripts/ci-hydrate-live-auth.sh` плюс `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` і його scheduled/release callers. - Native Codex bound-chat smoke: `pnpm test:docker:live-codex-bind` - Запускає Docker live lane проти шляху Codex app-server, прив’язує синтетичний Slack DM через `/codex bind`, виконує `/codex fast` і - `/codex permissions`, потім перевіряє, що проста відповідь і вкладення зображення - проходять через нативне прив’язування plugin замість ACP. + `/codex permissions`, а потім перевіряє, що звичайна відповідь і вкладення зображення + проходять через native plugin binding замість ACP. - Codex app-server harness smoke: `pnpm test:docker:live-codex-harness` - - Запускає turns агента Gateway через harness Codex app-server, яким володіє plugin, - перевіряє `/codex status` і `/codex models`, і за замовчуванням виконує перевірки image, - cron MCP, sub-agent і Guardian. Вимикайте перевірку sub-agent через + - Запускає gateway agent turns через Codex app-server harness, яким володіє plugin, + перевіряє `/codex status` і `/codex models`, а за замовчуванням виконує image, + cron MCP, sub-agent і Guardian probes. Вимкніть sub-agent probe за допомогою `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0`, коли ізолюєте інші збої Codex - app-server. Для сфокусованої перевірки sub-agent вимикайте інші перевірки: + app-server. Для сфокусованої sub-agent перевірки вимкніть інші перевірки: `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=1 pnpm test:docker:live-codex-harness`. - Це завершується після перевірки sub-agent, якщо не встановлено + Це завершується після sub-agent probe, якщо не встановлено `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0`. -- Smoke команди порятунку Crestodian: `pnpm test:live:crestodian-rescue-channel` - - Opt-in перевірка «belt-and-suspenders» для поверхні команди порятунку message-channel. - Вона виконує `/crestodian status`, ставить у чергу постійну зміну моделі, - відповідає `/crestodian yes` і перевіряє шлях запису audit/config. -- Docker smoke планувальника Crestodian: `pnpm test:docker:crestodian-planner` +- Crestodian rescue command smoke: `pnpm test:live:crestodian-rescue-channel` + - Opt-in belt-and-suspenders перевірка для поверхні rescue command каналу повідомлень. + Вона виконує `/crestodian status`, ставить у чергу persistent model + change, відповідає `/crestodian yes` і перевіряє шлях audit/config write. +- Crestodian planner Docker smoke: `pnpm test:docker:crestodian-planner` - Запускає Crestodian у контейнері без конфігурації з фальшивим Claude CLI у `PATH` - і перевіряє, що fuzzy planner fallback перетворюється на аудитований типізований - запис конфігурації. -- Docker smoke першого запуску Crestodian: `pnpm test:docker:crestodian-first-run` - - Стартує з порожнього каталогу стану OpenClaw, маршрутизує голий `openclaw` до - Crestodian, застосовує setup/model/agent/Discord plugin + записи SecretRef, - валідовує конфігурацію та перевіряє записи audit. Той самий шлях Ring 0 setup - також покрито в QA Lab через + і перевіряє, що fuzzy planner fallback перетворюється на audited typed + config write. +- Crestodian first-run Docker smoke: `pnpm test:docker:crestodian-first-run` + - Починає з порожнього каталогу стану OpenClaw, маршрутизує голий `openclaw` до + Crestodian, застосовує setup/model/agent/Discord plugin + SecretRef writes, + перевіряє конфігурацію та audit entries. Той самий шлях Ring 0 setup також + покрито в QA Lab через `pnpm openclaw qa suite --scenario crestodian-ring-zero-setup`. -- Moonshot/Kimi cost smoke: з установленим `MOONSHOT_API_KEY` запустіть +- Moonshot/Kimi cost smoke: із встановленим `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 і - transcript асистента зберігає нормалізоване `usage.cost`. + проти `moonshot/kimi-k2.6`. Перевірте, що JSON повідомляє Moonshot/K2.6, а + assistant transcript зберігає нормалізоване `usage.cost`. -Коли вам потрібен лише один failing case, віддавайте перевагу звуженню live-тестів через allowlist env vars, описані нижче. +Коли потрібен лише один збійний випадок, віддавайте перевагу звуженню live-тестів через allowlist env vars, описані нижче. ## 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, +CI запускає QA Lab у виділених workflow. `Parity gate` запускається на відповідних PR і +з manual dispatch із mock providers. `QA-Lab - All Lanes` запускається щоночі на +`main` і з manual dispatch з mock parity gate, live Matrix lane, Convex-managed live Telegram lane і Convex-managed live Discord lane як -паралельні jobs. Scheduled QA і release checks явно передають Matrix `--profile fast`, -тоді як Matrix CLI і manual workflow input за замовчуванням залишаються -`all`; ручний dispatch може шардити `all` на `transport`, `media`, `e2ee-smoke`, +parallel jobs. Scheduled QA і release checks передають Matrix `--profile fast` +явно, тоді як Matrix CLI і manual workflow input default залишаються +`all`; manual dispatch може розбити `all` на `transport`, `media`, `e2ee-smoke`, `e2ee-deep` і `e2ee-cli` jobs. `OpenClaw Release Checks` запускає parity плюс -fast Matrix і Telegram lanes перед затвердженням релізу, використовуючи -`mock-openai/gpt-5.5` для release transport checks, щоб вони залишалися детермінованими -і уникали звичайного startup provider-plugin. Ці live transport gateways вимикають -memory search; поведінка memory залишається покритою QA parity suites. +fast Matrix і Telegram lanes перед release approval, використовуючи +`mock-openai/gpt-5.5` для release transport checks, щоб вони лишалися детермінованими +і уникали звичайного запуску provider-plugin. Ці live transport gateways вимикають +memory search; поведінка пам’яті лишається покритою QA parity suites. Full release live media shards використовують `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04`, який уже має `ffmpeg` і `ffprobe`. Docker live model/backend shards використовують спільний образ `ghcr.io/openclaw/openclaw-live-test:`, зібраний один раз для вибраного -commit, а потім завантажують його з `OPENCLAW_SKIP_DOCKER_BUILD=1` замість перебудови -в кожному shard. +commit, а потім тягнуть його з `OPENCLAW_SKIP_DOCKER_BUILD=1` замість повторного збирання +всередині кожного shard. - `pnpm openclaw qa suite` - - Запускає QA-сценарії з репозиторію безпосередньо на host. - - За замовчуванням запускає кілька вибраних сценаріїв паралельно з ізольованими + - Запускає repo-backed QA scenarios безпосередньо на хості. + - Запускає кілька вибраних scenarios паралельно за замовчуванням з ізольованими gateway workers. `qa-channel` за замовчуванням має concurrency 4 (обмежено - кількістю вибраних сценаріїв). Використовуйте `--concurrency `, щоб налаштувати - кількість workers, або `--concurrency 1` для старішої serial lane. - - Завершується з ненульовим кодом, якщо будь-який сценарій падає. Використовуйте `--allow-failures`, коли вам - потрібні artifacts без failing exit code. - - Підтримує режими провайдера `live-frontier`, `mock-openai` і `aimock`. - `aimock` запускає локальний provider server на базі AIMock для експериментального - покриття fixture і protocol-mock без заміни scenario-aware + кількістю вибраних scenarios). Використовуйте `--concurrency `, щоб налаштувати + кількість workers, або `--concurrency 1` для старішого serial lane. + - Завершується з ненульовим кодом, коли будь-який scenario зазнає невдачі. Використовуйте `--allow-failures`, коли + потрібні артефакти без failing exit code. + - Підтримує provider modes `live-frontier`, `mock-openai` і `aimock`. + `aimock` запускає локальний AIMock-backed provider server для експериментального + fixture і protocol-mock coverage без заміни scenario-aware `mock-openai` lane. - `pnpm test:gateway:cpu-scenarios` - - Запускає bench старту Gateway плюс невеликий пакет mock QA Lab сценаріїв + - Запускає gateway startup bench плюс невеликий mock QA Lab scenario pack (`channel-chat-baseline`, `memory-failure-fallback`, - `gateway-restart-inflight-run`) і записує об’єднаний підсумок CPU-спостережень - у `.artifacts/gateway-cpu-scenarios/`. - - За замовчуванням позначає лише сталі hot CPU observations (`--cpu-core-warn` - плюс `--hot-wall-warn-ms`), тож короткі startup bursts записуються як metrics - і не виглядають як minutes-long gateway peg regression. - - Використовує зібрані artifacts `dist`; спершу запустіть build, якщо checkout ще не має - свіжого runtime output. + `gateway-restart-inflight-run`) і записує об’єднаний CPU observation + summary у `.artifacts/gateway-cpu-scenarios/`. + - За замовчуванням позначає лише sustained hot CPU observations (`--cpu-core-warn` + плюс `--hot-wall-warn-ms`), тому короткі startup bursts записуються як metrics + без вигляду minutes-long gateway peg regression. + - Використовує зібрані `dist` artifacts; спочатку запустіть build, коли checkout не + має свіжого runtime output. - `pnpm openclaw qa suite --runner multipass` - - Запускає той самий QA suite всередині disposable Multipass Linux VM. - - Зберігає ту саму поведінку вибору сценаріїв, що й `qa suite` на host. - - Повторно використовує ті самі flags вибору провайдера/моделі, що й `qa suite`. - - Live-запуски передають підтримувані QA auth inputs, практичні для guest: + - Запускає той самий QA-набір усередині одноразової Multipass Linux VM. + - Зберігає ту саму поведінку scenario-selection, що й `qa suite` на хості. + - Повторно використовує ті самі provider/model selection flags, що й `qa suite`. + - Live-запуски пересилають підтримувані QA auth inputs, практичні для guest: env-based provider keys, шлях QA live provider config і `CODEX_HOME`, коли він присутній. - - Output dirs мають залишатися під коренем репозиторію, щоб guest міг записувати назад через + - Output dirs мають лишатися в межах кореня репозиторію, щоб guest міг записувати назад через змонтований workspace. - Записує звичайний QA report + summary плюс Multipass logs у `.artifacts/qa-e2e/...`. - `pnpm qa:lab:up` - Запускає Docker-backed QA site для operator-style QA work. - `pnpm test:docker:npm-onboard-channel-agent` - - Збирає npm tarball з поточного checkout, глобально встановлює його в + - Збирає npm tarball з поточного checkout, встановлює його глобально в Docker, запускає non-interactive OpenAI API-key onboarding, за замовчуванням налаштовує Telegram, - перевіряє, що вмикання plugin встановлює runtime dependencies на вимогу, - запускає doctor і виконує один local agent turn проти mocked OpenAI + перевіряє, що ввімкнення plugin встановлює runtime dependencies на вимогу, + запускає doctor і виконує один локальний agent turn проти mocked OpenAI endpoint. - Використовуйте `OPENCLAW_NPM_ONBOARD_CHANNEL=discord`, щоб запустити той самий packaged-install lane з Discord. - `pnpm test:docker:session-runtime-context` - - Запускає детермінований built-app Docker smoke для transcripts embedded runtime context. - Він перевіряє, що прихований OpenClaw runtime context зберігається як + - Запускає детермінований built-app Docker smoke для embedded runtime context + transcripts. Він перевіряє, що прихований OpenClaw runtime context зберігається як non-display custom message замість витоку у видимий user turn, - потім засіває affected broken session JSONL і перевіряє, що + потім сіє affected broken session JSONL і перевіряє, що `openclaw doctor --fix` переписує його на active branch із backup. - `pnpm test:docker:npm-telegram-live` - - Встановлює candidate пакета OpenClaw у Docker, запускає installed-package + - Встановлює candidate package OpenClaw у Docker, запускає installed-package onboarding, налаштовує Telegram через installed CLI, потім повторно використовує - live Telegram QA lane з тим установленим пакетом як SUT Gateway. + live Telegram QA lane з цим installed package як SUT Gateway. - За замовчуванням використовує `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`; встановіть `OPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgz` або `OPENCLAW_CURRENT_PACKAGE_TGZ`, щоб тестувати resolved local tarball замість @@ -193,18 +193,18 @@ commit, а потім завантажують його з `OPENCLAW_SKIP_DOCKER `OPENCLAW_QA_CONVEX_SITE_URL` і Convex role secret присутні в CI, Docker wrapper автоматично вибирає Convex. - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` перевизначає спільний - `OPENCLAW_QA_CREDENTIAL_ROLE` лише для цієї lane. - - GitHub Actions експонує цю lane як ручний maintainer workflow + `OPENCLAW_QA_CREDENTIAL_ROLE` лише для цього lane. + - GitHub Actions надає цей lane як ручний maintainer workflow `NPM Telegram Beta E2E`. Він не запускається під час merge. Workflow використовує середовище `qa-live-shared` і Convex CI credential leases. -- GitHub Actions також експонує `Package Acceptance` для side-run product proof +- GitHub Actions також надає `Package Acceptance` для side-run product proof проти одного candidate package. Він приймає trusted ref, published npm spec, HTTPS tarball URL плюс SHA-256 або tarball artifact з іншого run, завантажує - нормалізований `openclaw-current.tgz` як `package-under-test`, потім запускає - наявний Docker E2E scheduler зі smoke, package, product, full або custom + нормалізований `openclaw-current.tgz` як `package-under-test`, а потім запускає + existing Docker E2E scheduler зі smoke, package, product, full або custom lane profiles. Встановіть `telegram_mode=mock-openai` або `live-frontier`, щоб запустити Telegram QA workflow проти того самого artifact `package-under-test`. - - Останнє beta product proof: + - Latest beta product proof: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -214,7 +214,7 @@ gh workflow run package-acceptance.yml --ref main \ -f telegram_mode=mock-openai ``` -- Доказ exact tarball URL потребує digest: +- Exact tarball URL proof вимагає digest: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -224,7 +224,7 @@ gh workflow run package-acceptance.yml --ref main \ -f suite_profile=package ``` -- Доказ артефакта завантажує tarball-артефакт з іншого запуску Actions: +- Доказ артефакту завантажує артефакт tarball з іншого запуску Actions: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -236,29 +236,25 @@ gh workflow run package-acceptance.yml --ref main \ - `pnpm test:docker:bundled-channel-deps` - Пакує та встановлює поточну збірку OpenClaw у Docker, запускає Gateway - з налаштованим OpenAI, а потім вмикає вбудовані канали/plugins через - редагування конфігурації. - - Перевіряє, що виявлення налаштування залишає неналаштовані runtime-залежності plugin - відсутніми, перший налаштований запуск Gateway або doctor встановлює runtime-залежності кожного вбудованого - plugin на вимогу, а другий перезапуск не перевстановлює - залежності, які вже було активовано. + з налаштованим OpenAI, а потім вмикає вбудовані канали/Plugin через зміни + конфігурації. + - Перевіряє, що виявлення налаштування залишає відсутніми неналаштовані runtime-залежності Plugin, перший налаштований запуск Gateway або doctor встановлює runtime-залежності кожного вбудованого + Plugin на вимогу, а другий перезапуск не перевстановлює залежності, які вже були активовані. - Також встановлює відому старішу базову версію npm, вмикає Telegram перед запуском - `openclaw update --tag ` і перевіряє, що post-update doctor кандидата - виправляє runtime-залежності вбудованого каналу без - postinstall-виправлення на боці harness. + `openclaw update --tag ` і перевіряє, що post-update doctor кандидата відновлює runtime-залежності вбудованого каналу без + postinstall-відновлення на стороні harness. - `pnpm test:parallels:npm-update` - - Запускає smoke-перевірку оновлення нативного packaged-install у гостьових системах Parallels. Кожна - вибрана платформа спершу встановлює запитаний базовий пакет, потім запускає - встановлену команду `openclaw update` у тій самій гостьовій системі та перевіряє - встановлену версію, статус оновлення, готовність gateway і один локальний хід агента. + - Запускає native smoke оновлення packaged-install у гостях Parallels. Кожна + вибрана платформа спочатку встановлює запитаний базовий пакет, потім запускає + встановлену команду `openclaw update` у тому самому гості та перевіряє + встановлену версію, статус оновлення, готовність Gateway і один локальний хід агента. - Використовуйте `--platform macos`, `--platform windows` або `--platform linux` під час - ітерацій на одній гостьовій системі. Використовуйте `--json` для шляху до підсумкового артефакта та - статусу кожної lane. - - Lane OpenAI за замовчуванням використовує `openai/gpt-5.5` для live-доказу ходу агента. - Передайте `--model ` або задайте + ітерацій з одним гостем. Використовуйте `--json` для шляху до підсумкового артефакту та + статусу по кожній лінії. + - Лінія OpenAI типово використовує `openai/gpt-5.5` для live-доказу ходу агента. Передайте `--model ` або встановіть `OPENCLAW_PARALLELS_OPENAI_MODEL`, коли навмисно перевіряєте іншу модель OpenAI. - - Обгортайте довгі локальні запуски в host timeout, щоб зависання транспорту Parallels не + - Обгортайте довгі локальні запуски в timeout хоста, щоб зависання транспорту Parallels не використали решту вікна тестування: ```bash @@ -266,17 +262,17 @@ gh workflow run package-acceptance.yml --ref main \ timeout --foreground 90m pnpm test:parallels:npm-update -- --platform windows --json ``` - - Скрипт записує вкладені журнали lane у `/tmp/openclaw-parallels-npm-update.*`. + - Скрипт записує вкладені журнали ліній у `/tmp/openclaw-parallels-npm-update.*`. Перегляньте `windows-update.log`, `macos-update.log` або `linux-update.log`, перш ніж припускати, що зовнішня обгортка зависла. - - Оновлення Windows може витрачати 10-15 хвилин на post-update doctor/runtime - виправлення залежностей у холодній гостьовій системі; це все ще нормальний стан, якщо вкладений - журнал npm debug просувається. - - Не запускайте цю агрегувальну обгортку паралельно з окремими smoke lanes Parallels - macOS, Windows або Linux. Вони спільно використовують стан VM і можуть конфліктувати під час - відновлення snapshot, подавання пакета або стану gateway у гостьовій системі. - - Post-update proof запускає звичайну поверхню вбудованого plugin, тому що - facade можливостей, як-от мовлення, генерація зображень і розуміння медіа, + - Оновлення Windows може витратити 10-15 хвилин на post-update doctor/runtime + відновлення залежностей на холодному гості; це все ще нормальний стан, якщо вкладений + debug-журнал npm просувається. + - Не запускайте цю агрегатну обгортку паралельно з окремими smoke-лініями Parallels + для macOS, Windows або Linux. Вони спільно використовують стан VM і можуть конфліктувати під час + відновлення snapshot, обслуговування пакета або стану Gateway у гості. + - Post-update-доказ запускає звичайну поверхню вбудованого Plugin, оскільки + фасади можливостей, як-от мовлення, генерація зображень і розуміння медіа, завантажуються через вбудовані runtime API, навіть коли сам хід агента перевіряє лише просту текстову відповідь. @@ -284,25 +280,25 @@ gh workflow run package-acceptance.yml --ref main \ - Запускає лише локальний сервер провайдера AIMock для прямого smoke-тестування протоколу. - `pnpm openclaw qa matrix` - - Запускає live QA lane Matrix проти одноразового homeserver Tuwunel на базі Docker. Лише source-checkout — packaged installs не постачають `qa-lab`. + - Запускає live-лінію QA Matrix проти одноразового homeserver Tuwunel на базі Docker. Лише source-checkout — packaged installs не постачають `qa-lab`. - Повний CLI, каталог профілів/сценаріїв, env vars і структура артефактів: [Matrix QA](/uk/concepts/qa-matrix). - `pnpm openclaw qa telegram` - - Запускає live QA lane Telegram проти справжньої приватної групи з використанням токенів driver і SUT bot з env. - - Потребує `OPENCLAW_QA_TELEGRAM_GROUP_ID`, `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` і `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`. Group id має бути числовим Telegram chat id. - - Підтримує `--credential-source convex` для спільних pooled credentials. За замовчуванням використовуйте режим env або задайте `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`, щоб увімкнути pooled leases. - - Завершується з ненульовим кодом, коли будь-який сценарій завершується помилкою. Використовуйте `--allow-failures`, коли вам - потрібні артефакти без failing exit code. - - Потребує двох окремих ботів в одній приватній групі, причому SUT bot має надавати Telegram username. - - Для стабільного спостереження bot-to-bot увімкніть Bot-to-Bot Communication Mode у `@BotFather` для обох ботів і переконайтеся, що driver bot може спостерігати трафік ботів у групі. - - Записує звіт Telegram QA, підсумок і артефакт observed-messages у `.artifacts/qa-e2e/...`. Сценарії з відповідями включають RTT від запиту надсилання driver до спостереженої відповіді SUT. + - Запускає live-лінію QA Telegram проти справжньої приватної групи, використовуючи токени driver і SUT bot з env. + - Потребує `OPENCLAW_QA_TELEGRAM_GROUP_ID`, `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` і `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`. Ідентифікатор групи має бути числовим chat id Telegram. + - Підтримує `--credential-source convex` для спільних pooled credentials. Типово використовуйте режим env або встановіть `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`, щоб увімкнути pooled leases. + - Завершується з ненульовим кодом, коли будь-який сценарій завершується невдало. Використовуйте `--allow-failures`, коли вам + потрібні артефакти без коду завершення з помилкою. + - Потребує двох різних bot в одній приватній групі, причому SUT bot має надавати username Telegram. + - Для стабільного спостереження bot-to-bot увімкніть Bot-to-Bot Communication Mode у `@BotFather` для обох bot і переконайтеся, що driver bot може спостерігати груповий bot traffic. + - Записує звіт Telegram QA, підсумок і артефакт observed-messages у `.artifacts/qa-e2e/...`. Сценарії відповідей містять RTT від запиту надсилання driver до спостереженої відповіді SUT. -Live transport lanes мають один стандартний контракт, щоб нові транспорти не відхилялися; матриця покриття для кожної lane міститься в [огляд QA → Покриття live transport](/uk/concepts/qa-e2e-automation#live-transport-coverage). `qa-channel` — це широкий synthetic suite і не є частиною цієї матриці. +Live transport lines мають спільний стандартний контракт, щоб нові транспорти не відхилялися; матриця покриття по кожній лінії міститься в [Огляд QA → Покриття live transport](/uk/concepts/qa-e2e-automation#live-transport-coverage). `qa-channel` — це широкий синтетичний набір і він не є частиною цієї матриці. ### Спільні облікові дані Telegram через Convex (v1) Коли `--credential-source convex` (або `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`) увімкнено для -`openclaw qa telegram`, QA lab отримує ексклюзивний lease з pool на базі Convex, надсилає heartbeats -для цього lease, поки lane виконується, і звільняє lease під час shutdown. +`openclaw qa telegram`, QA lab отримує ексклюзивну lease зі спільного пулу на базі Convex, надсилає Heartbeat +для цієї lease, поки лінія виконується, і звільняє lease під час завершення. Еталонний scaffold проєкту Convex: @@ -311,29 +307,29 @@ Live transport lanes мають один стандартний контракт Обов’язкові env vars: - `OPENCLAW_QA_CONVEX_SITE_URL` (наприклад `https://your-deployment.convex.site`) -- Один секрет для вибраної ролі: +- Один secret для вибраної ролі: - `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 vars: -- `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` дозволяє URL Convex з loopback `http://` лише для локальної розробки. +- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` дозволяє loopback `http://` URL Convex для суто локальної розробки. -`OPENCLAW_QA_CONVEX_SITE_URL` має використовувати `https://` у звичайній роботі. +`OPENCLAW_QA_CONVEX_SITE_URL` у звичайній роботі має використовувати `https://`. -Адміністративні команди maintainer (pool add/remove/list) потребують +Admin-команди maintainer (додати/видалити/перелічити пул) вимагають саме `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`. -CLI helpers для maintainers: +CLI helpers для maintainer: ```bash pnpm openclaw qa credentials doctor @@ -343,11 +339,11 @@ pnpm openclaw qa credentials remove --credential-id ``` Використовуйте `doctor` перед live-запусками, щоб перевірити URL сайту Convex, broker secrets, -endpoint prefix, HTTP timeout і доступність admin/list без виведення -секретних значень. Використовуйте `--json` для machine-readable output у scripts і CI +префікс endpoint, HTTP timeout і доступність admin/list без друку +secret values. Використовуйте `--json` для машинно-читаного виводу в скриптах і CI utilities. -Стандартний endpoint contract (`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): +Типовий контракт endpoint (`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): - `POST /acquire` - Запит: `{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs }` @@ -365,417 +361,426 @@ utilities. - `POST /admin/remove` (лише maintainer secret) - Запит: `{ credentialId, actorId }` - Успіх: `{ status: "ok", changed, credential }` - - Active lease guard: `{ status: "error", code: "LEASE_ACTIVE", ... }` + - Захист активної lease: `{ status: "error", code: "LEASE_ACTIVE", ... }` - `POST /admin/list` (лише maintainer secret) - Запит: `{ kind?, status?, includePayload?, limit? }` - Успіх: `{ status: "ok", credentials, count }` -Форма payload для виду Telegram: +Форма payload для Telegram kind: - `{ groupId: string, driverToken: string, sutToken: string }` -- `groupId` має бути рядком numeric Telegram chat id. -- `admin/add` перевіряє цю форму для `kind: "telegram"` і відхиляє malformed payloads. +- `groupId` має бути числовим рядком chat id Telegram. +- `admin/add` перевіряє цю форму для `kind: "telegram"` і відхиляє некоректні payloads. ### Додавання каналу до QA -Назви архітектури та scenario-helper для нових адаптерів каналів описані в [огляд QA → Додавання каналу](/uk/concepts/qa-e2e-automation#adding-a-channel). Мінімальна вимога: реалізувати transport runner на спільному host seam `qa-lab`, оголосити `qaRunners` у manifest plugin, змонтувати як `openclaw qa ` і створити сценарії в `qa/scenarios/`. +Архітектура та імена scenario-helper для нових адаптерів каналів описані в [Огляд QA → Додавання каналу](/uk/concepts/qa-e2e-automation#adding-a-channel). Мінімальна планка: реалізувати transport runner на спільному host seam `qa-lab`, оголосити `qaRunners` у маніфесті Plugin, змонтувати як `openclaw qa ` і створити сценарії в `qa/scenarios/`. -## Тестові набори (що де запускається) +## Набори тестів (що де запускається) -Думайте про набори як про “зростальну реалістичність” (і зростальну нестабільність/вартість): +Думайте про набори як про «зростання реалістичності» (і зростання flaky/cost): -### Unit / integration (за замовчуванням) +### Unit / integration (типово) - Команда: `pnpm test` -- Конфігурація: нецільові запуски використовують набір shard `vitest.full-*.config.ts` і можуть розгортати multi-project shards у per-project configs для паралельного планування +- Конфігурація: нецільові запуски використовують shard set `vitest.full-*.config.ts` і можуть розгортати multi-project shards у per-project configs для паралельного планування - Файли: core/unit inventories у `src/**/*.test.ts`, `packages/**/*.test.ts` і `test/**/*.test.ts`; UI unit tests запускаються у виділеному shard `unit-ui` -- Обсяг: +- Область: - Чисті unit tests - - In-process integration tests (gateway auth, routing, tooling, parsing, config) - - Детерміновані регресії для відомих помилок + - In-process integration tests (автентифікація Gateway, маршрутизація, tooling, parsing, config) + - Детерміновані регресії для відомих bugs - Очікування: - Запускається в CI - - Реальні ключі не потрібні + - Не потребує справжніх ключів - Має бути швидким і стабільним + - Тести resolver і public-surface loader мають доводити широку fallback-поведінку `api.js` і + `runtime-api.js` з generated tiny plugin fixtures, а не + реальними bundled plugin source APIs. Реальні завантаження plugin API належать до + contract/integration suites, власником яких є Plugin. - - Ненацілені запуски `pnpm test` виконують дванадцять менших конфігурацій шардів (`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`) замість одного величезного нативного процесу кореневого проєкту. Це зменшує піковий RSS на навантажених машинах і не дає роботі auto-reply/extension виснажувати ресурси для непов'язаних наборів тестів. - - `pnpm test --watch` досі використовує нативний граф проєктів кореневого `vitest.config.ts`, оскільки цикл спостереження з багатьма шардами непрактичний. - - `pnpm test`, `pnpm test:watch` і `pnpm test:perf:imports` спершу спрямовують явні цілі файлів/каталогів через scoped lanes, тому `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` не платить повну вартість запуску кореневого проєкту. - - `pnpm test:changed` за замовчуванням розгортає змінені git-шляхи в дешеві scoped lanes: прямі редагування тестів, сусідні файли `*.test.ts`, явні зіставлення джерел і локальні залежні файли з import graph. Редагування config/setup/package не запускають тести широко, якщо ви явно не використаєте `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`. - - `pnpm check:changed` є звичайним розумним локальним контрольним gate для вузьких змін. Він класифікує diff на core, core tests, extensions, extension tests, apps, docs, release metadata, live Docker tooling і tooling, а потім запускає відповідні команди typecheck, lint і guard. Він не запускає Vitest-тести; для тестового підтвердження викликайте `pnpm test:changed` або явний `pnpm test `. Version bumps лише для release metadata запускають цільові перевірки version/config/root-dependency з guard, який відхиляє зміни package поза верхньорівневим полем version. - - Редагування live Docker ACP harness запускають сфокусовані перевірки: синтаксис shell для live Docker auth-скриптів і dry-run планувальника live Docker. Зміни `package.json` включаються лише тоді, коли diff обмежений `scripts["test:docker:live-*"]`; зміни dependency, export, version та інших package-surface досі використовують ширші guards. - - Import-light unit-тести з agents, commands, plugins, auto-reply helpers, `plugin-sdk` та подібних чистих utility-областей спрямовуються через lane `unit-fast`, який пропускає `test/setup-openclaw-runtime.ts`; stateful/runtime-heavy файли лишаються на наявних lanes. - - Вибрані helper source-файли `plugin-sdk` і `commands` також зіставляють changed-mode запуски з явними сусідніми тестами в цих легких lanes, тому редагування helper-ів не перезапускають увесь важкий набір для цього каталогу. - - `auto-reply` має окремі buckets для верхньорівневих core helpers, верхньорівневих integration-тестів `reply.*` і піддерева `src/auto-reply/reply/**`. CI додатково розділяє піддерево reply на shards agent-runner, dispatch і commands/state-routing, щоб один import-heavy bucket не володів усім Node-хвостом. + - Ненацілений `pnpm test` запускає дванадцять менших конфігурацій шардів (`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`) замість одного гігантського нативного процесу кореневого проєкту. Це зменшує піковий RSS на завантажених машинах і не дає роботі auto-reply/extension виснажувати ресурси для непов’язаних наборів тестів. + - `pnpm test --watch` і далі використовує нативний кореневий граф проєкту `vitest.config.ts`, бо цикл спостереження з кількома шардами непрактичний. + - `pnpm test`, `pnpm test:watch` і `pnpm test:perf:imports` спершу спрямовують явні цілі файлів/каталогів через обмежені за областю доріжки, тому `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` уникає повної стартової вартості кореневого проєкту. + - `pnpm test:changed` типово розгортає змінені git-шляхи в дешеві обмежені за областю доріжки: прямі зміни тестів, сусідні файли `*.test.ts`, явні зіставлення джерел і локальні залежні елементи графа імпортів. Зміни config/setup/package не запускають тести широко, якщо явно не використати `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`. + - `pnpm check:changed` — це звичайний розумний локальний контрольний gate для вузької роботи. Він класифікує diff на core, тести core, extensions, тести extension, застосунки, docs, метадані release, інструменти live Docker і tooling, а потім запускає відповідні команди typecheck, lint і guard. Він не запускає тести Vitest; для тестового доказу викликайте `pnpm test:changed` або явний `pnpm test `. Зміни версій лише в метаданих release запускають цільові перевірки версії/config/кореневих залежностей із guard, який відхиляє зміни package за межами поля версії верхнього рівня. + - Зміни live Docker ACP harness запускають сфокусовані перевірки: shell-синтаксис для скриптів live Docker auth і dry-run планувальника live Docker. Зміни `package.json` включаються лише тоді, коли diff обмежений `scripts["test:docker:live-*"]`; зміни залежностей, експорту, версії та інших поверхонь package і далі використовують ширші guards. + - Легкі щодо імпортів unit-тести з agents, commands, plugins, допоміжних засобів auto-reply, `plugin-sdk` і подібних ділянок чистих утиліт проходять через доріжку `unit-fast`, яка пропускає `test/setup-openclaw-runtime.ts`; файли зі станом або важкі щодо runtime залишаються на наявних доріжках. + - Вибрані вихідні файли допоміжних засобів `plugin-sdk` і `commands` також зіставляють запуски в режимі changed з явними сусідніми тестами в цих легких доріжках, тож зміни допоміжних засобів уникають повторного запуску всього важкого набору для цього каталогу. + - `auto-reply` має окремі групи для високорівневих допоміжних засобів core, високорівневих інтеграційних тестів `reply.*` і піддерева `src/auto-reply/reply/**`. CI додатково розділяє піддерево reply на шарди agent-runner, dispatch і commands/state-routing, щоб одна група, важка щодо імпортів, не займала весь Node-хвіст. + - Звичайний CI для PR/main навмисно пропускає пакетний sweep extension і shard `agentic-plugins`, призначений лише для release. Full Release Validation запускає дочірній CI з `full_release_validation=true`, що знову вмикає ці важкі щодо plugin/extension набори для кандидатів у release. - - Коли ви змінюєте вхідні дані виявлення message-tool або runtime-контекст compaction, + - Коли змінюєте вхідні дані виявлення message-tool або runtime-контекст compaction, зберігайте обидва рівні покриття. - - Додавайте сфокусовані регресійні helper-тести для меж чистої маршрутизації та нормалізації. - - Підтримуйте справність integration-наборів вбудованого runner: + - Додавайте сфокусовані регресійні перевірки допоміжних засобів для чистих меж + маршрутизації та нормалізації. + - Підтримуйте справність інтеграційних наборів вбудованого 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 ids і поведінка compaction досі проходять - через реальні шляхи `run.ts` / `compact.ts`; helper-only тести - не є достатньою заміною для цих integration-шляхів. + - Ці набори перевіряють, що scoped ids і поведінка compaction і далі проходять + через реальні шляхи `run.ts` / `compact.ts`; тести лише допоміжних засобів + не є достатньою заміною для цих інтеграційних шляхів. - + - - Базова конфігурація Vitest за замовчуванням використовує `threads`. + - Базова конфігурація Vitest типово використовує `threads`. - Спільна конфігурація Vitest фіксує `isolate: false` і використовує неізольований runner у кореневих проєктах, e2e та live-конфігураціях. - - Коренева UI lane зберігає своє налаштування `jsdom` та optimizer, але також працює на - спільному неізольованому runner. + - Коренева UI-доріжка зберігає свій setup і optimizer `jsdom`, але також працює + на спільному неізольованому runner. - Кожен shard `pnpm test` успадковує ті самі типові значення `threads` + `isolate: false` зі спільної конфігурації Vitest. - - `scripts/run-vitest.mjs` за замовчуванням додає `--no-maglev` для дочірніх Node-процесів + - `scripts/run-vitest.mjs` типово додає `--no-maglev` для дочірніх Node-процесів Vitest, щоб зменшити churn компіляції V8 під час великих локальних запусків. - Встановіть `OPENCLAW_VITEST_ENABLE_MAGLEV=1`, щоб порівняти зі штатною + Установіть `OPENCLAW_VITEST_ENABLE_MAGLEV=1`, щоб порівняти зі стандартною поведінкою V8. - - `pnpm changed:lanes` показує, які архітектурні lanes запускає diff. - - Pre-commit hook виконує лише форматування. Він повторно додає відформатовані файли до staging і - не запускає lint, typecheck або тести. - - Запускайте `pnpm check:changed` явно перед handoff або push, коли вам - потрібен розумний локальний check gate. - - `pnpm test:changed` за замовчуванням спрямовується через дешеві scoped lanes. Використовуйте + - `pnpm changed:lanes` показує, які архітектурні доріжки активує diff. + - Pre-commit hook виконує лише форматування. Він повторно додає відформатовані файли до staged + і не запускає lint, typecheck або тести. + - Запускайте `pnpm check:changed` явно перед передаванням роботи або push, коли вам + потрібен розумний локальний контрольний gate. + - `pnpm test:changed` типово проходить через дешеві обмежені за областю доріжки. Використовуйте `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed` лише тоді, коли agent - вирішує, що редагування harness, config, package або contract справді потребує ширшого + вирішить, що зміна harness, config, package або contract справді потребує ширшого покриття Vitest. - `pnpm test:max` і `pnpm test:changed:max` зберігають ту саму поведінку маршрутизації, - лише з вищим лімітом workers. - - Локальне автоматичне масштабування workers навмисно консервативне й відступає, + лише з вищим обмеженням worker. + - Локальне автомасштабування worker навмисно консервативне й відступає, коли середнє навантаження host уже високе, тому кілька одночасних - запусків Vitest за замовчуванням шкодять менше. + запусків Vitest типово завдають менше шкоди. - Базова конфігурація Vitest позначає проєкти/config-файли як - `forceRerunTriggers`, щоб reruns у changed-mode лишалися коректними, коли змінюється - wiring тестів. - - Конфігурація лишає `OPENCLAW_VITEST_FS_MODULE_CACHE` увімкненим на підтримуваних - hosts; встановіть `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`, якщо хочете - одне явне розташування cache для прямого profiling. + `forceRerunTriggers`, щоб повторні запуски в режимі changed залишалися коректними, коли змінюється + підключення тестів. + - Конфігурація залишає `OPENCLAW_VITEST_FS_MODULE_CACHE` увімкненим на підтримуваних + hosts; задайте `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`, якщо хочете + одне явне розташування кешу для прямого профілювання. - - `pnpm test:perf:imports` вмикає звітування Vitest про тривалість imports плюс - вивід import-breakdown. - - `pnpm test:perf:imports:changed` обмежує той самий profiling view файлами, - зміненими відносно `origin/main`. - - Дані timing шардів записуються в `.artifacts/vitest-shard-timings.json`. - Запуски whole-config використовують шлях config як ключ; include-pattern CI - shards додають назву shard, щоб filtered shards можна було відстежувати - окремо. - - Коли один hot test усе ще витрачає більшу частину часу на startup imports, - тримайте важкі dependencies за вузьким локальним швом `*.runtime.ts` і - mock-айте цей шов напряму замість deep-import runtime helpers лише - для передавання їх через `vi.mock(...)`. + - `pnpm test:perf:imports` вмикає звітування Vitest про тривалість імпортів, а також + вивід розбивки імпортів. + - `pnpm test:perf:imports:changed` обмежує той самий профільний перегляд + файлами, зміненими від `origin/main`. + - Дані часу шардів записуються до `.artifacts/vitest-shard-timings.json`. + Запуски всієї конфігурації використовують шлях конфігурації як ключ; CI-шарди + з include-патернами додають назву шарда, щоб відфільтровані шарди можна було + відстежувати окремо. + - Коли один гарячий тест усе ще витрачає більшість часу на стартові імпорти, + тримайте важкі залежності за вузьким локальним швом `*.runtime.ts` і + мокайте цей шов напряму, замість глибоко імпортувати runtime-хелпери лише + для того, щоб пропустити їх через `vi.mock(...)`. - `pnpm test:perf:changed:bench -- --ref ` порівнює маршрутизований - `test:changed` із нативним шляхом root-project для цього закоміченого - diff і друкує wall time плюс macOS max RSS. + `test:changed` із нативним шляхом кореневого проєкту для цього закоміченого + diff і виводить wall time, а також macOS max RSS. - `pnpm test:perf:changed:bench -- --worktree` бенчмаркить поточне - dirty tree, спрямовуючи список змінених файлів через + брудне дерево, маршрутизуючи список змінених файлів через `scripts/test-projects.mjs` і кореневу конфігурацію Vitest. - - `pnpm test:perf:profile:main` записує CPU profile main-thread для - startup Vitest/Vite і transform overhead. - - `pnpm test:perf:profile:runner` записує CPU+heap profiles runner для - unit-набору з вимкненим file parallelism. + - `pnpm test:perf:profile:main` записує CPU-профіль головного потоку для + накладних витрат запуску та трансформацій Vitest/Vite. + - `pnpm test:perf:profile:runner` записує CPU+heap-профілі runner для + unit-набору з вимкненим файловим паралелізмом. -### Стабільність (Gateway) +### Стабільність (gateway) - Команда: `pnpm test:stability:gateway` - Конфігурація: `vitest.gateway.config.ts`, примусово один worker - Область: - - Запускає реальний loopback Gateway із diagnostics, увімкненими за замовчуванням - - Проганяє синтетичне gateway-повідомлення, memory і large-payload churn через diagnostic event path + - Запускає справжній loopback Gateway із діагностикою, увімкненою за замовчуванням + - Проганяє синтетичний gateway-повідомлення, пам'ять і churn великих payload через шлях діагностичних подій - Запитує `diagnostics.stability` через Gateway WS RPC - - Покриває helpers persistence для diagnostic stability bundle - - Перевіряє, що recorder лишається bounded, синтетичні RSS samples лишаються в межах pressure budget, а глибини per-session queue повертаються до нуля + - Покриває хелпери збереження пакета діагностичної стабільності + - Перевіряє, що recorder залишається обмеженим, синтетичні RSS-семпли лишаються нижче бюджету тиску, а глибини черг для кожної сесії знову спадають до нуля - Очікування: - Безпечно для CI і без ключів - - Вузька lane для подальшої stability-regression роботи, не заміна повному набору Gateway + - Вузька лінія для подальшої роботи над регресіями стабільності, не заміна повного набору Gateway ### E2E (gateway smoke) - Команда: `pnpm test:e2e` - Конфігурація: `vitest.e2e.config.ts` -- Файли: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts` і bundled-plugin E2E-тести в `extensions/` -- Runtime defaults: - - Використовує Vitest `threads` з `isolate: false`, як і решта repo. - - Використовує adaptive workers (CI: до 2, локально: 1 за замовчуванням). - - За замовчуванням працює в silent mode, щоб зменшити overhead console I/O. -- Корисні overrides: +- Файли: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts` і E2E-тести bundled-plugin у `extensions/` +- Runtime-типові значення: + - Використовує Vitest `threads` з `isolate: false`, як і решта репозиторію. + - Використовує адаптивних workers (CI: до 2, локально: 1 за замовчуванням). + - За замовчуванням працює в тихому режимі, щоб зменшити накладні витрати console I/O. +- Корисні перевизначення: - `OPENCLAW_E2E_WORKERS=` для примусового встановлення кількості workers (обмежено 16). - - `OPENCLAW_E2E_VERBOSE=1` для повторного ввімкнення докладного console output. + - `OPENCLAW_E2E_VERBOSE=1` для повторного ввімкнення докладного виводу консолі. - Область: - - End-to-end поведінка multi-instance gateway - - Поверхні WebSocket/HTTP, pairing node і важчий networking + - Наскрізна поведінка gateway з кількома інстансами + - WebSocket/HTTP-поверхні, pairing Node і важча мережева взаємодія - Очікування: - - Запускається в CI (коли ввімкнено в pipeline) + - Працює в CI (коли ввімкнено в pipeline) - Реальні ключі не потрібні - Більше рухомих частин, ніж в unit-тестах (може бути повільніше) -### E2E: OpenShell backend smoke +### E2E: smoke бекенда OpenShell - Команда: `pnpm test:e2e:openshell` - Файл: `extensions/openshell/src/backend.e2e.test.ts` - Область: - - Запускає ізольований OpenShell gateway на host через Docker + - Запускає ізольований OpenShell gateway на хості через Docker - Створює sandbox із тимчасового локального Dockerfile - - Перевіряє OpenShell backend OpenClaw через реальний `sandbox ssh-config` + SSH exec + - Перевіряє бекенд OpenShell в OpenClaw через справжній `sandbox ssh-config` + SSH exec - Перевіряє remote-canonical поведінку файлової системи через sandbox fs bridge - Очікування: - Лише opt-in; не входить до стандартного запуску `pnpm test:e2e` - - Потребує локального CLI `openshell` і робочого Docker daemon - - Використовує ізольовані `HOME` / `XDG_CONFIG_HOME`, потім знищує test gateway і sandbox -- Корисні overrides: + - Потребує локального `openshell` CLI і робочого Docker daemon + - Використовує ізольовані `HOME` / `XDG_CONFIG_HOME`, а потім знищує тестовий gateway і sandbox +- Корисні перевизначення: - `OPENCLAW_E2E_OPENSHELL=1` для ввімкнення тесту під час ручного запуску ширшого e2e-набору - - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` для вказання нестандартного CLI binary або wrapper script + - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` для вказання нестандартного CLI-бінарника або wrapper-скрипта -### Live (реальні providers + реальні models) +### Live (реальні providers + реальні моделі) - Команда: `pnpm test:live` - Конфігурація: `vitest.live.config.ts` -- Файли: `src/**/*.live.test.ts`, `test/**/*.live.test.ts` і bundled-plugin live-тести в `extensions/` -- За замовчуванням: **увімкнено** через `pnpm test:live` (встановлює `OPENCLAW_LIVE_TEST=1`) +- Файли: `src/**/*.live.test.ts`, `test/**/*.live.test.ts` і live-тести bundled-plugin у `extensions/` +- Типово: **увімкнено** через `pnpm test:live` (встановлює `OPENCLAW_LIVE_TEST=1`) - Область: - “Чи цей provider/model справді працює _сьогодні_ з реальними creds?” - - Виявляти зміни provider format, особливості tool-calling, проблеми auth і поведінку rate limit + - Ловить зміни форматів provider, особливості tool-calling, проблеми auth і поведінку rate limit - Очікування: - - За задумом не є CI-stable (реальні networks, реальні policies providers, quotas, outages) + - За задумом не є стабільним для CI (реальні мережі, реальні політики provider, квоти, збої) - Коштує грошей / використовує rate limits - Надавайте перевагу запуску звужених піднаборів замість “усього” -- Live-запуски source-ять `~/.profile`, щоб отримати відсутні API keys. -- За замовчуванням live-запуски все одно ізолюють `HOME` і копіюють config/auth матеріал у тимчасовий test home, щоб unit fixtures не могли змінити ваш реальний `~/.openclaw`. -- Встановлюйте `OPENCLAW_LIVE_USE_REAL_HOME=1` лише тоді, коли вам навмисно потрібно, щоб live-тести використовували ваш реальний home directory. -- `pnpm test:live` тепер за замовчуванням працює в тихішому режимі: він зберігає progress output `[live] ...`, але приглушує додаткове повідомлення `~/.profile` і вимикає logs bootstrap Gateway/Bonjour chatter. Встановіть `OPENCLAW_LIVE_TEST_QUIET=0`, якщо хочете повернути повні startup logs. -- Ротація API keys (залежить від provider): встановіть `*_API_KEYS` у форматі з комами/крапками з комою або `*_API_KEY_1`, `*_API_KEY_2` (наприклад, `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) або per-live override через `OPENCLAW_LIVE_*_KEY`; тести повторюють спробу при відповідях rate limit. -- Вивід progress/Heartbeat: - - Live-набори тепер виводять progress lines у stderr, щоб довгі provider calls були помітно активними навіть тоді, коли console capture Vitest тихий. - - `vitest.live.config.ts` вимикає перехоплення console у Vitest, щоб progress lines provider/gateway одразу stream-илися під час live-запусків. - - Налаштовуйте direct-model Heartbeat через `OPENCLAW_LIVE_HEARTBEAT_MS`. +- Live-запуски source-ять `~/.profile`, щоб підхопити відсутні API-ключі. +- За замовчуванням live-запуски все одно ізолюють `HOME` і копіюють config/auth-матеріали в тимчасовий тестовий home, щоб unit-fixtures не могли змінити ваш справжній `~/.openclaw`. +- Встановлюйте `OPENCLAW_LIVE_USE_REAL_HOME=1` лише тоді, коли вам навмисно потрібно, щоб live-тести використовували ваш справжній домашній каталог. +- `pnpm test:live` тепер за замовчуванням працює тихіше: він залишає progress-вивід `[live] ...`, але приглушує додаткове повідомлення `~/.profile` і mute-ить логи bootstrap Gateway/Bonjour chatter. Встановіть `OPENCLAW_LIVE_TEST_QUIET=0`, якщо хочете повернути повні startup-логи. +- Ротація API-ключів (provider-specific): задайте `*_API_KEYS` у форматі з комами/крапками з комою або `*_API_KEY_1`, `*_API_KEY_2` (наприклад, `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) або per-live override через `OPENCLAW_LIVE_*_KEY`; тести повторюють спроби на відповідях rate limit. +- Вивід progress/heartbeat: + - Live-набори тепер виводять progress-рядки до stderr, щоб довгі provider-виклики були видимо активними навіть тоді, коли capture консолі Vitest тихий. + - `vitest.live.config.ts` вимикає перехоплення консолі Vitest, щоб progress-рядки provider/gateway стрімилися негайно під час live-запусків. + - Налаштовуйте Heartbeat direct-model через `OPENCLAW_LIVE_HEARTBEAT_MS`. - Налаштовуйте Heartbeat gateway/probe через `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS`. -## Який набір слід запускати? +## Який набір мені запускати? -Використовуйте цю таблицю рішень: +Скористайтеся цією таблицею рішень: -- Редагування logic/tests: запускайте `pnpm test` (і `pnpm test:coverage`, якщо ви змінили багато) -- Зачіпаєте gateway networking / WS protocol / pairing: додайте `pnpm test:e2e` -- Налагоджуєте “my bot is down” / provider-specific failures / tool calling: запускайте звужений `pnpm test:live` +- Редагування логіки/тестів: запустіть `pnpm test` (і `pnpm test:coverage`, якщо ви змінили багато) +- Зміни в мережевій частині Gateway / WS-протоколі / сполученні: додайте `pnpm test:e2e` +- Налагодження «мій бот не працює» / збоїв, специфічних для провайдера / виклику інструментів: запустіть звужений `pnpm test:live` -## Live (network-touching) tests +## Live-тести (що торкаються мережі) -Для актуальної матриці моделей, smoke-перевірок бекенда CLI, smoke-перевірок ACP, harness сервера застосунку Codex і всіх live-тестів медіапровайдерів (Deepgram, BytePlus, ComfyUI, зображення, музика, відео, медіа-harness) — а також обробки облікових даних для live-запусків — див. +Про live-матрицю моделей, smoke-тести бекенда CLI, smoke-тести ACP, тестовий +harness сервера застосунку Codex і всі live-тести медіапровайдерів (Deepgram, +BytePlus, ComfyUI, зображення, музика, відео, медіа-harness) — а також обробку +облікових даних для live-запусків — дивіться в [Тестування — live-набори](/uk/help/testing-live). ## Docker-ранери (необов’язкові перевірки «працює в Linux») Ці Docker-ранери поділяються на дві групи: -- 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`), монтують локальний каталог конфігурації та робочу область (і підвантажують `~/.profile`, якщо його змонтовано). Відповідні локальні точки входу: `test:live:models-profiles` і `test:live:gateway-profiles`. -- Docker live-ранери типово використовують менший ліміт smoke-перевірок, щоб повний Docker-прогін лишався практичним: - `test:docker:live-models` типово має `OPENCLAW_LIVE_MAX_MODELS=12`, а - `test:docker:live-gateway` типово має `OPENCLAW_LIVE_GATEWAY_SMOKE=1`, +- Ранери 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`), монтують ваш локальний каталог конфігурації та робочу область (і підвантажують `~/.profile`, якщо його змонтовано). Відповідні локальні точки входу: `test:live:models-profiles` і `test:live:gateway-profiles`. +- Docker live-ранери за замовчуванням використовують меншу межу smoke-перевірок, щоб повний 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 vars, коли - явно потрібне ширше вичерпне сканування. -- `test:docker:all` один раз збирає live Docker-образ через `test:docker:live-build`, один раз пакує OpenClaw як npm tarball через `scripts/package-openclaw-for-docker.mjs`, а потім збирає або повторно використовує два образи `scripts/e2e/Dockerfile`. Базовий образ є лише Node/Git-ранером для напрямів install/update/plugin-dependency; ці напрями монтують попередньо зібраний tarball. Функціональний образ встановлює той самий tarball у `/app` для напрямів функціональності зібраного застосунку. Визначення Docker-напрямів містяться в `scripts/lib/docker-e2e-scenarios.mjs`; логіка планувальника міститься в `scripts/lib/docker-e2e-plan.mjs`; `scripts/test-docker-all.mjs` виконує вибраний план. Агрегований запуск використовує зважений локальний планувальник: `OPENCLAW_DOCKER_ALL_PARALLELISM` керує слотами процесів, тоді як ресурсні ліміти не дають важким live-, npm-install- і multi-service-напрямам стартувати одночасно. Якщо один напрям важчий за активні ліміти, планувальник усе одно може запустити його, коли пул порожній, і тоді тримає його єдиним запущеним, доки знову не стане доступна місткість. Типові значення: 10 слотів, `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`, `OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` і `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`; налаштовуйте `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` або `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT` лише коли Docker-хост має більший запас ресурсів. Ранер типово виконує Docker preflight, видаляє застарілі OpenClaw E2E-контейнери, друкує статус кожні 30 секунд, зберігає таймінги успішних напрямів у `.artifacts/docker-tests/lane-timings.json` і використовує ці таймінги, щоб у наступних запусках першими стартували довші напрями. Використовуйте `OPENCLAW_DOCKER_ALL_DRY_RUN=1`, щоб надрукувати зважений маніфест напрямів без збирання чи запуску Docker, або `node scripts/test-docker-all.mjs --plan-json`, щоб надрукувати CI-план для вибраних напрямів, потреб пакетів/образів і облікових даних. -- `Package Acceptance` — це GitHub-нативний пакетний gate для перевірки «чи працює цей встановлюваний tarball як продукт?». Він визначає один кандидатний пакет із `source=npm`, `source=ref`, `source=url` або `source=artifact`, завантажує його як `package-under-test`, а потім запускає багаторазові Docker E2E-напрями проти саме цього tarball замість повторного пакування вибраного ref. `workflow_ref` вибирає довірений workflow/harness-скрипти, тоді як `package_ref` вибирає вихідний коміт/гілку/тег для пакування, коли `source=ref`; це дає змогу поточній логіці acceptance перевіряти старіші довірені коміти. Профілі впорядковані за широтою: `smoke` — це швидка перевірка install/channel/agent плюс gateway/config, `package` — контракт package/update/plugin і типова нативна заміна більшості покриття package/update у Parallels, `product` додає MCP-канали, очищення cron/subagent, вебпошук OpenAI і OpenWebUI, а `full` запускає Docker-фрагменти release-path з OpenWebUI. Валідація релізу запускає власну пакетну дельту (`bundled-channel-deps-compat plugins-offline`) плюс Telegram package QA, бо Docker-фрагменти release-path уже покривають перехресні напрями package/update/plugin. Цільові команди повторного запуску GitHub Docker, згенеровані з артефактів, включають попередній пакетний артефакт і підготовлені вхідні дані образів, коли вони доступні, тож проблемні напрями можуть уникнути повторного збирання пакета й образів. -- Перевірки збирання та релізу запускають `scripts/check-cli-bootstrap-imports.mjs` після tsdown. Guard обходить статичний зібраний граф із `dist/entry.js` і `dist/cli/run-main.js` та завершується з помилкою, якщо pre-dispatch startup імпортує пакетні залежності на кшталт Commander, prompt UI, undici або логування до dispatch команди; він також утримує зібраний gateway run chunk у межах бюджету та відхиляє статичні імпорти відомих холодних gateway-шляхів. Packaged CLI smoke також покриває кореневу довідку, довідку onboard, довідку doctor, status, схему config і команду model-list. -- Сумісність із застарілими версіями Package Acceptance обмежена `2026.4.25` (включно з `2026.4.25-beta.*`). До цієї межі harness допускає лише прогалини метаданих уже випущених пакетів: пропущені приватні записи QA-інвентарю, відсутній `gateway install --wrapper`, відсутні patch-файли у tarball-derived git fixture, відсутній збережений `update.channel`, застарілі розташування plugin install-record, відсутнє збереження marketplace install-record і міграцію метаданих config під час `plugins update`. Для пакетів після `2026.4.25` ці шляхи є суворими збоями. + `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`. Перевизначайте ці env-змінні, коли + вам явно потрібне ширше вичерпне сканування. +- `test:docker:all` один раз збирає live Docker-образ через `test:docker:live-build`, один раз пакує OpenClaw як npm-tarball через `scripts/package-openclaw-for-docker.mjs`, а потім збирає/повторно використовує два образи `scripts/e2e/Dockerfile`. Bare-образ — це лише Node/Git-ранер для напрямів install/update/plugin-dependency; ці напрями монтують попередньо зібраний tarball. Функціональний образ встановлює той самий tarball у `/app` для напрямів функціональності зібраного застосунку. Визначення Docker-напрямів містяться в `scripts/lib/docker-e2e-scenarios.mjs`; логіка планувальника — у `scripts/lib/docker-e2e-plan.mjs`; `scripts/test-docker-all.mjs` виконує вибраний план. Агрегований запуск використовує зважений локальний планувальник: `OPENCLAW_DOCKER_ALL_PARALLELISM` керує слотами процесів, тоді як обмеження ресурсів не дають важким live-, npm-install- і multi-service-напрямам стартувати одночасно. Якщо окремий напрям важчий за активні обмеження, планувальник усе одно може запустити його, коли пул порожній, а потім тримає його єдиним запущеним, доки знову не з’явиться місткість. Типові значення: 10 слотів, `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`, `OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` і `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`; налаштовуйте `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` або `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT` лише тоді, коли Docker-хост має більше запасу. Ранер за замовчуванням виконує Docker-перевірку preflight, видаляє застарілі E2E-контейнери OpenClaw, друкує статус кожні 30 секунд, зберігає часи успішних напрямів у `.artifacts/docker-tests/lane-timings.json` і використовує ці часи, щоб у наступних запусках спершу стартували довші напрями. Використовуйте `OPENCLAW_DOCKER_ALL_DRY_RUN=1`, щоб надрукувати зважений маніфест напрямів без збирання чи запуску Docker, або `node scripts/test-docker-all.mjs --plan-json`, щоб надрукувати CI-план для вибраних напрямів, потреб пакета/образу та облікових даних. +- `Package Acceptance` — це нативний для GitHub пакетний gate для питання «чи працює цей installable tarball як продукт?» Він визначає один кандидатний пакет із `source=npm`, `source=ref`, `source=url` або `source=artifact`, завантажує його як `package-under-test`, а потім запускає багаторазові Docker E2E-напрями проти саме цього tarball замість повторного пакування вибраного ref. `workflow_ref` вибирає довірені workflow/harness-скрипти, тоді як `package_ref` вибирає коміт/гілку/тег джерела для пакування, коли `source=ref`; це дає змогу поточній логіці acceptance перевіряти старіші довірені коміти. Профілі впорядковано за широтою: `smoke` — швидкі install/channel/agent плюс gateway/config, `package` — контракт package/update/plugin і типовий нативний замінник більшості покриття Parallels для package/update, `product` додає MCP-канали, очищення cron/subagent, вебпошук OpenAI і OpenWebUI, а `full` запускає Docker-фрагменти release-path з OpenWebUI. Перевірка релізу запускає користувацьку дельту пакета (`bundled-channel-deps-compat plugins-offline`) плюс QA пакета Telegram, бо Docker-фрагменти release-path уже покривають перетинні напрями package/update/plugin. Цільові команди повторного запуску GitHub Docker, згенеровані з артефактів, містять попередній артефакт пакета та підготовлені вхідні дані образів, коли вони доступні, тож невдалі напрями можуть уникнути повторного збирання пакета й образів. +- Перевірки збирання та релізу запускають `scripts/check-cli-bootstrap-imports.mjs` після tsdown. Захист обходить статичний зібраний граф із `dist/entry.js` і `dist/cli/run-main.js` та завершується з помилкою, якщо запуск до диспетчеризації команд імпортує пакетні залежності, як-от Commander, prompt UI, undici або логування, до диспетчеризації команди; він також утримує зібраний gateway run chunk у межах бюджету й відхиляє статичні імпорти відомих холодних шляхів Gateway. Smoke-перевірка упакованого CLI також покриває кореневу довідку, довідку onboard, довідку doctor, status, схему config і команду списку моделей. +- Сумісність Package Acceptance зі спадковими версіями обмежена `2026.4.25` (включно з `2026.4.25-beta.*`). До цієї межі harness терпить лише прогалини метаданих відвантаженого пакета: пропущені приватні записи QA-інвентарю, відсутній `gateway install --wrapper`, відсутні patch-файли у git-фікстурі, отриманій із tarball, відсутній збережений `update.channel`, спадкові розташування install-record Plugin, відсутнє збереження marketplace install-record і міграцію метаданих config під час `plugins update`. Для пакетів після `2026.4.25` ці шляхи є суворими помилками. - Контейнерні smoke-ранери: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:npm-onboard-channel-agent`, `test:docker:update-channel-switch`, `test:docker:session-runtime-context`, `test:docker:agents-delete-shared-workspace`, `test:docker:gateway-network`, `test:docker:browser-cdp-snapshot`, `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` запускають один або кілька реальних контейнерів і перевіряють інтеграційні шляхи вищого рівня. -Live-model Docker-ранери також bind-mount лише потрібні CLI auth homes (або всі підтримувані, коли запуск не звужено), а потім копіюють їх у домашній каталог контейнера перед запуском, щоб external-CLI OAuth міг оновлювати токени без зміни auth-сховища хоста: +Docker-ранери live-моделей також bind-mount-ять лише потрібні домівки CLI-автентифікації (або всі підтримувані, коли запуск не звужено), а потім копіюють їх у домівку контейнера перед запуском, щоб OAuth зовнішнього CLI міг оновлювати токени без мутації сховища автентифікації хоста: - Прямі моделі: `pnpm test:docker:live-models` (скрипт: `scripts/test-live-models-docker.sh`) -- Перевірка прив’язки ACP: `pnpm test:docker:live-acp-bind` (скрипт: `scripts/test-live-acp-bind-docker.sh`; типово охоплює Claude, Codex і Gemini, зі строгим покриттям Droid/OpenCode через `pnpm test:docker:live-acp-bind:droid` і `pnpm test:docker:live-acp-bind:opencode`) -- Перевірка бекенда CLI: `pnpm test:docker:live-cli-backend` (скрипт: `scripts/test-live-cli-backend-docker.sh`) -- Перевірка app-server harness Codex: `pnpm test:docker:live-codex-harness` (скрипт: `scripts/test-live-codex-harness-docker.sh`) +- ACP bind smoke: `pnpm test:docker:live-acp-bind` (скрипт: `scripts/test-live-acp-bind-docker.sh`; за замовчуванням охоплює Claude, Codex і Gemini, зі строгим покриттям Droid/OpenCode через `pnpm test:docker:live-acp-bind:droid` і `pnpm test:docker:live-acp-bind:opencode`) +- CLI backend smoke: `pnpm test:docker:live-cli-backend` (скрипт: `scripts/test-live-cli-backend-docker.sh`) +- Codex app-server harness smoke: `pnpm test:docker:live-codex-harness` (скрипт: `scripts/test-live-codex-harness-docker.sh`) - Gateway + агент розробки: `pnpm test:docker:live-gateway` (скрипт: `scripts/test-live-gateway-models-docker.sh`) -- Перевірка спостережуваності: `pnpm qa:otel:smoke` — приватна лінія перевірки вихідного checkout QA. Вона навмисно не входить до Docker-ліній випуску пакета, бо npm tarball не містить QA Lab. -- Жива перевірка Open WebUI: `pnpm test:docker:openwebui` (скрипт: `scripts/e2e/openwebui-docker.sh`) -- Майстер онбордингу (TTY, повне створення каркаса): `pnpm test:docker:onboard` (скрипт: `scripts/e2e/onboard-docker.sh`) -- Перевірка онбордингу/каналу/агента npm tarball: `pnpm test:docker:npm-onboard-channel-agent` глобально встановлює упакований OpenClaw tarball у Docker, налаштовує OpenAI через онбординг із env-ref і типово Telegram, перевіряє, що doctor відремонтував активовані runtime-залежності Plugin, і запускає один змодельований хід агента OpenAI. Повторно використайте попередньо зібраний tarball через `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, пропустіть перебудову на хості через `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` або перемкніть канал через `OPENCLAW_NPM_ONBOARD_CHANNEL=discord`. -- Перевірка перемикання каналу оновлень: `pnpm test:docker:update-channel-switch` глобально встановлює упакований OpenClaw tarball у Docker, перемикається з package `stable` на git `dev`, перевіряє збережений канал і роботу Plugin після оновлення, потім перемикається назад на package `stable` і перевіряє статус оновлення. -- Перевірка runtime-контексту сесії: `pnpm test:docker:session-runtime-context` перевіряє збереження прихованого runtime-контексту транскрипту та ремонт doctor для зачеплених дубльованих гілок prompt-rewrite. -- Перевірка глобального встановлення Bun: `bash scripts/e2e/bun-global-install-smoke.sh` пакує поточне дерево, встановлює його через `bun install -g` в ізольованому домашньому каталозі та перевіряє, що `openclaw infer image providers --json` повертає вбудованих постачальників зображень замість зависання. Повторно використайте попередньо зібраний tarball через `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, пропустіть збірку на хості через `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` або скопіюйте `dist/` із зібраного Docker-образу через `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local`. -- Docker-перевірка інсталятора: `bash scripts/test-install-sh-docker.sh` спільно використовує один npm-кеш між своїми root, update і direct-npm контейнерами. Перевірка оновлення типово використовує npm `latest` як stable-базу перед оновленням до candidate tarball. Перевизначте локально через `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22` або через вхід `update_baseline_version` workflow Install Smoke на GitHub. Перевірки інсталятора без root тримають ізольований npm-кеш, щоб root-owned записи кешу не приховували поведінку локального встановлення користувача. Установіть `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache`, щоб повторно використовувати кеш root/update/direct-npm під час локальних повторних запусків. -- Install Smoke CI пропускає дубльоване пряме глобальне оновлення direct-npm через `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1`; запускайте скрипт локально без цієї змінної середовища, коли потрібне покриття прямого `npm install -g`. -- Перевірка CLI видалення агентами спільного робочого простору: `pnpm test:docker:agents-delete-shared-workspace` (скрипт: `scripts/e2e/agents-delete-shared-workspace-docker.sh`) типово збирає образ із кореневого Dockerfile, засіває двох агентів одним робочим простором в ізольованому домашньому каталозі контейнера, запускає `agents delete --json` і перевіряє валідний JSON та поведінку збереженого робочого простору. Повторно використайте образ install-smoke через `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1`. -- Мережева взаємодія Gateway (два контейнери, WS auth + health): `pnpm test:docker:gateway-network` (скрипт: `scripts/e2e/gateway-network-docker.sh`) -- Перевірка snapshot Browser CDP: `pnpm test:docker:browser-cdp-snapshot` (скрипт: `scripts/e2e/browser-cdp-snapshot-docker.sh`) збирає вихідний E2E-образ плюс шар Chromium, запускає Chromium із raw CDP, запускає `browser doctor --deep` і перевіряє, що snapshot ролей CDP охоплюють URL посилань, клікабельні елементи, підвищені курсором, refs iframe і метадані frame. -- Регресія OpenAI Responses web_search minimal reasoning: `pnpm test:docker:openai-web-search-minimal` (скрипт: `scripts/e2e/openai-web-search-minimal-docker.sh`) запускає змодельований сервер OpenAI через Gateway, перевіряє, що `web_search` піднімає `reasoning.effort` з `minimal` до `low`, потім примусово викликає відхилення схеми провайдера й перевіряє, що необроблена detail з’являється в логах Gateway. -- Міст MCP-каналів (засіяний Gateway + stdio-міст + перевірка raw Claude notification-frame): `pnpm test:docker:mcp-channels` (скрипт: `scripts/e2e/mcp-channels-docker.sh`) -- MCP-інструменти Pi bundle (справжній stdio MCP-сервер + перевірка 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`) -- Plugin-и (перевірка встановлення, встановлення/видалення ClawHub kitchen-sink, оновлення marketplace і ввімкнення/інспекція Claude-bundle): `pnpm test:docker:plugins` (скрипт: `scripts/e2e/plugins-docker.sh`) - Установіть `OPENCLAW_PLUGINS_E2E_CLAWHUB=0`, щоб пропустити блок ClawHub, або перевизначте типову пару package/runtime kitchen-sink через `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` і `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID`. Без `OPENCLAW_CLAWHUB_URL`/`CLAWHUB_URL` тест використовує герметичний локальний сервер fixture ClawHub. -- Перевірка незміненого оновлення Plugin: `pnpm test:docker:plugin-update` (скрипт: `scripts/e2e/plugin-update-unchanged-docker.sh`) -- Перевірка metadata перезавантаження конфігурації: `pnpm test:docker:config-reload` (скрипт: `scripts/e2e/config-reload-source-docker.sh`) -- Runtime-залежності вбудованих 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_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`. Повний Docker-агрегат і bundled-channel chunks шляху випуску попередньо пакують цей tarball один раз, потім shard-поділяють перевірки вбудованих каналів на незалежні лінії, включно з окремими лініями оновлення для Telegram, Discord, Slack, Feishu, memory-lancedb і ACPX. Release chunks розділяють перевірки каналів, цілі оновлення та контракти setup/runtime на `bundled-channels-core`, `bundled-channels-update-a`, `bundled-channels-update-b` і `bundled-channels-contracts`; агрегатний chunk `bundled-channels` залишається доступним для ручних повторних запусків. Release workflow також розділяє chunks інсталятора провайдера та chunks встановлення/видалення вбудованих Plugin; застарілі chunks `package-update`, `plugins-runtime` і `plugins-integrations` залишаються агрегатними aliases для ручних повторних запусків. Використовуйте `OPENCLAW_BUNDLED_CHANNELS=telegram,slack`, щоб звузити матрицю каналів під час прямого запуску вбудованої лінії, або `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx`, щоб звузити сценарій оновлення. Docker-запуски за сценаріями типово мають `OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT=900s`; багатотаргетний сценарій оновлення типово має `OPENCLAW_BUNDLED_CHANNEL_UPDATE_DOCKER_RUN_TIMEOUT=2400s`. Лінія також перевіряє, що `channels..enabled=false` і `plugins.entries..enabled=false` пригнічують ремонт doctor/runtime-dependency. -- Звужуйте runtime-залежності вбудованих Plugin під час ітерацій, вимикаючи непов’язані сценарії, наприклад: +- Observability smoke: `pnpm qa:otel:smoke` є приватною QA-гілкою перевірки source-checkout. Вона навмисно не входить до Docker-гілок випуску пакета, тому що npm tarball не містить QA Lab. +- Open WebUI live smoke: `pnpm test:docker:openwebui` (скрипт: `scripts/e2e/openwebui-docker.sh`) +- Майстер початкового налаштування (TTY, повне створення каркаса): `pnpm test:docker:onboard` (скрипт: `scripts/e2e/onboard-docker.sh`) +- Npm tarball onboarding/channel/agent smoke: `pnpm test:docker:npm-onboard-channel-agent` глобально встановлює запакований OpenClaw tarball у Docker, налаштовує OpenAI через env-ref onboarding плюс Telegram за замовчуванням, перевіряє, що doctor відновлює активовані runtime-залежності Plugin, і запускає один змокований хід агента OpenAI. Повторно використовуйте попередньо зібраний tarball через `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, пропускайте перебудову на хості через `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` або перемикайте канал через `OPENCLAW_NPM_ONBOARD_CHANNEL=discord`. +- Update channel switch smoke: `pnpm test:docker:update-channel-switch` глобально встановлює запакований OpenClaw tarball у Docker, перемикається з пакетного `stable` на git `dev`, перевіряє збережений канал і роботу Plugin після оновлення, потім перемикається назад на пакетний `stable` і перевіряє статус оновлення. +- Session runtime context smoke: `pnpm test:docker:session-runtime-context` перевіряє збереження прихованого runtime-контексту в транскрипті плюс doctor-відновлення зачеплених дубльованих гілок prompt-rewrite. +- Bun global install smoke: `bash scripts/e2e/bun-global-install-smoke.sh` пакує поточне дерево, встановлює його через `bun install -g` в ізольованому home і перевіряє, що `openclaw infer image providers --json` повертає вбудованих провайдерів зображень замість зависання. Повторно використовуйте попередньо зібраний tarball через `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, пропускайте збірку на хості через `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` або копіюйте `dist/` зі зібраного Docker-образу через `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local`. +- Installer Docker smoke: `bash scripts/test-install-sh-docker.sh` спільно використовує один npm-кеш між своїми root, update і direct-npm контейнерами. Update smoke за замовчуванням використовує npm `latest` як стабільний baseline перед оновленням до кандидатного tarball. Перевизначайте через `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22` локально або через вхід `update_baseline_version` workflow Install Smoke на GitHub. Перевірки встановлювача без root зберігають ізольований npm-кеш, щоб записи кешу, що належать root, не маскували поведінку локального для користувача встановлення. Встановіть `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache`, щоб повторно використовувати кеш root/update/direct-npm між локальними повторними запусками. +- Install Smoke CI пропускає дубльоване глобальне оновлення direct-npm через `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1`; запускайте скрипт локально без цього env, коли потрібне покриття прямого `npm install -g`. +- Agents delete shared workspace CLI smoke: `pnpm test:docker:agents-delete-shared-workspace` (скрипт: `scripts/e2e/agents-delete-shared-workspace-docker.sh`) за замовчуванням збирає кореневий образ Dockerfile, засіває двох агентів з одним workspace в ізольованому container home, запускає `agents delete --json` і перевіряє валідний JSON плюс поведінку збереження workspace. Повторно використовуйте install-smoke image через `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1`. +- Gateway networking (два контейнери, WS auth + health): `pnpm test:docker:gateway-network` (скрипт: `scripts/e2e/gateway-network-docker.sh`) +- Browser CDP snapshot smoke: `pnpm test:docker:browser-cdp-snapshot` (скрипт: `scripts/e2e/browser-cdp-snapshot-docker.sh`) збирає source E2E image плюс шар Chromium, запускає Chromium із raw CDP, виконує `browser doctor --deep` і перевіряє, що snapshot-и CDP-ролей охоплюють URL посилань, clickables, підвищені з курсора, iframe refs і метадані frame. +- OpenAI Responses web_search minimal reasoning regression: `pnpm test:docker:openai-web-search-minimal` (скрипт: `scripts/e2e/openai-web-search-minimal-docker.sh`) запускає змокований сервер OpenAI через Gateway, перевіряє, що `web_search` піднімає `reasoning.effort` з `minimal` до `low`, потім примусово спричиняє reject схеми провайдера й перевіряє, що raw detail з’являється в логах Gateway. +- MCP channel bridge (засіяний Gateway + stdio bridge + raw Claude notification-frame smoke): `pnpm test:docker:mcp-channels` (скрипт: `scripts/e2e/mcp-channels-docker.sh`) +- Pi bundle MCP tools (реальний stdio MCP server + embedded Pi profile allow/deny smoke): `pnpm test:docker:pi-bundle-mcp-tools` (скрипт: `scripts/e2e/pi-bundle-mcp-tools-docker.sh`) +- Cron/subagent MCP cleanup (реальний Gateway + stdio MCP child teardown після ізольованого cron і одноразових subagent-запусків): `pnpm test:docker:cron-mcp-cleanup` (скрипт: `scripts/e2e/cron-mcp-cleanup-docker.sh`) +- Плагіни (install smoke, ClawHub kitchen-sink install/uninstall, marketplace updates і Claude-bundle enable/inspect): `pnpm test:docker:plugins` (скрипт: `scripts/e2e/plugins-docker.sh`) + Встановіть `OPENCLAW_PLUGINS_E2E_CLAWHUB=0`, щоб пропустити блок ClawHub, або перевизначте стандартну пару kitchen-sink package/runtime через `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` і `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID`. Без `OPENCLAW_CLAWHUB_URL`/`CLAWHUB_URL` тест використовує герметичний локальний fixture-сервер ClawHub. +- Plugin update unchanged smoke: `pnpm test:docker:plugin-update` (скрипт: `scripts/e2e/plugin-update-unchanged-docker.sh`) +- Config reload metadata smoke: `pnpm test:docker:config-reload` (скрипт: `scripts/e2e/config-reload-source-docker.sh`) +- Bundled plugin runtime deps: `pnpm test:docker:bundled-channel-deps` за замовчуванням збирає невеликий образ Docker runner, один раз збирає й пакує OpenClaw на хості, а потім монтує цей tarball у кожен сценарій встановлення Linux. Повторно використовуйте образ через `OPENCLAW_SKIP_DOCKER_BUILD=1`, пропускайте перебудову на хості після свіжої локальної збірки через `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` або вкажіть наявний tarball через `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`. Повний Docker aggregate і release-path bundled-channel chunks попередньо пакують цей tarball один раз, а потім шардують перевірки bundled channel в незалежні гілки, включно з окремими update lanes для Telegram, Discord, Slack, Feishu, memory-lancedb і ACPX. Release chunks розділяють channel smokes, update targets і setup/runtime contracts на `bundled-channels-core`, `bundled-channels-update-a`, `bundled-channels-update-b` і `bundled-channels-contracts`; aggregate chunk `bundled-channels` залишається доступним для ручних повторних запусків. Release workflow також розділяє provider installer chunks і bundled plugin install/uninstall chunks; застарілі chunks `package-update`, `plugins-runtime` і `plugins-integrations` залишаються aggregate aliases для ручних повторних запусків. Використовуйте `OPENCLAW_BUNDLED_CHANNELS=telegram,slack`, щоб звузити channel matrix під час прямого запуску bundled lane, або `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx`, щоб звузити update scenario. Docker-запуски для окремих сценаріїв за замовчуванням мають `OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT=900s`; multi-target update scenario за замовчуванням має `OPENCLAW_BUNDLED_CHANNEL_UPDATE_DOCKER_RUN_TIMEOUT=2400s`. Lane також перевіряє, що `channels..enabled=false` і `plugins.entries..enabled=false` пригнічують doctor/runtime-dependency repair. +- Звужуйте bundled plugin runtime deps під час ітерацій, вимикаючи непов’язані сценарії, наприклад: `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`. -Щоб вручну попередньо зібрати й повторно використати спільний функціональний образ: +Щоб вручну попередньо зібрати й повторно використовувати спільний функціональний образ: ```bash OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local pnpm test:docker:e2e-build OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels ``` -Suite-specific перевизначення образів, як-от `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE`, усе одно мають пріоритет, коли задані. Коли `OPENCLAW_SKIP_DOCKER_BUILD=1` вказує на віддалений спільний образ, скрипти завантажують його, якщо він ще не локальний. Docker-тести QR та інсталятора зберігають власні Dockerfile, бо вони перевіряють поведінку пакета/встановлення, а не спільний runtime зібраного застосунку. +Перевизначення образів для конкретних suite, як-от `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE`, усе ще мають перевагу, коли встановлені. Коли `OPENCLAW_SKIP_DOCKER_BUILD=1` вказує на віддалений спільний образ, скрипти pull-ять його, якщо він ще не локальний. QR і Docker-тести встановлювача зберігають власні Dockerfile, тому що вони перевіряють поведінку package/install, а не спільний runtime зібраного застосунку. -Docker runners live-model також монтують поточний checkout лише для читання та -поміщають його в тимчасовий робочий каталог усередині контейнера. Це зберігає runtime -образ легким, але все одно запускає Vitest проти саме вашого локального source/config. -Крок staging пропускає великі локальні кеші та build-виводи застосунків, як-от -`.pnpm-store`, `.worktrees`, `__openclaw_vitest__`, а також локальні для застосунку каталоги `.build` або -Gradle output, щоб Docker live-запуски не витрачали хвилини на копіювання -machine-specific артефактів. -Вони також задають `OPENCLAW_SKIP_CHANNELS=1`, щоб live probes Gateway не запускали -справжні worker-и каналів Telegram/Discord/тощо всередині контейнера. -`test:docker:live-models` усе ще запускає `pnpm test:live`, тож також передавайте -`OPENCLAW_LIVE_GATEWAY_*`, коли потрібно звузити або виключити live-покриття -Gateway із цієї Docker-лінії. -`test:docker:openwebui` — це високорівнева перевірка сумісності: вона запускає -контейнер Gateway OpenClaw з увімкненими OpenAI-сумісними HTTP endpoint-ами, -запускає pinned контейнер Open WebUI проти цього Gateway, входить через +Live-model Docker runners також bind-mount-ять поточний checkout лише для читання і +стейджать його в тимчасовий workdir усередині контейнера. Це зберігає runtime +image компактним, але все одно запускає Vitest проти вашого точного локального source/config. +Крок staging пропускає великі локальні кеші та build outputs застосунків, як-от +`.pnpm-store`, `.worktrees`, `__openclaw_vitest__`, а також локальні для застосунку `.build` або +каталоги виводу Gradle, щоб Docker live runs не витрачали хвилини на копіювання +машинно-специфічних artifacts. +Вони також встановлюють `OPENCLAW_SKIP_CHANNELS=1`, щоб gateway live probes не запускали +реальних Telegram/Discord/тощо channel workers усередині контейнера. +`test:docker:live-models` усе ще запускає `pnpm test:live`, тому також передавайте +`OPENCLAW_LIVE_GATEWAY_*`, коли потрібно звузити або виключити gateway +live coverage із цієї Docker lane. +`test:docker:openwebui` є compatibility smoke вищого рівня: він запускає +контейнер Gateway OpenClaw з увімкненими HTTP endpoints, сумісними з OpenAI, +запускає pinned Open WebUI container проти цього gateway, входить через Open WebUI, перевіряє, що `/api/models` expose-ить `openclaw/default`, потім надсилає -справжній chat request через proxy Open WebUI `/api/chat/completions`. -Перший запуск може бути помітно повільнішим, бо Docker може знадобитися завантажити -образ Open WebUI, а Open WebUI може знадобитися завершити власне cold-start setup. -Ця лінія очікує придатний live model key, і `OPENCLAW_PROFILE_FILE` -(типово `~/.profile`) є основним способом надати його в Dockerized-запусках. -Успішні запуски друкують невелике JSON payload на кшталт `{ "ok": true, "model": +реальний chat request через proxy Open WebUI `/api/chat/completions`. +Перший запуск може бути помітно повільнішим, бо Docker може потребувати pull +образу Open WebUI, а Open WebUI може потребувати завершення власного cold-start setup. +Ця lane очікує придатний live model key, і `OPENCLAW_PROFILE_FILE` +(`~/.profile` за замовчуванням) є основним способом надати його в Dockerized runs. +Успішні запуски друкують невеликий JSON payload на кшталт `{ "ok": true, "model": "openclaw/default", ... }`. `test:docker:mcp-channels` навмисно детермінований і не потребує -справжнього облікового запису Telegram, Discord або iMessage. Він завантажує засіяний контейнер Gateway, +реального облікового запису Telegram, Discord або iMessage. Він завантажує засіяний контейнер Gateway, запускає другий контейнер, який spawn-ить `openclaw mcp serve`, потім -перевіряє routed conversation discovery, читання транскриптів, metadata вкладень, -поведінку черги live event, маршрутизацію outbound send і channel + -permission notifications у стилі Claude через справжній stdio MCP bridge. Перевірка сповіщень -безпосередньо інспектує raw stdio MCP frames, тож перевірка валідує те, що -міст фактично emits, а не лише те, що конкретний client SDK випадково surface-ить. +перевіряє routed conversation discovery, transcript reads, attachment metadata, +live event queue behavior, outbound send routing і Claude-style channel + +permission notifications через реальний stdio MCP bridge. Notification check +напряму інспектує raw stdio MCP frames, щоб smoke перевіряв те, що +bridge фактично emits, а не лише те, що випадково surface-ить конкретний client SDK. `test:docker:pi-bundle-mcp-tools` детермінований і не потребує live -model key. Він збирає Docker-образ репозиторію, запускає справжній stdio MCP probe server -усередині контейнера, materialize-ить цей сервер через вбудований runtime Pi bundle -MCP, виконує інструмент, а потім перевіряє, що `coding` і `messaging` зберігають -інструменти `bundle-mcp`, тоді як `minimal` і `tools.deny: ["bundle-mcp"]` їх фільтрують. +model key. Він збирає repo Docker image, запускає реальний stdio MCP probe server +усередині контейнера, materializes цей сервер через embedded Pi bundle +MCP runtime, виконує tool, а потім перевіряє, що `coding` і `messaging` зберігають +`bundle-mcp` tools, тоді як `minimal` і `tools.deny: ["bundle-mcp"]` їх фільтрують. `test:docker:cron-mcp-cleanup` детермінований і не потребує live model -key. Він запускає засіяний Gateway зі справжнім stdio MCP probe server, запускає -ізольований хід cron і одноразовий дочірній хід `/subagents spawn`, потім перевіряє, -що дочірній процес MCP завершується після кожного запуску. +key. Він запускає засіяний Gateway з реальним stdio MCP probe server, виконує +ізольований cron turn і одноразовий child turn `/subagents spawn`, а потім перевіряє, +що MCP child process завершується після кожного запуску. -Ручна plain-language перевірка thread ACP (не CI): +Ручний ACP plain-language thread smoke (не CI): - `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...` -- Зберігайте цей скрипт для регресійних і налагоджувальних робочих процесів. Він може знову знадобитися для перевірки маршрутизації потоків ACP, тому не видаляйте його. +- Залиште цей скрипт для робочих процесів регресії/налагодження. Він може знову знадобитися для перевірки маршрутизації потоків ACP, тому не видаляйте його. Корисні змінні середовища: - `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` для перевірки лише змінних середовища, підвантажених із `OPENCLAW_PROFILE_FILE`, із тимчасовими каталогами конфігурації/робочого простору та без монтувань автентифікації зовнішніх CLI -- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...` (типово: `~/.cache/openclaw/docker-cli-tools`) монтується до `/home/node/.npm-global` для кешованих встановлень CLI всередині Docker -- Каталоги/файли автентифікації зовнішніх CLI під `$HOME` монтуються лише для читання під `/host-auth...`, а потім копіюються до `/home/node/...` перед запуском тестів +- `OPENCLAW_PROFILE_FILE=...` (типово: `~/.profile`) монтується до `/home/node/.profile` і завантажується перед запуском тестів +- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1`, щоб перевіряти лише змінні середовища, завантажені з `OPENCLAW_PROFILE_FILE`, використовуючи тимчасові каталоги конфігурації/робочої області та без монтування зовнішньої автентифікації CLI +- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...` (типово: `~/.cache/openclaw/docker-cli-tools`) монтується до `/home/node/.npm-global` для кешованих встановлень CLI у Docker +- Зовнішні каталоги/файли автентифікації 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_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` для гарантії, що облікові дані надходять зі сховища профілю (а не з середовища) -- `OPENCLAW_OPENWEBUI_MODEL=...` для вибору моделі, яку Gateway надає для smoke-перевірки Open WebUI -- `OPENCLAW_OPENWEBUI_PROMPT=...` для перевизначення підказки перевірки nonce, яку використовує smoke-перевірка Open WebUI -- `OPENWEBUI_IMAGE=...` для перевизначення закріпленого тегу образу Open WebUI +- `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`, щоб переконатися, що облікові дані надходять зі сховища профілів (а не зі змінних середовища) +- `OPENCLAW_OPENWEBUI_MODEL=...`, щоб вибрати модель, яку Gateway надає для smoke-тесту Open WebUI +- `OPENCLAW_OPENWEBUI_PROMPT=...`, щоб перевизначити запит перевірки nonce, який використовує smoke-тест Open WebUI +- `OPENWEBUI_IMAGE=...`, щоб перевизначити зафіксований тег образу Open WebUI -## Перевірка коректності документації +## Перевірка документації -Запускайте перевірки документації після змін у документах: `pnpm check:docs`. +Запускайте перевірки документації після редагування документації: `pnpm check:docs`. Запускайте повну перевірку якорів Mintlify, коли також потрібні перевірки заголовків на сторінці: `pnpm docs:check-links:anchors`. ## Офлайн-регресія (безпечна для CI) Це регресії «реального конвеєра» без реальних провайдерів: -- Виклик інструментів через Gateway (імітація OpenAI, реальний Gateway + цикл агента): `src/gateway/gateway.test.ts` (випадок: "виконує імітований виклик інструмента OpenAI наскрізно через цикл агента Gateway") -- Майстер Gateway (WS `wizard.start`/`wizard.next`, записує конфігурацію + примусово застосовує автентифікацію): `src/gateway/gateway.test.ts` (випадок: "запускає майстер через ws і записує конфігурацію токена автентифікації") +- Виклики інструментів Gateway (імітація OpenAI, реальний gateway + цикл агента): `src/gateway/gateway.test.ts` (випадок: "runs a mock OpenAI tool call end-to-end via gateway agent loop") +- Майстер Gateway (WS `wizard.start`/`wizard.next`, записує конфігурацію + примусово застосовує автентифікацію): `src/gateway/gateway.test.ts` (випадок: "runs wizard over ws and writes auth token config") ## Оцінювання надійності агентів (skills) -У нас уже є кілька безпечних для CI тестів, що поводяться як «оцінювання надійності агентів»: +У нас уже є кілька безпечних для CI тестів, які поводяться як «оцінювання надійності агентів»: -- Імітований виклик інструментів через реальний Gateway + цикл агента (`src/gateway/gateway.test.ts`). -- Наскрізні потоки майстра, які перевіряють зв’язування сесії та ефекти конфігурації (`src/gateway/gateway.test.ts`). +- Імітація виклику інструментів через реальний Gateway + цикл агента (`src/gateway/gateway.test.ts`). +- Наскрізні потоки майстра, які перевіряють підключення сесії та ефекти конфігурації (`src/gateway/gateway.test.ts`). -Чого ще бракує для Skills (див. [Skills](/uk/tools/skills)): +Чого ще бракує для skills (див. [Skills](/uk/tools/skills)): -- **Ухвалення рішень:** коли Skills наведені в підказці, чи вибирає агент правильний skill (або уникає нерелевантних)? -- **Дотримання вимог:** чи читає агент `SKILL.md` перед використанням і чи виконує потрібні кроки/аргументи? -- **Контракти робочого процесу:** багатокрокові сценарії, які перевіряють порядок інструментів, перенесення історії сесії та межі пісочниці. +- **Ухвалення рішень:** коли skills перелічені в запиті, чи вибирає агент правильний skill (або уникає нерелевантних)? +- **Відповідність вимогам:** чи читає агент `SKILL.md` перед використанням і чи виконує потрібні кроки/аргументи? +- **Контракти робочих процесів:** багатокрокові сценарії, які перевіряють порядок інструментів, перенесення історії сесії та межі пісочниці. -Майбутні оцінювання насамперед мають залишатися детермінованими: +Майбутні оцінювання мають спершу залишатися детермінованими: -- Виконавець сценаріїв із використанням імітованих провайдерів для перевірки викликів інструментів + порядку, читання файлів skill і зв’язування сесії. -- Невеликий набір сценаріїв, зосереджених на skills (використовувати чи уникати, обмеження, ін’єкція підказок). -- Необов’язкові live-оцінювання (за явним увімкненням, керовані змінними середовища) лише після того, як буде готовий безпечний для CI набір. +- Виконувач сценаріїв із mock-провайдерами для перевірки викликів інструментів + порядку, читання файлів skills і підключення сесії. +- Невеликий набір сценаріїв, зосереджених на skills (використання проти уникнення, gating, інʼєкція запиту). +- Необовʼязкові live-оцінювання (за явним увімкненням, керовані змінними середовища) лише після появи безпечного для CI набору. -## Контрактні тести (форма Plugin і каналу) +## Контрактні тести (форма plugin і channel) -Контрактні тести перевіряють, що кожен зареєстрований Plugin і канал відповідає своєму -контракту інтерфейсу. Вони проходять усі знайдені plugins і запускають набір -перевірок форми та поведінки. Типова unit-смуга `pnpm test` навмисно -пропускає ці спільні файли швів і smoke-файли; запускайте контрактні команди явно, -коли змінюєте спільні поверхні каналів або провайдерів. +Контрактні тести перевіряють, що кожен зареєстрований plugin і channel відповідає своєму +інтерфейсному контракту. Вони проходять по всіх виявлених plugins і запускають набір +перевірок форми та поведінки. Типова unit-доріжка `pnpm test` навмисно +пропускає ці спільні файли seam і smoke; запускайте контрактні команди явно, +коли змінюєте спільні поверхні channel або provider. ### Команди - Усі контракти: `pnpm test:contracts` -- Лише контракти каналів: `pnpm test:contracts:channels` -- Лише контракти провайдерів: `pnpm test:contracts:plugins` +- Лише контракти channel: `pnpm test:contracts:channels` +- Лише контракти provider: `pnpm test:contracts:plugins` -### Контракти каналів +### Контракти channel Розташовані в `src/channels/plugins/contracts/*.contract.test.ts`: -- **plugin** - Базова форма Plugin (id, name, capabilities) +- **plugin** - Базова форма plugin (id, name, capabilities) - **setup** - Контракт майстра налаштування -- **session-binding** - Поведінка зв’язування сесії -- **outbound-payload** - Структура корисного навантаження повідомлення +- **session-binding** - Поведінка привʼязки сесії +- **outbound-payload** - Структура payload повідомлення - **inbound** - Обробка вхідних повідомлень -- **actions** - Обробники дій каналу -- **threading** - Обробка ID потоків -- **directory** - API каталогу/реєстру учасників +- **actions** - Обробники дій channel +- **threading** - Обробка ID потоку +- **directory** - API каталогу/списку учасників - **group-policy** - Застосування групової політики -### Контракти статусу провайдерів +### Контракти статусу provider Розташовані в `src/plugins/contracts/*.contract.test.ts`. -- **status** - Перевірки статусу каналу +- **status** - Проби статусу channel - **registry** - Форма реєстру Plugin -### Контракти провайдерів +### Контракти provider Розташовані в `src/plugins/contracts/*.contract.test.ts`: @@ -784,32 +789,32 @@ key. Він запускає засіяний Gateway зі справжнім st - **catalog** - API каталогу моделей - **discovery** - Виявлення Plugin - **loader** - Завантаження Plugin -- **runtime** - Середовище виконання провайдера +- **runtime** - Runtime provider - **shape** - Форма/інтерфейс Plugin - **wizard** - Майстер налаштування ### Коли запускати - Після зміни експортів або підшляхів plugin-sdk -- Після додавання або змінення каналу чи провайдерського Plugin -- Після рефакторингу реєстрації або виявлення Plugin +- Після додавання або зміни channel чи provider plugin +- Після рефакторингу реєстрації або виявлення plugin -Контрактні тести запускаються в CI і не потребують реальних ключів API. +Контрактні тести запускаються в CI і не потребують реальних API-ключів. ## Додавання регресій (настанови) -Коли ви виправляєте проблему провайдера/моделі, виявлену наживо: +Коли ви виправляєте проблему provider/model, виявлену наживо: -- Додайте безпечну для CI регресію, якщо можливо (імітація/заглушка провайдера або фіксація точної трансформації форми запиту) -- Якщо це за своєю суттю лише live-випадок (ліміти швидкості, політики автентифікації), залишайте live-тест вузьким і вмикайте його явно через змінні середовища -- Надавайте перевагу найменшому шару, який ловить помилку: - - помилка перетворення/відтворення запиту провайдера → прямий тест моделей - - помилка конвеєра сесії/історії/інструментів Gateway → live-smoke Gateway або безпечний для CI імітований тест Gateway -- Захисне обмеження обходу SecretRef: - - `src/secrets/exec-secret-ref-id-parity.test.ts` виводить одну вибіркову ціль для кожного класу SecretRef з метаданих реєстру (`listSecretTargetRegistryEntries()`), а потім перевіряє, що exec id із сегментами обходу відхиляються. - - Якщо ви додаєте нове сімейство цілей SecretRef `includeInPlan` у `src/secrets/target-registry-data.ts`, оновіть `classifyTargetClass` у цьому тесті. Тест навмисно падає на некласифікованих ідентифікаторах цілей, щоб нові класи не можна було пропустити непомітно. +- Додайте безпечну для CI регресію, якщо можливо (mock/stub provider або зафіксуйте точне перетворення форми запиту) +- Якщо це за своєю суттю лише live-випадок (обмеження частоти, політики автентифікації), залиште live-тест вузьким і вмикайте його явно через змінні середовища +- Віддавайте перевагу найменшому шару, який ловить помилку: + - помилка перетворення/відтворення запиту provider → прямий тест моделей + - помилка конвеєра сесії/історії/інструментів Gateway → live smoke Gateway або безпечний для CI mock-тест Gateway +- Запобіжник обходу SecretRef: + - `src/secrets/exec-secret-ref-id-parity.test.ts` виводить одну вибрану ціль для кожного класу SecretRef з метаданих реєстру (`listSecretTargetRegistryEntries()`), а потім перевіряє, що exec ids із сегментами обходу відхиляються. + - Якщо ви додаєте нову сімʼю цілей SecretRef `includeInPlan` у `src/secrets/target-registry-data.ts`, оновіть `classifyTargetClass` у цьому тесті. Тест навмисно падає на некласифікованих target ids, щоб нові класи не можна було мовчки пропустити. -## Пов’язане +## Повʼязане - [Тестування наживо](/uk/help/testing-live) - [CI](/uk/ci)