From fcdf1ec6dcf3a93d2a0f7c0703e336871167cd9b Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Tue, 21 Apr 2026 21:31:06 +0000 Subject: [PATCH] chore(i18n): refresh uk translations --- docs/uk/channels/imessage.md | 188 +++--- docs/uk/channels/msteams.md | 459 +++++++------- docs/uk/channels/troubleshooting.md | 120 ++-- docs/uk/ci.md | 92 +-- docs/uk/help/testing.md | 947 ++++++++++++++-------------- docs/uk/providers/index.md | 49 +- docs/uk/reference/test.md | 90 +-- 7 files changed, 974 insertions(+), 971 deletions(-) diff --git a/docs/uk/channels/imessage.md b/docs/uk/channels/imessage.md index 61c239a86..39ed4210f 100644 --- a/docs/uk/channels/imessage.md +++ b/docs/uk/channels/imessage.md @@ -2,13 +2,13 @@ read_when: - Налаштування підтримки iMessage - Налагодження надсилання/отримання iMessage -summary: Застаріла підтримка iMessage через imsg (JSON-RPC через stdio). Для нових налаштувань слід використовувати BlueBubbles. +summary: Застаріла підтримка iMessage через imsg (JSON-RPC через stdio). У нових налаштуваннях слід використовувати BlueBubbles. title: iMessage x-i18n: - generated_at: "2026-04-05T17:58:18Z" + generated_at: "2026-04-21T21:27:21Z" model: gpt-5.4 provider: openai - source_hash: 086d85bead49f75d12ae6b14ac917af52375b6afd28f6af1a0dcbbc7fcb628a0 + source_hash: fb9cc5a0bd4fbc7ff6f792e737bc4302a67f9ab6aa8231ff6f751fe6d732ca5d source_path: channels/imessage.md workflow: 15 --- @@ -16,21 +16,21 @@ x-i18n: # iMessage (застаріле: imsg) -Для нових розгортань iMessage використовуйте BlueBubbles. +Для нових розгортань iMessage використовуйте BlueBubbles. -Інтеграція `imsg` є застарілою та може бути видалена в одному з майбутніх випусків. +Інтеграція `imsg` є застарілою і може бути вилучена в майбутньому випуску. -Стан: застаріла зовнішня інтеграція CLI. Gateway запускає `imsg rpc` і обмінюється даними через JSON-RPC по stdio (без окремого демона/порту). +Статус: застаріла зовнішня інтеграція CLI. Gateway запускає `imsg rpc` і обмінюється даними через JSON-RPC по stdio (без окремого демона/порту). - + Бажаний шлях iMessage для нових налаштувань. - - Для приватних повідомлень iMessage типово використовується режим прив’язки. + + Прямі повідомлення iMessage типово використовують режим сполучення. - + Повний довідник полів iMessage. @@ -40,7 +40,7 @@ x-i18n: - + ```bash brew install steipete/tap/imsg @@ -57,7 +57,7 @@ imsg rpc --help imessage: { enabled: true, cliPath: "/usr/local/bin/imsg", - dbPath: "/Users//Library/Messages/chat.db", + dbPath: "/Users/user/Library/Messages/chat.db", }, }, } @@ -73,21 +73,21 @@ openclaw gateway - + ```bash openclaw pairing list imessage openclaw pairing approve imessage ``` - Запити на прив’язку спливають через 1 годину. + Запити на сполучення спливають через 1 годину. - OpenClaw потребує лише сумісний зі stdio `cliPath`, тому ви можете вказати для `cliPath` обгортковий скрипт, який підключається через SSH до віддаленого Mac і запускає `imsg`. + OpenClaw потребує лише сумісний зі stdio `cliPath`, тож ви можете вказати в `cliPath` скрипт-обгортку, який підключається через SSH до віддаленого Mac і запускає `imsg`. ```bash #!/usr/bin/env bash @@ -104,8 +104,8 @@ exec ssh -T gateway-host imsg "$@" cliPath: "~/.openclaw/scripts/imsg-ssh", remoteHost: "user@gateway-host", // використовується для отримання вкладень через SCP includeAttachments: true, - // Необов’язково: перевизначити дозволені корені вкладень. - // Типово включають /Users/*/Library/Messages/Attachments + // Необов’язково: перевизначити дозволені кореневі каталоги вкладень. + // Типово включає /Users/*/Library/Messages/Attachments attachmentRoots: ["/Users/*/Library/Messages/Attachments"], remoteAttachmentRoots: ["/Users/*/Library/Messages/Attachments"], }, @@ -113,22 +113,22 @@ exec ssh -T gateway-host imsg "$@" } ``` - Якщо `remoteHost` не задано, OpenClaw спробує автоматично визначити його, аналізуючи обгортковий SSH-скрипт. - `remoteHost` має бути у форматі `host` або `user@host` (без пробілів або параметрів SSH). - OpenClaw використовує сувору перевірку ключа хоста для SCP, тому ключ хоста ретранслятора вже має бути присутній у `~/.ssh/known_hosts`. - Шляхи вкладень перевіряються відносно дозволених коренів (`attachmentRoots` / `remoteAttachmentRoots`). + Якщо `remoteHost` не задано, OpenClaw намагається автоматично визначити його, аналізуючи SSH-скрипт-обгортку. + `remoteHost` має бути у форматі `host` або `user@host` (без пробілів чи параметрів SSH). + OpenClaw використовує сувору перевірку ключа хоста для SCP, тому ключ хоста ретранслятора вже має бути наявний у `~/.ssh/known_hosts`. + Шляхи до вкладень перевіряються на відповідність дозволеним кореневим каталогам (`attachmentRoots` / `remoteAttachmentRoots`). ## Вимоги та дозволи (macOS) -- У Messages має бути виконано вхід на Mac, де працює `imsg`. -- Для контексту процесу, у якому працює OpenClaw/`imsg`, потрібен Full Disk Access (доступ до бази даних Messages). +- У Messages має бути виконано вхід на Mac, де запускається `imsg`. +- Для контексту процесу, у якому працює OpenClaw/`imsg`, потрібен Full Disk Access (доступ до БД Messages). - Для надсилання повідомлень через Messages.app потрібен дозвіл Automation. -Дозволи надаються для кожного контексту процесу окремо. Якщо gateway працює без графічного інтерфейсу (LaunchAgent/SSH), виконайте одноразову інтерактивну команду в цьому самому контексті, щоб викликати підказки: +Дозволи надаються для кожного контексту процесу. Якщо gateway працює без графічного інтерфейсу (LaunchAgent/SSH), виконайте одноразову інтерактивну команду в тому самому контексті, щоб викликати запити: ```bash imsg chats --limit 1 @@ -141,17 +141,17 @@ imsg send "test" ## Керування доступом і маршрутизація - + `channels.imessage.dmPolicy` керує прямими повідомленнями: - `pairing` (типово) - `allowlist` - - `open` (потрібно, щоб `allowFrom` включав `"*"`) + - `open` (потребує, щоб `allowFrom` містив `"*"`) - `disabled` Поле allowlist: `channels.imessage.allowFrom`. - Записи allowlist можуть бути дескрипторами або цілями чату (`chat_id:*`, `chat_guid:*`, `chat_identifier:*`). + Записи allowlist можуть бути handle або цілі чату (`chat_id:*`, `chat_guid:*`, `chat_identifier:*`). @@ -164,49 +164,49 @@ imsg send "test" Allowlist відправників груп: `channels.imessage.groupAllowFrom`. - Резервний механізм під час виконання: якщо `groupAllowFrom` не задано, перевірки відправників груп iMessage повертаються до `allowFrom`, якщо він доступний. - Примітка щодо виконання: якщо `channels.imessage` повністю відсутній, середовище виконання повертається до `groupPolicy="allowlist"` і записує попередження в журнал (навіть якщо задано `channels.defaults.groupPolicy`). + Резервна логіка під час виконання: якщо `groupAllowFrom` не задано, перевірки відправників груп iMessage використовують `allowFrom`, якщо воно доступне. + Примітка щодо виконання: якщо `channels.imessage` повністю відсутній, під час виконання використовується `groupPolicy="allowlist"` і записується попередження в журнал (навіть якщо задано `channels.defaults.groupPolicy`). - Керування згадками для груп: + Обмеження за згадками для груп: - iMessage не має вбудованих метаданих згадок - - виявлення згадок використовує regex-шаблони (`agents.list[].groupChat.mentionPatterns`, резервно — `messages.groupChat.mentionPatterns`) - - без налаштованих шаблонів керування згадками неможливо забезпечити + - виявлення згадок використовує шаблони regex (`agents.list[].groupChat.mentionPatterns`, резервно `messages.groupChat.mentionPatterns`) + - якщо шаблони не налаштовані, обмеження за згадками неможливо забезпечити - Керівні команди від авторизованих відправників можуть обходити вимогу згадки в групах. + Команди керування від авторизованих відправників можуть обходити обмеження за згадками в групах. - - - Для приватних повідомлень використовується пряма маршрутизація; для груп — групова. - - За типовим `session.dmScope=main` приватні повідомлення iMessage зводяться до основної сесії агента. - - Групові сесії ізольовані (`agent::imessage:group:`). - - Відповіді маршрутизуються назад в iMessage з використанням метаданих каналу/цілі походження. + + - DM використовують пряму маршрутизацію; групи — групову. + - Із типовим `session.dmScope=main` DM iMessage згортаються в основний сеанс агента. + - Групові сеанси ізольовані (`agent::imessage:group:`). + - Відповіді маршрутизуються назад в iMessage з використанням метаданих початкового каналу/цілі. Поведінка потоків, схожих на групові: - Деякі багатокористувацькі потоки iMessage можуть надходити з `is_group=false`. - Якщо такий `chat_id` явно налаштований у `channels.imessage.groups`, OpenClaw обробляє його як груповий трафік (керування групами + ізоляція групової сесії). + Деякі багатосторонні потоки iMessage можуть надходити з `is_group=false`. + Якщо такий `chat_id` явно налаштовано в `channels.imessage.groups`, OpenClaw обробляє його як груповий трафік (групові обмеження + ізоляція групового сеансу). ## Прив’язки розмов ACP -Застарілі чати iMessage також можна прив’язувати до сесій ACP. +Застарілі чати iMessage також можна прив’язувати до сеансів ACP. -Швидкий операторський сценарій: +Швидкий потік дій оператора: -- Виконайте `/acp spawn codex --bind here` у приватному повідомленні або дозволеному груповому чаті. -- Подальші повідомлення в цій самій розмові iMessage маршрутизуються до створеної сесії ACP. -- `/new` і `/reset` скидають цю саму прив’язану сесію ACP на місці. -- `/acp close` закриває сесію ACP і видаляє прив’язку. +- Виконайте `/acp spawn codex --bind here` у DM або дозволеному груповому чаті. +- Майбутні повідомлення в цій самій розмові iMessage маршрутизуватимуться до створеного сеансу ACP. +- `/new` і `/reset` скидають той самий прив’язаний сеанс ACP на місці. +- `/acp close` закриває сеанс ACP і видаляє прив’язку. Налаштовані постійні прив’язки підтримуються через записи верхнього рівня `bindings[]` з `type: "acp"` і `match.channel: "imessage"`. `match.peer.id` може використовувати: -- нормалізований дескриптор приватного повідомлення, наприклад `+15555550123` або `user@example.com` +- нормалізований handle DM, наприклад `+15555550123` або `user@example.com` - `chat_id:` (рекомендовано для стабільних групових прив’язок) - `chat_guid:` - `chat_identifier:` @@ -241,23 +241,23 @@ imsg send "test" } ``` -Див. [ACP Agents](/tools/acp-agents) щодо спільної поведінки прив’язок ACP. +Див. [ACP Agents](/uk/tools/acp-agents) для спільної поведінки прив’язки ACP. -## Сценарії розгортання +## Шаблони розгортання - - Використовуйте окремий Apple ID і користувача macOS, щоб трафік бота був ізольований від вашого особистого профілю Messages. + + Використовуйте окремий Apple ID і macOS-користувача, щоб трафік бота був ізольований від вашого особистого профілю Messages. - Типовий сценарій: + Типовий потік: - 1. Створіть окремого користувача macOS і ввійдіть у нього. + 1. Створіть окремого macOS-користувача і виконайте вхід. 2. Увійдіть у Messages з Apple ID бота в цьому користувачі. - 3. Установіть `imsg` у цього користувача. + 3. Встановіть `imsg` для цього користувача. 4. Створіть SSH-обгортку, щоб OpenClaw міг запускати `imsg` у контексті цього користувача. - 5. Вкажіть `channels.imessage.accounts..cliPath` і `.dbPath` на профіль цього користувача. + 5. Спрямуйте `channels.imessage.accounts..cliPath` і `.dbPath` на профіль цього користувача. - Перший запуск може вимагати підтверджень у графічному інтерфейсі (Automation + Full Disk Access) у сесії цього користувача бота. + Під час першого запуску можуть знадобитися підтвердження через GUI (Automation + Full Disk Access) у сеансі цього користувача бота. @@ -290,36 +290,36 @@ imsg send "test" exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@" ``` - Використовуйте ключі SSH, щоб і SSH, і SCP були неінтерактивними. - Спочатку переконайтеся, що ключ хоста довірений (наприклад, `ssh bot@mac-mini.tailnet-1234.ts.net`), щоб заповнити `known_hosts`. + Використовуйте SSH-ключі, щоб і SSH, і SCP працювали без взаємодії. + Спочатку переконайтеся, що ключ хоста довірений (наприклад, `ssh bot@mac-mini.tailnet-1234.ts.net`), щоб було заповнено `known_hosts`. - iMessage підтримує конфігурацію для кожного облікового запису окремо в `channels.imessage.accounts`. + iMessage підтримує конфігурацію для кожного облікового запису в `channels.imessage.accounts`. - Для кожного облікового запису можна перевизначити такі поля, як `cliPath`, `dbPath`, `allowFrom`, `groupPolicy`, `mediaMaxMb`, налаштування історії та allowlist коренів вкладень. + Для кожного облікового запису можна перевизначати такі поля, як `cliPath`, `dbPath`, `allowFrom`, `groupPolicy`, `mediaMaxMb`, налаштування історії та allowlist кореневих каталогів вкладень. -## Медіа, фрагментація та цілі доставки +## Медіа, розбиття на частини та цілі доставки - - отримання вхідних вкладень є необов’язковим: `channels.imessage.includeAttachments` - - шляхи віддалених вкладень можна отримувати через SCP, коли задано `remoteHost` - - шляхи вкладень мають відповідати дозволеним кореням: + - отримання вхідних вкладень необов’язкове: `channels.imessage.includeAttachments` + - шляхи до віддалених вкладень можна отримувати через SCP, якщо задано `remoteHost` + - шляхи до вкладень мають відповідати дозволеним кореневим каталогам: - `channels.imessage.attachmentRoots` (локально) - `channels.imessage.remoteAttachmentRoots` (віддалений режим SCP) - - типовий шаблон кореня: `/Users/*/Library/Messages/Attachments` + - типовий шаблон кореневого каталогу: `/Users/*/Library/Messages/Attachments` - SCP використовує сувору перевірку ключа хоста (`StrictHostKeyChecking=yes`) - - розмір вихідного медіа керується `channels.imessage.mediaMaxMb` (типово 16 MB) + - розмір вихідних медіа визначається `channels.imessage.mediaMaxMb` (типово 16 MB) - - - ліміт фрагмента тексту: `channels.imessage.textChunkLimit` (типово 4000) - - режим фрагментації: `channels.imessage.chunkMode` + + - ліміт частини тексту: `channels.imessage.textChunkLimit` (типово 4000) + - режим розбиття: `channels.imessage.chunkMode` - `length` (типово) - `newline` (розбиття спочатку за абзацами) @@ -331,7 +331,7 @@ exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@" - `chat_guid:...` - `chat_identifier:...` - Також підтримуються цілі-дескриптори: + Також підтримуються цілі-handle: - `imessage:+1555...` - `sms:+1555...` @@ -344,11 +344,11 @@ imsg chats --limit 20 -## Запис конфігурації +## Записи конфігурації -iMessage типово дозволяє ініційований каналом запис конфігурації (для `/config set|unset`, коли `commands.config: true`). +iMessage типово дозволяє ініційовані каналом записи конфігурації (для `/config set|unset`, коли `commands.config: true`). -Вимкнення: +Вимкнути: ```json5 { @@ -360,11 +360,11 @@ iMessage типово дозволяє ініційований каналом } ``` -## Усунення несправностей +## Усунення неполадок - Перевірте бінарний файл і підтримку RPC: + Перевірте двійковий файл і підтримку RPC: ```bash imsg rpc --help @@ -375,12 +375,12 @@ openclaw channels status --probe - + Перевірте: - `channels.imessage.dmPolicy` - `channels.imessage.allowFrom` - - підтвердження прив’язки (`openclaw pairing list imessage`) + - підтвердження сполучення (`openclaw pairing list imessage`) @@ -389,8 +389,8 @@ openclaw channels status --probe - `channels.imessage.groupPolicy` - `channels.imessage.groupAllowFrom` - - поведінку allowlist для `channels.imessage.groups` - - налаштування шаблонів згадок (`agents.list[].groupChat.mentionPatterns`) + - поведінку allowlist у `channels.imessage.groups` + - конфігурацію шаблонів згадок (`agents.list[].groupChat.mentionPatterns`) @@ -399,36 +399,36 @@ openclaw channels status --probe - `channels.imessage.remoteHost` - `channels.imessage.remoteAttachmentRoots` - - автентифікацію ключами SSH/SCP з хоста gateway - - наявність ключа хоста в `~/.ssh/known_hosts` на хості gateway + - автентифікацію ключем SSH/SCP з хоста gateway + - чи є ключ хоста в `~/.ssh/known_hosts` на хості gateway - читабельність віддаленого шляху на Mac, де працює Messages - - Повторно виконайте в інтерактивному GUI-терміналі в тому самому контексті користувача/сесії та підтвердьте підказки: + + Повторно запустіть в інтерактивному GUI-терміналі в тому самому контексті користувача/сеансу і підтвердьте запити: ```bash imsg chats --limit 1 imsg send "test" ``` - Переконайтеся, що Full Disk Access і Automation надано для контексту процесу, у якому працює OpenClaw/`imsg`. + Переконайтеся, що Full Disk Access і Automation надано для контексту процесу, який запускає OpenClaw/`imsg`. -## Вказівники на довідкові матеріали з конфігурації +## Вказівники на довідник із конфігурації -- [Довідник з конфігурації - iMessage](/gateway/configuration-reference#imessage) -- [Конфігурація gateway](/gateway/configuration) -- [Прив’язка](/channels/pairing) -- [BlueBubbles](/channels/bluebubbles) +- [Довідник із конфігурації - iMessage](/uk/gateway/configuration-reference#imessage) +- [Конфігурація Gateway](/uk/gateway/configuration) +- [Сполучення](/uk/channels/pairing) +- [BlueBubbles](/uk/channels/bluebubbles) ## Пов’язане -- [Огляд каналів](/channels) — усі підтримувані канали -- [Прив’язка](/channels/pairing) — автентифікація приватних повідомлень і сценарій прив’язки -- [Групи](/channels/groups) — поведінка групового чату та керування згадками -- [Маршрутизація каналів](/channels/channel-routing) — маршрутизація сесій для повідомлень -- [Безпека](/gateway/security) — модель доступу та посилення захисту +- [Огляд каналів](/uk/channels) — усі підтримувані канали +- [Сполучення](/uk/channels/pairing) — автентифікація DM і потік сполучення +- [Групи](/uk/channels/groups) — поведінка групових чатів і обмеження за згадками +- [Маршрутизація каналів](/uk/channels/channel-routing) — маршрутизація сеансів для повідомлень +- [Безпека](/uk/gateway/security) — модель доступу та посилення захисту diff --git a/docs/uk/channels/msteams.md b/docs/uk/channels/msteams.md index 47da116f9..8e4e972e8 100644 --- a/docs/uk/channels/msteams.md +++ b/docs/uk/channels/msteams.md @@ -1,37 +1,36 @@ --- read_when: - - Працюємо над функціями каналу Microsoft Teams -summary: Статус підтримки бота Microsoft Teams, можливості та конфігурація + - Робота над функціями каналу Microsoft Teams +summary: Статус підтримки бота Microsoft Teams, можливості та налаштування title: Microsoft Teams x-i18n: - generated_at: "2026-04-21T20:37:36Z" + generated_at: "2026-04-21T21:27:20Z" model: gpt-5.4 provider: openai - source_hash: ed973d8948bc5c5b44f5bc28f361e883389ececc70403c6631fb18ee1254d542 + source_hash: ee9d52fb2cc7801e84249a705e0fa2052d4afbb7ef58cee2d3362b3e7012348c source_path: channels/msteams.md workflow: 15 --- # Microsoft Teams -> «Полиште всяку надію, ті, хто сюди входить». +> «Полиште надію всяк, хто входить сюди». -Оновлено: 2026-03-25 - -Статус: підтримуються текст + вкладення в DM; надсилання файлів у канали/групи потребує `sharePointSiteId` + дозволів Graph (див. [Надсилання файлів у групових чатах](#sending-files-in-group-chats)). Опитування надсилаються через Adaptive Cards. Дії з повідомленнями надають явний `upload-file` для надсилань, де файл є основним. +Статус: підтримуються текст + вкладення DM; надсилання файлів у канали/групи потребує `sharePointSiteId` + дозволів Graph (див. [Надсилання файлів у групових чатах](#sending-files-in-group-chats)). Опитування надсилаються через Adaptive Cards. Дії з повідомленнями надають явний `upload-file` для надсилань, де файл є основним. ## Вбудований Plugin -Microsoft Teams постачається як вбудований Plugin у поточних релізах OpenClaw, тому в звичайній пакетованій збірці окреме встановлення не потрібне. +Microsoft Teams постачається як вбудований Plugin у поточних релізах OpenClaw, тож +в окремому встановленні немає потреби у звичайній пакетованій збірці. -Якщо ви використовуєте старішу збірку або власне встановлення без вбудованого Teams, +Якщо ви використовуєте старішу збірку або спеціальне встановлення, що не містить вбудований Teams, встановіть його вручну: ```bash openclaw plugins install @openclaw/msteams ``` -Локальний checkout (коли запускаєте з git-репозиторію): +Локальний checkout (під час запуску з git-репозиторію): ```bash openclaw plugins install ./path/to/local/msteams-plugin @@ -42,8 +41,8 @@ openclaw plugins install ./path/to/local/msteams-plugin ## Швидке налаштування (для початківців) 1. Переконайтеся, що Plugin Microsoft Teams доступний. - - Поточні пакетовані релізи OpenClaw уже містять його вбудованим. - - У старіших/власних встановленнях його можна додати вручну командами вище. + - Поточні пакетовані релізи OpenClaw уже містять його вбудовано. + - У старіших/спеціальних встановленнях його можна додати вручну командами вище. 2. Створіть **Azure Bot** (App ID + client secret + tenant ID). 3. Налаштуйте OpenClaw з цими обліковими даними. 4. Відкрийте `/api/messages` (типово порт 3978) через публічний URL або тунель. @@ -67,19 +66,19 @@ openclaw plugins install ./path/to/local/msteams-plugin Для production-розгортань розгляньте використання [federated authentication](#federated-authentication-certificate--managed-identity) (сертифікат або managed identity) замість client secret. -Примітка: групові чати типово заблоковані (`channels.msteams.groupPolicy: "allowlist"`). Щоб дозволити відповіді в групах, задайте `channels.msteams.groupAllowFrom` (або використайте `groupPolicy: "open"`, щоб дозволити будь-якому учаснику, за умови згадки). +Примітка: групові чати типово заблоковані (`channels.msteams.groupPolicy: "allowlist"`). Щоб дозволити відповіді в групах, задайте `channels.msteams.groupAllowFrom` (або використайте `groupPolicy: "open"`, щоб дозволити будь-якому учаснику, з обов’язковою згадкою). ## Цілі - Спілкуватися з OpenClaw через Teams DM, групові чати або канали. -- Зберігати детерміновану маршрутизацію: відповіді завжди повертаються в канал, звідки вони надійшли. -- Типово використовувати безпечну поведінку в каналах (потрібні згадки, якщо не налаштовано інакше). +- Зберігати детерміновану маршрутизацію: відповіді завжди повертаються в той канал, звідки вони надійшли. +- Типово використовувати безпечну поведінку каналу (згадки обов’язкові, якщо не налаштовано інакше). -## Записи конфігурації +## Запис конфігурації -Типово Microsoft Teams дозволено записувати оновлення конфігурації, ініційовані `/config set|unset` (потрібно `commands.config: true`). +Типово Microsoft Teams дозволено записувати оновлення конфігурації, ініційовані `/config set|unset` (потребує `commands.config: true`). -Вимкнути можна так: +Щоб вимкнути: ```json5 { @@ -87,21 +86,21 @@ openclaw plugins install ./path/to/local/msteams-plugin } ``` -## Контроль доступу (DM + групи) +## Керування доступом (DM + групи) **Доступ до DM** -- Типово: `channels.msteams.dmPolicy = "pairing"`. Невідомі відправники ігноруються, доки їх не буде схвалено. +- Типово: `channels.msteams.dmPolicy = "pairing"`. Невідомі відправники ігноруються, доки їх не схвалять. - `channels.msteams.allowFrom` має використовувати стабільні AAD object ID. -- UPN/display name є змінними; пряме зіставлення типово вимкнене й вмикається лише через `channels.msteams.dangerouslyAllowNameMatching: true`. +- UPN/display name можуть змінюватися; пряме зіставлення типово вимкнене й вмикається лише через `channels.msteams.dangerouslyAllowNameMatching: true`. - Майстер налаштування може зіставляти імена з ID через Microsoft Graph, якщо це дозволяють облікові дані. -**Груповий доступ** +**Доступ до груп** -- Типово: `channels.msteams.groupPolicy = "allowlist"` (заблоковано, доки ви не додасте `groupAllowFrom`). Використайте `channels.defaults.groupPolicy`, щоб змінити типове значення, якщо його не задано. -- `channels.msteams.groupAllowFrom` визначає, які відправники можуть ініціювати взаємодію в групових чатах/каналах (з резервним переходом до `channels.msteams.allowFrom`). -- Установіть `groupPolicy: "open"`, щоб дозволити будь-якому учаснику (типово все одно потрібна згадка). -- Щоб **заборонити всі канали**, установіть `channels.msteams.groupPolicy: "disabled"`. +- Типово: `channels.msteams.groupPolicy = "allowlist"` (заблоковано, доки ви не додасте `groupAllowFrom`). Використовуйте `channels.defaults.groupPolicy`, щоб змінити типову поведінку, якщо значення не задане. +- `channels.msteams.groupAllowFrom` визначає, які відправники можуть ініціювати дію в групових чатах/каналах (з резервним використанням `channels.msteams.allowFrom`). +- Установіть `groupPolicy: "open"`, щоб дозволити будь-якого учасника (типово все одно потрібна згадка). +- Щоб заборонити **усі канали**, задайте `channels.msteams.groupPolicy: "disabled"`. Приклад: @@ -118,12 +117,12 @@ openclaw plugins install ./path/to/local/msteams-plugin **Teams + allowlist каналів** -- Обмежуйте відповіді в групах/каналах, перелічивши команди Teams і канали в `channels.msteams.teams`. +- Обмежуйте відповіді в групах/каналах, перелічуючи teams і канали в `channels.msteams.teams`. - Ключі мають використовувати стабільні team ID і channel conversation ID. -- Коли `groupPolicy="allowlist"` і присутній allowlist Teams, приймаються лише перелічені команди/канали (за умови згадки). -- Майстер налаштування приймає записи `Team/Channel` і зберігає їх для вас. -- Під час запуску OpenClaw зіставляє назви team/channel і allowlist користувачів з ID (коли це дозволяють дозволи Graph) - і журналює це зіставлення; нерозпізнані назви team/channel зберігаються в тому вигляді, як були введені, але типово ігноруються для маршрутизації, якщо не ввімкнено `channels.msteams.dangerouslyAllowNameMatching: true`. +- Коли `groupPolicy="allowlist"` і задано allowlist teams, приймаються лише перелічені teams/канали (з обов’язковою згадкою). +- Майстер налаштування приймає записи `Team/Channel` і збереже їх для вас. +- Під час запуску OpenClaw зіставляє team/channel та імена користувачів з ID (коли це дозволяють дозволи Graph) + і записує зіставлення в журнал; нерозпізнані назви team/channel зберігаються як введені, але типово ігноруються для маршрутизації, якщо не ввімкнено `channels.msteams.dangerouslyAllowNameMatching: true`. Приклад: @@ -147,11 +146,11 @@ openclaw plugins install ./path/to/local/msteams-plugin ## Як це працює 1. Переконайтеся, що Plugin Microsoft Teams доступний. - - Поточні пакетовані релізи OpenClaw уже містять його вбудованим. - - У старіших/власних встановленнях його можна додати вручну командами вище. + - Поточні пакетовані релізи OpenClaw уже містять його вбудовано. + - У старіших/спеціальних встановленнях його можна додати вручну командами вище. 2. Створіть **Azure Bot** (App ID + secret + tenant ID). -3. Створіть **пакет застосунку Teams**, який посилається на бота й містить наведені нижче дозволи RSC. -4. Завантажте/встановіть застосунок Teams у команду (або в особистий scope для DM). +3. Зберіть **пакет застосунку Teams**, який посилається на бота й містить дозволи RSC нижче. +4. Завантажте/встановіть застосунок Teams у team (або в personal scope для DM). 5. Налаштуйте `msteams` у `~/.openclaw/openclaw.json` (або через env vars) і запустіть Gateway. 6. Gateway типово слухає webhook-трафік Bot Framework на `/api/messages`. @@ -164,18 +163,18 @@ openclaw plugins install ./path/to/local/msteams-plugin 1. Перейдіть до [Create Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot) 2. Заповніть вкладку **Basics**: - | Поле | Значення | + | Field | Value | | ------------------ | -------------------------------------------------------- | | **Bot handle** | Назва вашого бота, наприклад `openclaw-msteams` (має бути унікальною) | - | **Subscription** | Виберіть свою підписку Azure | + | **Subscription** | Виберіть вашу підписку Azure | | **Resource group** | Створіть нову або використайте наявну | - | **Pricing tier** | **Free** для dev/тестування | + | **Pricing tier** | **Free** для розробки/тестування | | **Type of App** | **Single Tenant** (рекомендовано — див. примітку нижче) | | **Creation type** | **Create new Microsoft App ID** | -> **Сповіщення про застарівання:** створення нових multi-tenant ботів було застарілим після 2025-07-31. Для нових ботів використовуйте **Single Tenant**. +> **Повідомлення про застарівання:** створення нових multi-tenant ботів застаріло після 2025-07-31. Для нових ботів використовуйте **Single Tenant**. -3. Натисніть **Review + create** → **Create** (зачекайте приблизно 1–2 хвилини) +3. Натисніть **Review + create** → **Create** (зачекайте ~1-2 хвилини) ### Крок 2: Отримайте облікові дані @@ -185,10 +184,10 @@ openclaw plugins install ./path/to/local/msteams-plugin 4. У розділі **Certificates & secrets** → **New client secret** → скопіюйте **Value** → це ваш `appPassword` 5. Перейдіть до **Overview** → скопіюйте **Directory (tenant) ID** → це ваш `tenantId` -### Крок 3: Налаштуйте Messaging endpoint +### Крок 3: Налаштуйте кінцеву точку обміну повідомленнями 1. У Azure Bot → **Configuration** -2. Установіть **Messaging endpoint** на URL вашого webhook: +2. Установіть **Messaging endpoint** на ваш webhook URL: - Production: `https://your-domain.com/api/messages` - Локальна розробка: використайте тунель (див. [Локальна розробка](#local-development-tunneling) нижче) @@ -198,7 +197,7 @@ openclaw plugins install ./path/to/local/msteams-plugin 2. Натисніть **Microsoft Teams** → Configure → Save 3. Прийміть Terms of Service -## Federated Authentication (Certificate + Managed Identity) +## Federated Authentication (сертифікат + managed identity) > Додано в 2026.3.24 @@ -206,11 +205,11 @@ openclaw plugins install ./path/to/local/msteams-plugin ### Варіант A: автентифікація на основі сертифіката -Використовуйте PEM-сертифікат, зареєстрований у вашому застосунку Entra ID app registration. +Використовуйте PEM-сертифікат, зареєстрований у вашому застосунку Entra ID. **Налаштування:** -1. Згенеруйте або отримайте сертифікат (формат PEM із приватним ключем). +1. Згенеруйте або отримайте сертифікат (формат PEM із private key). 2. У Entra ID → App Registration → **Certificates & secrets** → **Certificates** → завантажте публічний сертифікат. **Конфігурація:** @@ -237,19 +236,19 @@ openclaw plugins install ./path/to/local/msteams-plugin ### Варіант B: Azure Managed Identity -Використовуйте Azure Managed Identity для автентифікації без пароля. Це ідеально для розгортань в інфраструктурі Azure (AKS, App Service, Azure VMs), де доступна managed identity. +Використовуйте Azure Managed Identity для автентифікації без пароля. Це ідеальний варіант для розгортань в інфраструктурі Azure (AKS, App Service, Azure VM), де доступна managed identity. **Як це працює:** 1. Pod/VM бота має managed identity (system-assigned або user-assigned). -2. **Federated identity credential** пов’язує managed identity із застосунком Entra ID app registration. -3. Під час виконання OpenClaw використовує `@azure/identity`, щоб отримувати токени з endpoint Azure IMDS (`169.254.169.254`). -4. Токен передається в Teams SDK для автентифікації бота. +2. **Federated identity credential** пов’язує managed identity із застосунком Entra ID. +3. Під час виконання OpenClaw використовує `@azure/identity`, щоб отримувати токени з кінцевої точки Azure IMDS (`169.254.169.254`). +4. Токен передається до Teams SDK для автентифікації бота. **Передумови:** - Інфраструктура Azure з увімкненою managed identity (AKS workload identity, App Service, VM) -- Створений federated identity credential у застосунку Entra ID app registration +- Створений federated identity credential у застосунку Entra ID - Мережевий доступ до IMDS (`169.254.169.254:80`) з pod/VM **Конфігурація (system-assigned managed identity):** @@ -297,8 +296,8 @@ openclaw plugins install ./path/to/local/msteams-plugin Для розгортань AKS із workload identity: -1. **Увімкніть workload identity** у своєму кластері AKS. -2. **Створіть federated identity credential** у застосунку Entra ID app registration: +1. **Увімкніть workload identity** у вашому кластері AKS. +2. **Створіть federated identity credential** у застосунку Entra ID: ```bash az ad app federated-credential create --id --parameters '{ @@ -309,7 +308,7 @@ openclaw plugins install ./path/to/local/msteams-plugin }' ``` -3. **Додайте анотацію до service account Kubernetes** із client ID застосунку: +3. **Додайте анотацію до service account Kubernetes** з app client ID: ```yaml apiVersion: v1 @@ -320,7 +319,7 @@ openclaw plugins install ./path/to/local/msteams-plugin azure.workload.identity/client-id: "" ``` -4. **Додайте label до pod** для інʼєкції workload identity: +4. **Додайте мітку pod** для ін’єкції workload identity: ```yaml metadata: @@ -328,21 +327,21 @@ openclaw plugins install ./path/to/local/msteams-plugin azure.workload.identity/use: "true" ``` -5. **Переконайтеся в наявності мережевого доступу** до IMDS (`169.254.169.254`) — якщо використовується NetworkPolicy, додайте правило egress, що дозволяє трафік до `169.254.169.254/32` на порт 80. +5. **Забезпечте мережевий доступ** до IMDS (`169.254.169.254`) — якщо ви використовуєте NetworkPolicy, додайте правило egress, яке дозволяє трафік до `169.254.169.254/32` на порт 80. ### Порівняння типів автентифікації -| Метод | Конфігурація | Переваги | Недоліки | +| Method | Config | Pros | Cons | | -------------------- | ---------------------------------------------- | ---------------------------------- | ------------------------------------- | | **Client secret** | `appPassword` | Просте налаштування | Потрібна ротація секретів, менш безпечно | -| **Certificate** | `authType: "federated"` + `certificatePath` | Немає спільного секрету в мережі | Додаткові витрати на керування сертифікатами | -| **Managed Identity** | `authType: "federated"` + `useManagedIdentity` | Без пароля, не потрібно керувати секретами | Потрібна інфраструктура Azure | +| **Certificate** | `authType: "federated"` + `certificatePath` | Немає спільного секрету в мережі | Додаткове навантаження на керування сертифікатами | +| **Managed Identity** | `authType: "federated"` + `useManagedIdentity` | Автентифікація без пароля, не треба керувати секретами | Потрібна інфраструктура Azure | -**Типова поведінка:** якщо `authType` не задано, OpenClaw типово використовує автентифікацію через client secret. Наявні конфігурації продовжують працювати без змін. +**Поведінка за замовчуванням:** якщо `authType` не задано, OpenClaw типово використовує автентифікацію через client secret. Наявні конфігурації й надалі працюватимуть без змін. ## Локальна розробка (тунелювання) -Teams не може дістатися до `localhost`. Для локальної розробки використовуйте тунель: +Teams не може звертатися до `localhost`. Для локальної розробки використовуйте тунель: **Варіант A: ngrok** @@ -361,17 +360,17 @@ tailscale funnel 3978 ## Teams Developer Portal (альтернатива) -Замість ручного створення ZIP-файлу маніфесту, ви можете скористатися [Teams Developer Portal](https://dev.teams.microsoft.com/apps): +Замість ручного створення ZIP-файлу маніфесту ви можете скористатися [Teams Developer Portal](https://dev.teams.microsoft.com/apps): 1. Натисніть **+ New app** 2. Заповніть базову інформацію (назва, опис, інформація про розробника) 3. Перейдіть до **App features** → **Bot** -4. Виберіть **Enter a bot ID manually** і вставте App ID вашого Azure Bot -5. Позначте scope: **Personal**, **Team**, **Group Chat** +4. Виберіть **Enter a bot ID manually** і вставте ваш Azure Bot App ID +5. Позначте області: **Personal**, **Team**, **Group Chat** 6. Натисніть **Distribute** → **Download app package** 7. У Teams: **Apps** → **Manage your apps** → **Upload a custom app** → виберіть ZIP -Це часто простіше, ніж редагувати JSON-маніфести вручну. +Часто це простіше, ніж редагувати JSON-маніфести вручну. ## Тестування бота @@ -379,21 +378,21 @@ tailscale funnel 3978 1. У Azure Portal → ваш ресурс Azure Bot → **Test in Web Chat** 2. Надішліть повідомлення — ви маєте побачити відповідь -3. Це підтверджує, що ваш endpoint webhook працює до налаштування Teams +3. Це підтверджує, що ваш webhook endpoint працює до налаштування Teams **Варіант B: Teams (після встановлення застосунку)** -1. Встановіть застосунок Teams (sideload або через org catalog) +1. Встановіть застосунок Teams (sideload або через каталог організації) 2. Знайдіть бота в Teams і надішліть DM -3. Перевірте журнали Gateway на вхідну activity +3. Перевірте журнали Gateway на вхідну активність ## Налаштування (мінімальний лише текстовий режим) 1. **Переконайтеся, що Plugin Microsoft Teams доступний** - - Поточні пакетовані релізи OpenClaw уже містять його вбудованим. - - У старіших/власних встановленнях його можна додати вручну: + - Поточні пакетовані релізи OpenClaw уже містять його вбудовано. + - У старіших/спеціальних встановленнях його можна додати вручну: - З npm: `openclaw plugins install @openclaw/msteams` - - Із локального checkout: `openclaw plugins install ./path/to/local/msteams-plugin` + - З локального checkout: `openclaw plugins install ./path/to/local/msteams-plugin` 2. **Реєстрація бота** - Створіть Azure Bot (див. вище) і занотуйте: @@ -402,12 +401,12 @@ tailscale funnel 3978 - Tenant ID (single-tenant) 3. **Маніфест застосунку Teams** - - Додайте запис `bot` із `botId = `. - - Scope: `personal`, `team`, `groupChat`. - - `supportsFiles: true` (потрібно для обробки файлів в особистому scope). + - Додайте запис `bot` з `botId = `. + - Області: `personal`, `team`, `groupChat`. + - `supportsFiles: true` (обов’язково для обробки файлів у personal scope). - Додайте дозволи RSC (нижче). - Створіть іконки: `outline.png` (32x32) і `color.png` (192x192). - - Заархівуйте всі три файли разом: `manifest.json`, `outline.png`, `color.png`. + - Запакуйте всі три файли разом: `manifest.json`, `outline.png`, `color.png`. 4. **Налаштуйте OpenClaw** @@ -430,12 +429,12 @@ tailscale funnel 3978 - `MSTEAMS_APP_PASSWORD` - `MSTEAMS_TENANT_ID` - `MSTEAMS_AUTH_TYPE` (необов’язково: `"secret"` або `"federated"`) - - `MSTEAMS_CERTIFICATE_PATH` (federated + certificate) + - `MSTEAMS_CERTIFICATE_PATH` (federated + сертифікат) - `MSTEAMS_CERTIFICATE_THUMBPRINT` (необов’язково, не потрібен для автентифікації) - `MSTEAMS_USE_MANAGED_IDENTITY` (federated + managed identity) - `MSTEAMS_MANAGED_IDENTITY_CLIENT_ID` (лише для user-assigned MI) -5. **Endpoint бота** +5. **Кінцева точка бота** - Установіть Azure Bot Messaging Endpoint на: - `https://:3978/api/messages` (або ваш вибраний path/port). @@ -444,31 +443,31 @@ tailscale funnel 3978 ## Дія інформації про учасника -OpenClaw надає підтримувану Graph дію `member-info` для Microsoft Teams, щоб агенти й автоматизації могли напряму отримувати відомості про учасників каналу (display name, email, role) з Microsoft Graph. +OpenClaw надає для Microsoft Teams дію `member-info`, що працює через Graph, щоб агенти й автоматизації могли напряму отримувати відомості про учасників каналу (display name, email, роль) із Microsoft Graph. Вимоги: - Дозвіл RSC `Member.Read.Group` (уже є в рекомендованому маніфесті) -- Для міжкомандного пошуку: дозвіл Graph Application `User.Read.All` з admin consent +- Для пошуку між teams: дозвіл Graph Application `User.Read.All` з admin consent -Дія контролюється `channels.msteams.actions.memberInfo` (типово: увімкнено, коли доступні облікові дані Graph). +Дія контролюється через `channels.msteams.actions.memberInfo` (типово: увімкнено, коли доступні облікові дані Graph). ## Контекст історії -- `channels.msteams.historyLimit` визначає, скільки останніх повідомлень каналу/групи буде загорнуто в prompt. +- `channels.msteams.historyLimit` керує кількістю недавніх повідомлень каналу/групи, які додаються до prompt. - Використовує резервне значення з `messages.groupChat.historyLimit`. Установіть `0`, щоб вимкнути (типово 50). -- Отримана історія гілки фільтрується за allowlist відправників (`allowFrom` / `groupAllowFrom`), тож початкове заповнення контексту гілки включає лише повідомлення від дозволених відправників. -- Контекст quoted attachment (`ReplyTo*`, похідний від HTML відповіді Teams) наразі передається як отримано. -- Інакше кажучи, allowlist керують тим, хто може запускати агента; сьогодні фільтруються лише окремі шляхи додаткового контексту. -- Історію DM можна обмежити через `channels.msteams.dmHistoryLimit` (ходи користувача). Перевизначення для окремих користувачів: `channels.msteams.dms[""].historyLimit`. +- Отримана історія треду фільтрується за allowlist відправників (`allowFrom` / `groupAllowFrom`), тож початкове наповнення контексту треду містить лише повідомлення від дозволених відправників. +- Контекст цитованих вкладень (`ReplyTo*`, похідний від HTML відповіді Teams) зараз передається як отриманий. +- Інакше кажучи, allowlists контролюють, хто може активувати агента; наразі фільтруються лише окремі шляхи додаткового контексту. +- Історію DM можна обмежити через `channels.msteams.dmHistoryLimit` (ходи користувача). Перевизначення для конкретного користувача: `channels.msteams.dms[""].historyLimit`. ## Поточні дозволи Teams RSC (маніфест) -Це **наявні resourceSpecific permissions** у нашому маніфесті застосунку Teams. Вони застосовуються лише в межах команди/чату, де встановлено застосунок. +Це **наявні resourceSpecific permissions** у маніфесті нашого застосунку Teams. Вони діють лише в межах team/chat, де встановлено застосунок. -**Для каналів (scope команди):** +**Для каналів (область team):** -- `ChannelMessage.Read.Group` (Application) — отримання тексту всіх повідомлень каналу без @mention +- `ChannelMessage.Read.Group` (Application) — отримувати всі текстові повідомлення каналу без @mention - `ChannelMessage.Send.Group` (Application) - `Member.Read.Group` (Application) - `Owner.Read.Group` (Application) @@ -478,11 +477,11 @@ OpenClaw надає підтримувану Graph дію `member-info` для M **Для групових чатів:** -- `ChatMessage.Read.Chat` (Application) — отримання всіх повідомлень групового чату без @mention +- `ChatMessage.Read.Chat` (Application) — отримувати всі повідомлення групового чату без @mention -## Приклад маніфесту Teams (з редагуванням чутливих даних) +## Приклад маніфесту Teams (із вилученими даними) -Мінімальний, коректний приклад з обов’язковими полями. Замініть ID та URL. +Мінімальний, коректний приклад із потрібними полями. Замініть ID та URL. ```json5 { @@ -532,78 +531,78 @@ OpenClaw надає підтримувану Graph дію `member-info` для M ### Застереження щодо маніфесту (обов’язкові поля) -- `bots[].botId` **має** збігатися з App ID Azure Bot. -- `webApplicationInfo.id` **має** збігатися з App ID Azure Bot. -- `bots[].scopes` мають включати поверхні, які ви плануєте використовувати (`personal`, `team`, `groupChat`). -- `bots[].supportsFiles: true` потрібен для обробки файлів в особистому scope. -- `authorization.permissions.resourceSpecific` мають включати читання/надсилання в канали, якщо ви хочете каналовий трафік. +- `bots[].botId` **має** збігатися з Azure Bot App ID. +- `webApplicationInfo.id` **має** збігатися з Azure Bot App ID. +- `bots[].scopes` має включати поверхні, які ви плануєте використовувати (`personal`, `team`, `groupChat`). +- `bots[].supportsFiles: true` є обов’язковим для обробки файлів у personal scope. +- `authorization.permissions.resourceSpecific` має містити дозволи на читання/надсилання в канал, якщо вам потрібен трафік каналу. ### Оновлення наявного застосунку -Щоб оновити вже встановлений застосунок Teams (наприклад, щоб додати дозволи RSC): +Щоб оновити вже встановлений застосунок Teams (наприклад, додати дозволи RSC): 1. Оновіть `manifest.json` новими налаштуваннями -2. **Збільште поле `version`** (наприклад, `1.0.0` → `1.1.0`) -3. **Повторно заархівуйте** маніфест з іконками (`manifest.json`, `outline.png`, `color.png`) +2. **Збільшіть поле `version`** (наприклад, `1.0.0` → `1.1.0`) +3. **Повторно запакуйте в zip** маніфест разом з іконками (`manifest.json`, `outline.png`, `color.png`) 4. Завантажте новий zip: - - **Варіант A (Teams Admin Center):** Teams Admin Center → Teams apps → Manage apps → знайдіть свій застосунок → Upload new version - - **Варіант B (Sideload):** у Teams → Apps → Manage your apps → Upload a custom app -5. **Для каналів команди:** перевстановіть застосунок у кожній команді, щоб нові дозволи набули чинності -6. **Повністю закрийте й знову запустіть Teams** (не просто закрийте вікно), щоб очистити кешовані метадані застосунку + - **Варіант A (Teams Admin Center):** Teams Admin Center → Teams apps → Manage apps → знайдіть ваш застосунок → Upload new version + - **Варіант B (Sideload):** У Teams → Apps → Manage your apps → Upload a custom app +5. **Для каналів team:** перевстановіть застосунок у кожній team, щоб нові дозволи набрали чинності +6. **Повністю закрийте і знову запустіть Teams** (а не просто закрийте вікно), щоб очистити кешовані метадані застосунку ## Можливості: лише RSC проти Graph -### З **лише Teams RSC** (застосунок встановлено, без дозволів Graph API) +### Із **лише Teams RSC** (застосунок встановлено, без дозволів Microsoft Graph API) Працює: - Читання **текстового** вмісту повідомлень каналу. - Надсилання **текстового** вмісту повідомлень каналу. -- Отримання файлових вкладень у **personal (DM)**. +- Отримання **особистих (DM)** файлових вкладень. НЕ працює: -- **Зображення або вміст файлів** у каналах/групах (payload містить лише HTML-заглушку). -- Завантаження вкладень, що зберігаються в SharePoint/OneDrive. -- Читання історії повідомлень (поза live webhook event). +- Вміст **зображень або файлів** у каналах/групах (payload містить лише HTML-заглушку). +- Завантаження вкладень, що зберігаються у SharePoint/OneDrive. +- Читання історії повідомлень (поза межами живої webhook-події). -### З **Teams RSC + дозволами Microsoft Graph Application** +### Із **Teams RSC + дозволами Microsoft Graph Application** Додається: -- Завантаження hosted contents (зображення, вставлені в повідомлення). -- Завантаження файлових вкладень, що зберігаються в SharePoint/OneDrive. +- Завантаження hosted contents (зображень, вставлених у повідомлення). +- Завантаження файлових вкладень, що зберігаються у SharePoint/OneDrive. - Читання історії повідомлень каналу/чату через Graph. ### RSC проти Graph API -| Можливість | Дозволи RSC | Graph API | -| ---------------------- | -------------------- | ----------------------------------- | -| **Повідомлення в реальному часі** | Так (через webhook) | Ні (лише polling) | -| **Історичні повідомлення** | Ні | Так (можна запитувати історію) | -| **Складність налаштування** | Лише маніфест застосунку | Потрібні admin consent + token flow | -| **Працює офлайн** | Ні (має працювати) | Так (можна запитувати будь-коли) | +| Capability | RSC Permissions | Graph API | +| ----------------------- | -------------------- | ----------------------------------- | +| **Real-time messages** | Так (через webhook) | Ні (лише polling) | +| **Historical messages** | Ні | Так (можна запитувати історію) | +| **Setup complexity** | Лише маніфест застосунку | Потребує admin consent + token flow | +| **Works offline** | Ні (має бути запущено) | Так (можна запитувати будь-коли) | -**Висновок:** RSC призначений для прослуховування в реальному часі; Graph API — для історичного доступу. Щоб наздоганяти пропущені повідомлення під час офлайну, вам потрібен Graph API з `ChannelMessage.Read.All` (потрібен admin consent). +**Підсумок:** RSC призначено для прослуховування в реальному часі; Graph API — для історичного доступу. Щоб надолужувати пропущені повідомлення під час офлайну, вам потрібен Graph API з `ChannelMessage.Read.All` (потребує admin consent). -## Graph-enabled media + history (потрібно для каналів) +## Media + history з Graph (обов’язково для каналів) -Якщо вам потрібні зображення/файли в **каналах** або потрібно отримувати **історію повідомлень**, необхідно ввімкнути дозволи Microsoft Graph і надати admin consent. +Якщо вам потрібні зображення/файли в **каналах** або ви хочете отримувати **історію повідомлень**, потрібно ввімкнути дозволи Microsoft Graph і надати admin consent. 1. У **App Registration** Entra ID (Azure AD) додайте дозволи Microsoft Graph **Application permissions**: - `ChannelMessage.Read.All` (вкладення каналів + історія) - `Chat.Read.All` або `ChatMessage.Read.All` (групові чати) 2. **Надайте admin consent** для tenant. -3. Збільште **версію маніфесту** застосунку Teams, повторно завантажте його й **перевстановіть застосунок у Teams**. +3. Збільшіть **версію маніфесту** застосунку Teams, повторно завантажте його й **перевстановіть застосунок у Teams**. 4. **Повністю закрийте й знову запустіть Teams**, щоб очистити кешовані метадані застосунку. -**Додатковий дозвіл для згадок користувачів:** @mentions користувачів працюють відразу для користувачів у поточній розмові. Однак якщо ви хочете динамічно шукати й згадувати користувачів, які **не перебувають у поточній розмові**, додайте дозвіл `User.Read.All` (Application) і надайте admin consent. +**Додатковий дозвіл для згадок користувачів:** @mentions користувачів працюють одразу для користувачів у розмові. Однак якщо ви хочете динамічно шукати й згадувати користувачів, які **не перебувають у поточній розмові**, додайте дозвіл `User.Read.All` (Application) і надайте admin consent. ## Відомі обмеження ### Тайм-аути webhook -Teams доставляє повідомлення через HTTP webhook. Якщо обробка триває надто довго (наприклад, через повільні відповіді LLM), ви можете побачити: +Teams доставляє повідомлення через HTTP webhook. Якщо обробка триває надто довго (наприклад, повільні відповіді LLM), ви можете побачити: - тайм-аути Gateway - повторні спроби Teams доставити повідомлення (що спричиняє дублікати) @@ -615,38 +614,38 @@ OpenClaw обробляє це, швидко повертаючи відпові Markdown у Teams більш обмежений, ніж у Slack або Discord: -- Базове форматування працює: **жирний**, _курсив_, `code`, посилання +- Працює базове форматування: **жирний**, _курсив_, `code`, посилання - Складний markdown (таблиці, вкладені списки) може відображатися некоректно - Adaptive Cards підтримуються для опитувань і semantic presentation sends (див. нижче) ## Конфігурація -Ключові налаштування (див. `/gateway/configuration` для спільних шаблонів каналів): +Основні параметри (див. `/gateway/configuration` для спільних шаблонів каналів): - `channels.msteams.enabled`: увімкнути/вимкнути канал. - `channels.msteams.appId`, `channels.msteams.appPassword`, `channels.msteams.tenantId`: облікові дані бота. - `channels.msteams.webhook.port` (типово `3978`) - `channels.msteams.webhook.path` (типово `/api/messages`) - `channels.msteams.dmPolicy`: `pairing | allowlist | open | disabled` (типово: pairing) -- `channels.msteams.allowFrom`: allowlist для DM (рекомендовано AAD object ID). Майстер налаштування зіставляє імена з ID під час налаштування, коли доступний доступ до Graph. -- `channels.msteams.dangerouslyAllowNameMatching`: аварійний перемикач для повторного ввімкнення зіставлення за змінними UPN/display-name та прямої маршрутизації за назвами team/channel. +- `channels.msteams.allowFrom`: allowlist для DM (рекомендовано AAD object ID). Майстер налаштування під час setup зіставляє імена з ID, коли доступний доступ до Graph. +- `channels.msteams.dangerouslyAllowNameMatching`: аварійний перемикач для повторного ввімкнення зіставлення за змінюваними UPN/display-name і прямої маршрутизації за назвами team/channel. - `channels.msteams.textChunkLimit`: розмір фрагмента вихідного тексту. - `channels.msteams.chunkMode`: `length` (типово) або `newline`, щоб розбивати за порожніми рядками (межами абзаців) перед розбиттям за довжиною. - `channels.msteams.mediaAllowHosts`: allowlist для хостів вхідних вкладень (типово домени Microsoft/Teams). - `channels.msteams.mediaAuthAllowHosts`: allowlist для додавання заголовків Authorization під час повторних спроб отримання медіа (типово хости Graph + Bot Framework). - `channels.msteams.requireMention`: вимагати @mention у каналах/групах (типово true). - `channels.msteams.replyStyle`: `thread | top-level` (див. [Стиль відповіді](#reply-style-threads-vs-posts)). -- `channels.msteams.teams..replyStyle`: перевизначення для окремої команди. -- `channels.msteams.teams..requireMention`: перевизначення для окремої команди. -- `channels.msteams.teams..tools`: типові перевизначення політики інструментів для команди (`allow`/`deny`/`alsoAllow`), які використовуються, коли немає перевизначення для каналу. -- `channels.msteams.teams..toolsBySender`: типові перевизначення політики інструментів для команди за відправником (підтримується wildcard `"*"`). -- `channels.msteams.teams..channels..replyStyle`: перевизначення для окремого каналу. -- `channels.msteams.teams..channels..requireMention`: перевизначення для окремого каналу. -- `channels.msteams.teams..channels..tools`: перевизначення політики інструментів для каналу (`allow`/`deny`/`alsoAllow`). -- `channels.msteams.teams..channels..toolsBySender`: перевизначення політики інструментів для каналу за відправником (підтримується wildcard `"*"`). +- `channels.msteams.teams..replyStyle`: перевизначення для конкретної team. +- `channels.msteams.teams..requireMention`: перевизначення для конкретної team. +- `channels.msteams.teams..tools`: типові перевизначення політики інструментів для team (`allow`/`deny`/`alsoAllow`), які використовуються, коли немає перевизначення для каналу. +- `channels.msteams.teams..toolsBySender`: типові перевизначення політики інструментів для team за відправником (`"*"` wildcard підтримується). +- `channels.msteams.teams..channels..replyStyle`: перевизначення для конкретного каналу. +- `channels.msteams.teams..channels..requireMention`: перевизначення для конкретного каналу. +- `channels.msteams.teams..channels..tools`: перевизначення політики інструментів для конкретного каналу (`allow`/`deny`/`alsoAllow`). +- `channels.msteams.teams..channels..toolsBySender`: перевизначення політики інструментів для конкретного каналу за відправником (`"*"` wildcard підтримується). - Ключі `toolsBySender` мають використовувати явні префікси: - `id:`, `e164:`, `username:`, `name:` (застарілі ключі без префікса, як і раніше, зіставляються лише з `id:`). -- `channels.msteams.actions.memberInfo`: увімкнути або вимкнути дію інформації про учасника на основі Graph (типово: увімкнено, коли доступні облікові дані Graph). + `id:`, `e164:`, `username:`, `name:` (застарілі ключі без префікса все ще зіставляються лише з `id:`). +- `channels.msteams.actions.memberInfo`: увімкнути або вимкнути дію інформації про учасника, що працює через Graph (типово: увімкнено, коли доступні облікові дані Graph). - `channels.msteams.authType`: тип автентифікації — `"secret"` (типово) або `"federated"`. - `channels.msteams.certificatePath`: шлях до PEM-файлу сертифіката (federated + автентифікація сертифікатом). - `channels.msteams.certificateThumbprint`: thumbprint сертифіката (необов’язково, не потрібен для автентифікації). @@ -654,29 +653,29 @@ Markdown у Teams більш обмежений, ніж у Slack або Discord: - `channels.msteams.managedIdentityClientId`: client ID для user-assigned managed identity. - `channels.msteams.sharePointSiteId`: SharePoint site ID для вивантаження файлів у групових чатах/каналах (див. [Надсилання файлів у групових чатах](#sending-files-in-group-chats)). -## Маршрутизація й сесії +## Маршрутизація та сесії - Ключі сесій відповідають стандартному формату агента (див. [/concepts/session](/uk/concepts/session)): - - Direct messages спільно використовують основну сесію (`agent::`). + - Прямі повідомлення використовують основну сесію (`agent::`). - Повідомлення каналу/групи використовують conversation id: - `agent::msteams:channel:` - `agent::msteams:group:` -## Стиль відповіді: Threads проти Posts +## Стиль відповіді: треди проти дописів Нещодавно Teams запровадив два стилі UI каналів поверх тієї самої базової моделі даних: -| Стиль | Опис | Рекомендований `replyStyle` | -| ---------------------- | --------------------------------------------------------- | --------------------------- | -| **Posts** (класичний) | Повідомлення відображаються як картки з гілками відповідей під ними | `thread` (типово) | -| **Threads** (як у Slack) | Повідомлення йдуть лінійно, більше схоже на Slack | `top-level` | +| Style | Description | Recommended `replyStyle` | +| ------------------------ | --------------------------------------------------------- | ------------------------ | +| **Posts** (classic) | Повідомлення відображаються як картки з тредовими відповідями під ними | `thread` (типово) | +| **Threads** (Slack-like) | Повідомлення йдуть лінійно, більше схоже на Slack | `top-level` | -**Проблема:** API Teams не показує, який стиль UI використовує канал. Якщо використати неправильний `replyStyle`: +**Проблема:** Teams API не показує, який саме стиль UI використовує канал. Якщо використовувати неправильний `replyStyle`: -- `thread` у каналі стилю Threads → відповіді виглядають незграбно вкладеними -- `top-level` у каналі стилю Posts → відповіді з’являються як окремі повідомлення верхнього рівня, а не в гілці +- `thread` у каналі зі стилем Threads → відповіді відображаються незручно вкладеними +- `top-level` у каналі зі стилем Posts → відповіді з’являються як окремі дописи верхнього рівня, а не в треді -**Рішення:** Налаштуйте `replyStyle` для кожного каналу залежно від того, як налаштований канал: +**Рішення:** налаштуйте `replyStyle` для кожного каналу залежно від того, як налаштований канал: ```json5 { @@ -701,44 +700,44 @@ Markdown у Teams більш обмежений, ніж у Slack або Discord: **Поточні обмеження:** -- **DM:** зображення й файлові вкладення працюють через API файлів ботів Teams. -- **Канали/групи:** вкладення живуть у сховищі M365 (SharePoint/OneDrive). Payload webhook містить лише HTML-заглушку, а не фактичні байти файлу. **Для завантаження вкладень каналу потрібні дозволи Graph API**. -- Для явних надсилань, де файл є основним, використовуйте `action=upload-file` з `media` / `filePath` / `path`; необов’язковий `message` стає супровідним текстом/коментарем, а `filename` перевизначає назву завантаженого файлу. +- **DM:** зображення й файлові вкладення працюють через file API бота Teams. +- **Канали/групи:** вкладення зберігаються в M365 storage (SharePoint/OneDrive). Payload webhook містить лише HTML-заглушку, а не фактичні байти файлу. Для завантаження вкладень каналу **потрібні дозволи Graph API**. +- Для явного надсилання, де файл є основним, використовуйте `action=upload-file` з `media` / `filePath` / `path`; необов’язковий `message` стає супровідним текстом/коментарем, а `filename` перевизначає ім’я завантаженого файлу. -Без дозволів Graph повідомлення каналів із зображеннями надходитимуть лише як текст (вміст зображення для бота недоступний). -Типово OpenClaw завантажує медіа лише з хостів Microsoft/Teams. Перевизначайте це через `channels.msteams.mediaAllowHosts` (використайте `["*"]`, щоб дозволити будь-який хост). -Заголовки Authorization додаються лише для хостів у `channels.msteams.mediaAuthAllowHosts` (типово хости Graph + Bot Framework). Тримайте цей список строгим (уникайте multi-tenant суфіксів). +Без дозволів Graph повідомлення каналів із зображеннями отримуватимуться лише як текст (вміст зображення боту недоступний). +Типово OpenClaw завантажує медіа лише з hostname Microsoft/Teams. Перевизначте це через `channels.msteams.mediaAllowHosts` (використайте `["*"]`, щоб дозволити будь-який хост). +Заголовки Authorization додаються лише для хостів у `channels.msteams.mediaAuthAllowHosts` (типово хости Graph + Bot Framework). Тримайте цей список суворим (уникайте multi-tenant suffixes). ## Надсилання файлів у групових чатах -Боти можуть надсилати файли в DM через потік FileConsentCard (вбудований). Однак **надсилання файлів у групових чатах/каналах** потребує додаткового налаштування: +Боти можуть надсилати файли в DM, використовуючи потік FileConsentCard (вбудований). Однак **надсилання файлів у групових чатах/каналах** потребує додаткового налаштування: -| Контекст | Як надсилаються файли | Потрібне налаштування | -| ------------------------ | ---------------------------------------- | ----------------------------------------------- | -| **DM** | FileConsentCard → користувач приймає → бот вивантажує | Працює одразу | -| **Групові чати/канали** | Вивантаження в SharePoint → посилання для спільного доступу | Потрібні `sharePointSiteId` + дозволи Graph | -| **Зображення (будь-який контекст)** | Inline у кодуванні Base64 | Працює одразу | +| Context | How files are sent | Setup needed | +| ------------------------ | -------------------------------------------- | ----------------------------------------------- | +| **DMs** | FileConsentCard → користувач приймає → бот вивантажує | Працює одразу | +| **Group chats/channels** | Вивантаження до SharePoint → посилання для спільного доступу | Потрібні `sharePointSiteId` + дозволи Graph | +| **Images (any context)** | Inline у форматі Base64 | Працює одразу | ### Чому груповим чатам потрібен SharePoint -Боти не мають особистого диска OneDrive (endpoint Graph API `/me/drive` не працює для application identities). Щоб надсилати файли в групових чатах/каналах, бот вивантажує їх на **сайт SharePoint** і створює посилання для спільного доступу. +Боти не мають особистого диска OneDrive (кінцева точка Graph API `/me/drive` не працює для application identities). Щоб надсилати файли в групових чатах/каналах, бот вивантажує їх на **сайт SharePoint** і створює посилання для спільного доступу. ### Налаштування -1. **Додайте дозволи Graph API** в Entra ID (Azure AD) → App Registration: - - `Sites.ReadWrite.All` (Application) — вивантаження файлів у SharePoint - - `Chat.Read.All` (Application) — необов’язково, вмикає посилання для спільного доступу для окремих користувачів +1. **Додайте дозволи Graph API** у Entra ID (Azure AD) → App Registration: + - `Sites.ReadWrite.All` (Application) — вивантаження файлів до SharePoint + - `Chat.Read.All` (Application) — необов’язково, вмикає посилання для спільного доступу на рівні користувачів 2. **Надайте admin consent** для tenant. 3. **Отримайте ваш SharePoint site ID:** ```bash - # Через Graph Explorer або curl з чинним токеном: + # Через Graph Explorer або curl з дійсним токеном: curl -H "Authorization: Bearer $TOKEN" \ "https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}" - # Приклад: для сайту за адресою "contoso.sharepoint.com/sites/BotFiles" + # Приклад: для сайту "contoso.sharepoint.com/sites/BotFiles" curl -H "Authorization: Bearer $TOKEN" \ "https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles" @@ -760,40 +759,40 @@ Markdown у Teams більш обмежений, ніж у Slack або Discord: ### Поведінка спільного доступу -| Дозвіл | Поведінка спільного доступу | -| --------------------------------------- | ---------------------------------------------------------- | -| `Sites.ReadWrite.All` only | Посилання для спільного доступу на рівні організації (доступне будь-кому в org) | -| `Sites.ReadWrite.All` + `Chat.Read.All` | Посилання для спільного доступу для окремих користувачів (доступне лише учасникам чату) | +| Permission | Sharing behavior | +| --------------------------------------- | --------------------------------------------------------- | +| `Sites.ReadWrite.All` only | Посилання для спільного доступу на всю організацію (доступне будь-кому в організації) | +| `Sites.ReadWrite.All` + `Chat.Read.All` | Посилання для спільного доступу на рівні користувачів (доступне лише учасникам чату) | -Спільний доступ для окремих користувачів безпечніший, оскільки доступ до файлу мають лише учасники чату. Якщо дозвіл `Chat.Read.All` відсутній, бот повертається до спільного доступу на рівні організації. +Спільний доступ на рівні користувачів безпечніший, оскільки лише учасники чату можуть отримати доступ до файлу. Якщо дозвіл `Chat.Read.All` відсутній, бот повертається до спільного доступу на всю організацію. ### Резервна поведінка -| Сценарій | Результат | -| ------------------------------------------------ | --------------------------------------------------- | -| Груповий чат + файл + налаштовано `sharePointSiteId` | Вивантаження в SharePoint, надсилання посилання для спільного доступу | -| Груповий чат + файл + немає `sharePointSiteId` | Спроба вивантаження в OneDrive (може не вдатися), надсилання лише тексту | -| Особистий чат + файл | Потік FileConsentCard (працює без SharePoint) | -| Будь-який контекст + зображення | Inline у кодуванні Base64 (працює без SharePoint) | +| Scenario | Result | +| ------------------------------------------------- | -------------------------------------------------- | +| Груповий чат + файл + налаштовано `sharePointSiteId` | Вивантаження до SharePoint, надсилання посилання для спільного доступу | +| Груповий чат + файл + немає `sharePointSiteId` | Спроба вивантаження в OneDrive (може завершитися помилкою), надсилається лише текст | +| Особистий чат + файл | Потік FileConsentCard (працює без SharePoint) | +| Будь-який контекст + зображення | Inline у форматі Base64 (працює без SharePoint) | ### Де зберігаються файли -Вивантажені файли зберігаються в папці `/OpenClawShared/` у типовій бібліотеці документів налаштованого сайту SharePoint. +Вивантажені файли зберігаються в папці `/OpenClawShared/` у стандартній бібліотеці документів налаштованого сайту SharePoint. ## Опитування (Adaptive Cards) -OpenClaw надсилає опитування Teams як Adaptive Cards (рідного API опитувань Teams немає). +OpenClaw надсилає опитування Teams як Adaptive Cards (власного API опитувань у Teams немає). - CLI: `openclaw message poll --channel msteams --target conversation: ...` - Голоси записуються Gateway у `~/.openclaw/msteams-polls.json`. -- Gateway має залишатися онлайн, щоб записувати голоси. -- Опитування поки не публікують підсумки результатів автоматично (за потреби перегляньте файл сховища). +- Щоб записувати голоси, Gateway має залишатися онлайн. +- Підсумкові зведення результатів опитувань поки не публікуються автоматично (за потреби перевіряйте файл сховища). ## Картки presentation -Надсилайте семантичні payload presentation користувачам Teams або в розмови через інструмент `message` або CLI. OpenClaw відтворює їх як Teams Adaptive Cards із загального контракту presentation. +Надсилайте семантичні payload presentation користувачам або розмовам Teams за допомогою інструмента `message` або CLI. OpenClaw відтворює їх як Teams Adaptive Cards на основі узагальненого контракту presentation. -Параметр `presentation` приймає семантичні блоки. Якщо задано `presentation`, текст повідомлення є необов’язковим. +Параметр `presentation` приймає семантичні блоки. Якщо передано `presentation`, текст повідомлення не є обов’язковим. **Інструмент агента:** @@ -817,18 +816,18 @@ openclaw message send --channel msteams \ --presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello!"}]}' ``` -Докладно про формат цілі див. [Формати цілі](#target-formats) нижче. +Докладніше про формат target див. у [Формати target](#target-formats) нижче. -## Формати цілі +## Формати target -Цілі MSTeams використовують префікси, щоб розрізняти користувачів і розмови: +Target у MSTeams використовують префікси, щоб розрізняти користувачів і розмови: -| Тип цілі | Формат | Приклад | -| ---------------------- | -------------------------------- | --------------------------------------------------- | -| Користувач (за ID) | `user:` | `user:40a1a0ed-4ff2-4164-a219-55518990c197` | -| Користувач (за ім’ям) | `user:` | `user:John Smith` (потрібен Graph API) | -| Група/канал | `conversation:` | `conversation:19:abc123...@thread.tacv2` | -| Група/канал (raw) | `` | `19:abc123...@thread.tacv2` (якщо містить `@thread`) | +| Target type | Format | Example | +| ------------------- | -------------------------------- | --------------------------------------------------- | +| Користувач (за ID) | `user:` | `user:40a1a0ed-4ff2-4164-a219-55518990c197` | +| Користувач (за ім’ям) | `user:` | `user:John Smith` (потребує Graph API) | +| Група/канал | `conversation:` | `conversation:19:abc123...@thread.tacv2` | +| Група/канал (raw) | `` | `19:abc123...@thread.tacv2` (якщо містить `@thread`) | **Приклади CLI:** @@ -836,7 +835,7 @@ openclaw message send --channel msteams \ # Надіслати користувачу за ID openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello" -# Надіслати користувачу за display name (викликає пошук через Graph API) +# Надіслати користувачу за display name (запускає Graph API lookup) openclaw message send --channel msteams --target "user:John Smith" --message "Hello" # Надіслати в груповий чат або канал @@ -870,94 +869,94 @@ openclaw message send --channel msteams --target "conversation:19:abc...@thread. } ``` -Примітка: без префікса `user:` імена типово трактуються як цілі групи/команди. Завжди використовуйте `user:`, коли націлюєтеся на людей за display name. +Примітка: без префікса `user:` імена типово трактуються як цілі групи/team. Завжди використовуйте `user:`, коли адресуєте повідомлення людям за display name. ## Проактивні повідомлення - Проактивні повідомлення можливі лише **після** взаємодії користувача, оскільки саме тоді ми зберігаємо посилання на розмову. -- Див. `/gateway/configuration` для `dmPolicy` і керування через allowlist. +- Див. `/gateway/configuration` для `dmPolicy` і обмеження через allowlist. -## ID команд і каналів (поширена пастка) +## ID team і channel (типова пастка) -Параметр запиту `groupId` в URL Teams — **НЕ** той ID команди, який використовується для конфігурації. Натомість витягуйте ID зі шляху URL: +Параметр запиту `groupId` в URL Teams — **НЕ** той team ID, який використовується для конфігурації. Натомість витягуйте ID зі шляху URL: -**URL команди:** +**URL team:** ``` https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=... └────────────────────────────┘ - ID команди (декодуйте URL) + Team ID (декодуйте URL) ``` -**URL каналу:** +**URL channel:** ``` https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=... └─────────────────────────┘ - ID каналу (декодуйте URL) + Channel ID (декодуйте URL) ``` **Для конфігурації:** -- ID команди = сегмент шляху після `/team/` (після URL-декодування, наприклад `19:Bk4j...@thread.tacv2`) -- ID каналу = сегмент шляху після `/channel/` (після URL-декодування) +- Team ID = сегмент шляху після `/team/` (після декодування URL, наприклад, `19:Bk4j...@thread.tacv2`) +- Channel ID = сегмент шляху після `/channel/` (після декодування URL) - Параметр запиту `groupId` **ігноруйте** ## Приватні канали Боти мають обмежену підтримку в приватних каналах: -| Функція | Стандартні канали | Приватні канали | -| --------------------------- | ----------------- | --------------------- | -| Встановлення бота | Так | Обмежено | -| Повідомлення в реальному часі (webhook) | Так | Може не працювати | -| Дозволи RSC | Так | Можуть поводитися інакше | -| @mentions | Так | Якщо бот доступний | -| Історія через Graph API | Так | Так (з дозволами) | +| Feature | Standard Channels | Private Channels | +| ---------------------------- | ----------------- | --------------------- | +| Встановлення бота | Так | Обмежено | +| Повідомлення в реальному часі (webhook) | Так | Може не працювати | +| Дозволи RSC | Так | Можуть працювати інакше | +| @mentions | Так | Якщо бот доступний | +| Історія через Graph API | Так | Так (за наявності дозволів) | -**Обхідні варіанти, якщо приватні канали не працюють:** +**Обхідні шляхи, якщо приватні канали не працюють:** 1. Використовуйте стандартні канали для взаємодії з ботом 2. Використовуйте DM — користувачі завжди можуть писати боту напряму -3. Використовуйте Graph API для історичного доступу (потрібен `ChannelMessage.Read.All`) +3. Використовуйте Graph API для історичного доступу (потребує `ChannelMessage.Read.All`) -## Усунення несправностей +## Усунення проблем -### Поширені проблеми +### Типові проблеми - **Зображення не відображаються в каналах:** відсутні дозволи Graph або admin consent. Перевстановіть застосунок Teams і повністю закрийте/заново відкрийте Teams. -- **Немає відповідей у каналі:** типово потрібні згадки; установіть `channels.msteams.requireMention=false` або налаштуйте це для окремої команди/каналу. -- **Невідповідність версій (Teams усе ще показує старий маніфест):** видаліть і повторно додайте застосунок та повністю закрийте Teams, щоб оновити стан. -- **401 Unauthorized від webhook:** це очікувано під час ручного тестування без Azure JWT — означає, що endpoint досяжний, але автентифікація не пройшла. Для коректної перевірки використовуйте Azure Web Chat. +- **Немає відповідей у каналі:** згадки типово обов’язкові; задайте `channels.msteams.requireMention=false` або налаштуйте це для конкретної team/channel. +- **Невідповідність версій (Teams досі показує старий маніфест):** видаліть і знову додайте застосунок та повністю закрийте Teams, щоб оновити дані. +- **401 Unauthorized від webhook:** очікувана поведінка під час ручного тестування без Azure JWT — означає, що endpoint доступний, але автентифікація не пройшла. Для коректної перевірки використовуйте Azure Web Chat. ### Помилки завантаження маніфесту -- **"Icon file cannot be empty":** маніфест посилається на файли іконок розміром 0 байтів. Створіть коректні PNG-іконки (`outline.png` 32x32, `color.png` 192x192). -- **"webApplicationInfo.Id already in use":** застосунок усе ще встановлений в іншій команді/чаті. Спочатку знайдіть і видаліть його або зачекайте 5–10 хвилин на поширення змін. -- **"Something went wrong" під час завантаження:** завантажте через [https://admin.teams.microsoft.com](https://admin.teams.microsoft.com), відкрийте DevTools у браузері (F12) → вкладка Network і перевірте тіло відповіді на фактичну помилку. -- **Sideload не працює:** спробуйте "Upload an app to your org's app catalog" замість "Upload a custom app" — це часто обходить обмеження sideload. +- **"Icon file cannot be empty":** маніфест посилається на файли іконок розміром 0 байт. Створіть коректні PNG-іконки (`outline.png` 32x32, `color.png` 192x192). +- **"webApplicationInfo.Id already in use":** застосунок усе ще встановлений в іншій team/chat. Спочатку знайдіть і видаліть його або зачекайте 5–10 хвилин на поширення змін. +- **"Something went wrong" під час завантаження:** замість цього завантажуйте через [https://admin.teams.microsoft.com](https://admin.teams.microsoft.com), відкрийте DevTools у браузері (F12) → вкладка Network і перевірте тіло відповіді на фактичну помилку. +- **Не вдається sideload:** спробуйте "Upload an app to your org's app catalog" замість "Upload a custom app" — це часто обходить обмеження sideload. ### Дозволи RSC не працюють 1. Переконайтеся, що `webApplicationInfo.id` точно збігається з App ID вашого бота -2. Повторно завантажте застосунок і перевстановіть його в команді/чаті -3. Перевірте, чи адміністратор вашої org не заблокував дозволи RSC -4. Підтвердьте, що використовуєте правильний scope: `ChannelMessage.Read.Group` для команд, `ChatMessage.Read.Chat` для групових чатів +2. Повторно завантажте застосунок і перевстановіть його в team/chat +3. Перевірте, чи адміністратор вашої організації не заблокував дозволи RSC +4. Підтвердьте, що ви використовуєте правильну область: `ChannelMessage.Read.Group` для teams, `ChatMessage.Read.Chat` для групових чатів ## Посилання - [Create Azure Bot](https://learn.microsoft.com/en-us/azure/bot-service/bot-service-quickstart-registration) - посібник із налаштування Azure Bot -- [Teams Developer Portal](https://dev.teams.microsoft.com/apps) - створення та керування застосунками Teams +- [Teams Developer Portal](https://dev.teams.microsoft.com/apps) - створення/керування застосунками Teams - [Teams app manifest schema](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema) - [Receive channel messages with RSC](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/channel-messages-with-rsc) - [RSC permissions reference](https://learn.microsoft.com/en-us/microsoftteams/platform/graph-api/rsc/resource-specific-consent) -- [Teams bot file handling](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4) (для каналу/групи потрібен Graph) +- [Teams bot file handling](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4) (для channel/group потрібен Graph) - [Proactive messaging](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages) ## Пов’язане -- [Channels Overview](/uk/channels) — усі підтримувані канали +- [Огляд каналів](/uk/channels) — усі підтримувані канали - [Pairing](/uk/channels/pairing) — автентифікація DM і потік pairing -- [Groups](/uk/channels/groups) — поведінка групового чату й керування через згадки -- [Channel Routing](/uk/channels/channel-routing) — маршрутизація сесій для повідомлень -- [Security](/uk/gateway/security) — модель доступу та посилення захисту +- [Групи](/uk/channels/groups) — поведінка групового чату та обмеження через згадки +- [Маршрутизація каналів](/uk/channels/channel-routing) — маршрутизація сесій для повідомлень +- [Безпека](/uk/gateway/security) — модель доступу та посилення захисту diff --git a/docs/uk/channels/troubleshooting.md b/docs/uk/channels/troubleshooting.md index b455db263..3b3e63703 100644 --- a/docs/uk/channels/troubleshooting.md +++ b/docs/uk/channels/troubleshooting.md @@ -1,25 +1,25 @@ --- read_when: - - Транспорт каналу показує, що підключено, але відповіді не працюють - - Потрібні перевірки, специфічні для каналу, перед переходом до детальної документації провайдера -summary: Швидке усунення несправностей на рівні каналу з характерними ознаками збоїв і виправленнями для кожного каналу -title: Усунення несправностей каналу + - Транспорт каналу показує, що підключено, але відповіді не надсилаються + - Потрібні перевірки для конкретного каналу, перш ніж заглиблюватися в документацію провайдера +summary: Швидке усунення несправностей на рівні каналів із характерними ознаками збоїв і виправленнями для кожного каналу +title: Усунення несправностей каналів x-i18n: - generated_at: "2026-04-21T00:17:12Z" + generated_at: "2026-04-21T21:27:21Z" model: gpt-5.4 provider: openai - source_hash: 69e9e8f093bee1c7aafc244d6b999a957b7571cc125096d72060d0df52bf52c0 + source_hash: 8c57934b52086ea5f41565c5aae77ef6fa772cf7d56a6427655a844a5c63d1c6 source_path: channels/troubleshooting.md workflow: 15 --- -# Усунення несправностей каналу +# Усунення несправностей каналів Використовуйте цю сторінку, коли канал підключається, але працює неправильно. ## Послідовність команд -Спочатку виконайте їх у такому порядку: +Спочатку запускайте їх у такому порядку: ```bash openclaw status @@ -34,7 +34,7 @@ openclaw channels status --probe - `Runtime: running` - `Connectivity probe: ok` - `Capability: read-only`, `write-capable` або `admin-capable` -- Перевірка каналу показує, що транспорт підключено і, де підтримується, `works` або `audit ok` +- Перевірка каналу показує, що транспорт підключено і, де це підтримується, `works` або `audit ok` ## WhatsApp @@ -43,100 +43,100 @@ openclaw channels status --probe | Симптом | Найшвидша перевірка | Виправлення | | ------------------------------- | ------------------------------------------------ | ------------------------------------------------------------ | | Підключено, але немає відповідей у DM | `openclaw pairing list whatsapp` | Підтвердьте відправника або змініть політику DM/список дозволених. | -| Повідомлення групи ігноруються | Перевірте `requireMention` і шаблони згадок у конфігурації | Згадайте бота або пом’якшіть політику згадок для цієї групи. | +| Повідомлення в групі ігноруються | Перевірте `requireMention` і шаблони згадування в конфігурації | Згадайте бота або пом’якште політику згадування для цієї групи. | | Випадкові відключення/цикли повторного входу | `openclaw channels status --probe` + журнали | Увійдіть знову та переконайтеся, що каталог облікових даних справний. | -Повне усунення несправностей: [/channels/whatsapp#troubleshooting](/uk/channels/whatsapp#troubleshooting) +Повне усунення несправностей: [Усунення несправностей WhatsApp](/uk/channels/whatsapp#troubleshooting) ## Telegram ### Характерні ознаки збоїв Telegram -| Симптом | Найшвидша перевірка | Виправлення | -| ----------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | -| Є `/start`, але немає придатного потоку відповідей | `openclaw pairing list telegram` | Підтвердьте сполучення або змініть політику DM. | -| Бот онлайн, але група мовчить | Перевірте вимогу згадки та режим приватності бота | Вимкніть режим приватності для видимості в групі або згадайте бота. | -| Помилки надсилання з мережевими помилками | Перегляньте журнали на наявність збоїв викликів Telegram API | Виправте маршрутизацію DNS/IPv6/проксі до `api.telegram.org`. | -| Опитування зависає або повільно перепідключається | `openclaw logs --follow` для діагностики опитування | Оновіться; якщо перезапуски є хибнопозитивними, налаштуйте `pollingStallThresholdMs`. Постійні зависання все ще вказують на проксі/DNS/IPv6. | -| `setMyCommands` відхиляється під час запуску | Перегляньте журнали на `BOT_COMMANDS_TOO_MUCH` | Зменште кількість команд Telegram для Plugin/Skills/користувацьких команд або вимкніть нативні меню. | -| Після оновлення список дозволених вас блокує | `openclaw security audit` і списки дозволених у конфігурації | Виконайте `openclaw doctor --fix` або замініть `@username` на числові ID відправників. | +| Симптом | Найшвидша перевірка | Виправлення | +| ----------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| `/start`, але немає придатного потоку відповідей | `openclaw pairing list telegram` | Підтвердьте pairing або змініть політику DM. | +| Бот онлайн, але група мовчить | Перевірте вимогу згадування та режим приватності бота | Вимкніть режим приватності для видимості в групі або згадайте бота. | +| Надсилання завершується помилками мережі | Перегляньте журнали на наявність збоїв викликів Telegram API | Виправте маршрутизацію DNS/IPv6/proxy до `api.telegram.org`. | +| Polling зависає або повільно перепідключається | `openclaw logs --follow` для діагностики polling | Оновіться; якщо перезапуски є хибнопозитивними, налаштуйте `pollingStallThresholdMs`. Постійні зависання все ще вказують на proxy/DNS/IPv6. | +| `setMyCommands` відхиляється під час запуску | Перегляньте журнали на `BOT_COMMANDS_TOO_MUCH` | Зменште кількість команд Telegram від plugin/skill/custom або вимкніть нативні меню. | +| Після оновлення список дозволених вас блокує | `openclaw security audit` і списки дозволених у конфігурації | Запустіть `openclaw doctor --fix` або замініть `@username` на числові ID відправників. | -Повне усунення несправностей: [/channels/telegram#troubleshooting](/uk/channels/telegram#troubleshooting) +Повне усунення несправностей: [Усунення несправностей Telegram](/uk/channels/telegram#troubleshooting) ## Discord ### Характерні ознаки збоїв Discord -| Симптом | Найшвидша перевірка | Виправлення | -| ------------------------------- | -------------------------------- | ------------------------------------------------------------- | -| Бот онлайн, але немає відповідей у guild | `openclaw channels status --probe` | Дозвольте guild/channel і перевірте intent вмісту повідомлень. | -| Повідомлення групи ігноруються | Перевірте журнали на відкидання через вимогу згадки | Згадайте бота або встановіть `requireMention: false` для guild/channel. | -| Відсутні відповіді в DM | `openclaw pairing list discord` | Підтвердьте сполучення DM або скоригуйте політику DM. | +| Симптом | Найшвидша перевірка | Виправлення | +| ------------------------------- | ------------------------------------ | ------------------------------------------------------------ | +| Бот онлайн, але немає відповідей у guild | `openclaw channels status --probe` | Дозвольте guild/channel і перевірте intent для вмісту повідомлень. | +| Повідомлення в групі ігноруються | Перевірте журнали на drops через вимогу згадування | Згадайте бота або встановіть `requireMention: false` для guild/channel. | +| Немає відповідей у DM | `openclaw pairing list discord` | Підтвердьте DM pairing або скоригуйте політику DM. | -Повне усунення несправностей: [/channels/discord#troubleshooting](/uk/channels/discord#troubleshooting) +Повне усунення несправностей: [Усунення несправностей Discord](/uk/channels/discord#troubleshooting) ## Slack ### Характерні ознаки збоїв Slack -| Симптом | Найшвидша перевірка | Виправлення | -| -------------------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| Socket mode підключено, але немає відповідей | `openclaw channels status --probe` | Перевірте токен застосунку, токен бота та потрібні області доступу; звертайте увагу на `botTokenStatus` / `appTokenStatus = configured_unavailable` у конфігураціях на основі SecretRef. | -| DM заблоковані | `openclaw pairing list slack` | Підтвердьте сполучення або пом’якшіть політику DM. | -| Повідомлення каналу ігноруються | Перевірте `groupPolicy` і список дозволених каналів | Дозвольте канал або змініть політику на `open`. | +| Симптом | Найшвидша перевірка | Виправлення | +| -------------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Socket mode підключено, але немає відповідей | `openclaw channels status --probe` | Перевірте app token + bot token і потрібні scopes; зверніть увагу на `botTokenStatus` / `appTokenStatus = configured_unavailable` у конфігураціях на базі SecretRef. | +| DM заблоковано | `openclaw pairing list slack` | Підтвердьте pairing або пом’якште політику DM. | +| Повідомлення каналу ігнорується | Перевірте `groupPolicy` і список дозволених каналів | Дозвольте канал або змініть політику на `open`. | -Повне усунення несправностей: [/channels/slack#troubleshooting](/uk/channels/slack#troubleshooting) +Повне усунення несправностей: [Усунення несправностей Slack](/uk/channels/slack#troubleshooting) -## iMessage and BlueBubbles +## iMessage і BlueBubbles -### Характерні ознаки збоїв iMessage and BlueBubbles +### Характерні ознаки збоїв iMessage і BlueBubbles | Симптом | Найшвидша перевірка | Виправлення | | -------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------ | -| Немає вхідних подій | Перевірте доступність Webhook/сервера та дозволи застосунку | Виправте URL Webhook або стан сервера BlueBubbles. | -| Можна надсилати, але немає прийому на macOS | Перевірте дозволи приватності macOS для автоматизації Messages | Повторно надайте дозволи TCC і перезапустіть процес каналу. | -| Відправника DM заблоковано | `openclaw pairing list imessage` або `openclaw pairing list bluebubbles` | Підтвердьте сполучення або оновіть список дозволених. | +| Немає вхідних подій | Перевірте досяжність Webhook/сервера та дозволи застосунку | Виправте URL Webhook або стан сервера BlueBubbles. | +| Можна надсилати, але немає прийому на macOS | Перевірте дозволи конфіденційності macOS для автоматизації Messages | Повторно надайте дозволи TCC і перезапустіть процес каналу. | +| Відправника DM заблоковано | `openclaw pairing list imessage` або `openclaw pairing list bluebubbles` | Підтвердьте pairing або оновіть список дозволених. | Повне усунення несправностей: -- [/channels/imessage#troubleshooting](/uk/channels/imessage#troubleshooting) -- [/channels/bluebubbles#troubleshooting](/uk/channels/bluebubbles#troubleshooting) +- [Усунення несправностей iMessage](/uk/channels/imessage#troubleshooting) +- [Усунення несправностей BlueBubbles](/uk/channels/bluebubbles#troubleshooting) ## Signal ### Характерні ознаки збоїв Signal -| Симптом | Найшвидша перевірка | Виправлення | -| ------------------------------- | ----------------------------------- | ------------------------------------------------------------- | -| Демон доступний, але бот мовчить | `openclaw channels status --probe` | Перевірте URL/обліковий запис демона `signal-cli` і режим receive. | -| DM заблоковано | `openclaw pairing list signal` | Підтвердьте відправника або скоригуйте політику DM. | -| Не спрацьовують відповіді в групі | Перевірте список дозволених груп і шаблони згадок | Додайте відправника/групу або послабте обмеження. | +| Симптом | Найшвидша перевірка | Виправлення | +| ------------------------------- | --------------------------------------- | ------------------------------------------------------------- | +| Daemon доступний, але бот мовчить | `openclaw channels status --probe` | Перевірте URL/account daemon `signal-cli` і режим receive. | +| DM заблоковано | `openclaw pairing list signal` | Підтвердьте відправника або скоригуйте політику DM. | +| Відповіді в групі не спрацьовують | Перевірте список дозволених груп і шаблони згадування | Додайте відправника/групу або послабте правила фільтрації. | -Повне усунення несправностей: [/channels/signal#troubleshooting](/uk/channels/signal#troubleshooting) +Повне усунення несправностей: [Усунення несправностей Signal](/uk/channels/signal#troubleshooting) ## QQ Bot ### Характерні ознаки збоїв QQ Bot -| Симптом | Найшвидша перевірка | Виправлення | -| ------------------------------- | ------------------------------------------ | ---------------------------------------------------------------- | -| Бот відповідає "gone to Mars" | Перевірте `appId` і `clientSecret` у конфігурації | Задайте облікові дані або перезапустіть Gateway. | -| Немає вхідних повідомлень | `openclaw channels status --probe` | Перевірте облікові дані на QQ Open Platform. | -| Голос не транскрибується | Перевірте конфігурацію провайдера STT | Налаштуйте `channels.qqbot.stt` або `tools.media.audio`. | -| Ініційовані ботом повідомлення не надходять | Перевірте вимоги QQ platform до взаємодій | QQ може блокувати ініційовані ботом повідомлення без недавньої взаємодії. | +| Симптом | Найшвидша перевірка | Виправлення | +| ------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------ | +| Бот відповідає "gone to Mars" | Перевірте `appId` і `clientSecret` у конфігурації | Установіть облікові дані або перезапустіть Gateway. | +| Немає вхідних повідомлень | `openclaw channels status --probe` | Перевірте облікові дані на QQ Open Platform. | +| Голос не транскрибується | Перевірте конфігурацію провайдера STT | Налаштуйте `channels.qqbot.stt` або `tools.media.audio`. | +| Проактивні повідомлення не надходять | Перевірте вимоги платформи QQ щодо взаємодії | QQ може блокувати повідомлення, ініційовані ботом, без недавньої взаємодії. | -Повне усунення несправностей: [/channels/qqbot#troubleshooting](/uk/channels/qqbot#troubleshooting) +Повне усунення несправностей: [Усунення несправностей QQ Bot](/uk/channels/qqbot#troubleshooting) ## Matrix ### Характерні ознаки збоїв Matrix -| Симптом | Найшвидша перевірка | Виправлення | -| ----------------------------------- | ----------------------------------- | -------------------------------------------------------------------------- | -| Вхід виконано, але повідомлення кімнати ігноруються | `openclaw channels status --probe` | Перевірте `groupPolicy`, список дозволених кімнат і обмеження на згадки. | -| DM не обробляються | `openclaw pairing list matrix` | Підтвердьте відправника або скоригуйте політику DM. | -| Зашифровані кімнати не працюють | `openclaw matrix verify status` | Повторно верифікуйте пристрій, а потім перевірте `openclaw matrix verify backup status`. | -| Відновлення резервної копії очікує/пошкоджене | `openclaw matrix verify backup status` | Виконайте `openclaw matrix verify backup restore` або повторіть із ключем відновлення. | -| Кроспідписування/bootstrap виглядає неправильно | `openclaw matrix verify bootstrap` | За один прохід виправте secret storage, кроспідписування та стан резервних копій. | +| Симптом | Найшвидша перевірка | Виправлення | +| ----------------------------------- | --------------------------------------- | ------------------------------------------------------------------------- | +| Вхід виконано, але повідомлення кімнат ігноруються | `openclaw channels status --probe` | Перевірте `groupPolicy`, список дозволених кімнат і фільтрацію за згадуванням. | +| DM не обробляються | `openclaw pairing list matrix` | Підтвердьте відправника або скоригуйте політику DM. | +| Зашифровані кімнати не працюють | `openclaw matrix verify status` | Повторно підтвердьте пристрій, потім перевірте `openclaw matrix verify backup status`. | +| Відновлення резервної копії очікується/зламане | `openclaw matrix verify backup status` | Запустіть `openclaw matrix verify backup restore` або повторіть із recovery key. | +| Cross-signing/bootstrap виглядає неправильно | `openclaw matrix verify bootstrap` | Виправте secret storage, cross-signing і стан резервної копії за один прохід. | -Повне налаштування та конфігурація: [Matrix](/uk/channels/matrix) +Повне налаштування і конфігурація: [Matrix](/uk/channels/matrix) diff --git a/docs/uk/ci.md b/docs/uk/ci.md index e2a5a2aa8..bd3f24eae 100644 --- a/docs/uk/ci.md +++ b/docs/uk/ci.md @@ -1,89 +1,89 @@ --- read_when: - - Вам потрібно зрозуміти, чому завдання CI було або не було запущено - - Ви налагоджуєте збої перевірок GitHub Actions -summary: Граф завдань CI, шлюзи області змін і локальні еквіваленти команд + - Вам потрібно зрозуміти, чому завдання CI було або не було запущене + - Ви налагоджуєте перевірки GitHub Actions, що завершилися з помилкою +summary: Граф завдань CI, обмеження за областю змін і локальні еквіваленти команд title: Конвеєр CI x-i18n: - generated_at: "2026-04-21T18:05:48Z" + generated_at: "2026-04-21T21:27:24Z" model: gpt-5.4 provider: openai - source_hash: 4d01a178402976cdf7c3c864695e8a12d3f7d1d069a77ea1b02a8aef2a3497f7 + source_hash: ae08bad6cbd0f2eced6c88a792a11bc1c2b1a2bfb003a56f70ff328a2739d3fc source_path: ci.md workflow: 15 --- # Конвеєр CI -CI запускається для кожного push у `main` і для кожного pull request. Він використовує розумне визначення області змін, щоб пропускати дорогі завдання, коли змінено лише нерелевантні частини. +CI запускається для кожного push у `main` і для кожного pull request. Він використовує розумне обмеження за областю змін, щоб пропускати дорогі завдання, коли змінено лише не пов’язані ділянки. ## Огляд завдань -| Завдання | Призначення | Коли запускається | -| -------------------------------- | -------------------------------------------------------------------------------------------- | ----------------------------------- | -| `preflight` | Виявляє зміни лише в документації, області змін, змінені розширення та будує маніфест CI | Завжди для push і PR не в чернетці | -| `security-scm-fast` | Виявлення приватних ключів і аудит workflow через `zizmor` | Завжди для push і PR не в чернетці | -| `security-dependency-audit` | Аудит production lockfile без залежностей на основі advisories npm | Завжди для push і PR не в чернетці | -| `security-fast` | Обов’язковий агрегат для швидких завдань безпеки | Завжди для push і PR не в чернетці | -| `build-artifacts` | Один раз збирає `dist/` і Control UI, завантажує повторно використовувані артефакти для downstream-завдань | Зміни, релевантні для Node | -| `checks-fast-core` | Швидкі Linux-етапи перевірки коректності, як-от bundled/plugin-contract/protocol checks | Зміни, релевантні для Node | -| `checks-fast-contracts-channels` | Розшардовані перевірки контрактів каналів зі стабільним агрегованим результатом | Зміни, релевантні для Node | -| `checks-node-extensions` | Повні шарди тестів bundled-plugin для всього набору розширень | Зміни, релевантні для Node | -| `checks-node-core-test` | Шарди тестів core Node, за винятком каналів, bundled, контрактних і extension-етапів | Зміни, релевантні для Node | -| `extension-fast` | Цільові тести лише для змінених bundled plugins | Коли виявлено зміни в розширеннях | -| `check` | Розшардований еквівалент основного локального шлюзу: production types, lint, guards, test types і strict smoke | Зміни, релевантні для Node | -| `check-additional` | Шарди архітектурних, boundary, extension-surface guards, package-boundary і gateway-watch перевірок | Зміни, релевантні для Node | -| `build-smoke` | Smoke-тести зібраного CLI і smoke-перевірка пам’яті під час запуску | Зміни, релевантні для Node | -| `checks` | Решта Linux Node-етапів: тести каналів і сумісність Node 22 лише для push | Зміни, релевантні для Node | -| `check-docs` | Форматування документації, lint і перевірка на биті посилання | Документацію змінено | +| Завдання | Призначення | Коли запускається | +| -------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- | +| `preflight` | Виявляє зміни лише в документації, змінені області, змінені extensions і збирає маніфест CI | Завжди для push і PR, що не є draft | +| `security-scm-fast` | Виявлення приватних ключів і аудит workflow через `zizmor` | Завжди для push і PR, що не є draft | +| `security-dependency-audit` | Аудит production lockfile без залежностей щодо попереджень npm | Завжди для push і PR, що не є draft | +| `security-fast` | Обов’язковий агрегат для швидких завдань безпеки | Завжди для push і PR, що не є draft | +| `build-artifacts` | Один раз збирає `dist/` і Control UI, вивантажує повторно використовувані артефакти для наступних завдань | Зміни, релевантні для Node | +| `checks-fast-core` | Швидкі Linux-етапи перевірки коректності, як-от bundled/plugin-contract/protocol перевірки | Зміни, релевантні для Node | +| `checks-fast-contracts-channels` | Шардовані перевірки контрактів каналів зі стабільним агрегованим результатом перевірки | Зміни, релевантні для Node | +| `checks-node-extensions` | Повні шарди тестів bundled-plugin для всього набору extension | Зміни, релевантні для Node | +| `checks-node-core-test` | Шарди основних Node-тестів, без каналів, bundled, contract і extension-етапів | Зміни, релевантні для Node | +| `extension-fast` | Цільові тести лише для змінених bundled plugins | Коли виявлено зміни в extension | +| `check` | Шардований еквівалент основного локального gate: production types, lint, guards, test types і strict smoke | Зміни, релевантні для Node | +| `check-additional` | Шарди архітектури, меж, guards поверхні extension, package-boundary і gateway-watch | Зміни, релевантні для Node | +| `build-smoke` | Smoke-тести зібраного CLI і smoke-тест пам’яті під час запуску | Зміни, релевантні для Node | +| `checks` | Решта Linux Node-етапів: тести каналів і сумісність лише для push із Node 22 | Зміни, релевантні для Node | +| `check-docs` | Форматування документації, lint і перевірки битих посилань | Документацію змінено | | `skills-python` | Ruff + pytest для Skills на базі Python | Зміни, релевантні для Python Skills | -| `checks-windows` | Windows-специфічні тестові етапи | Зміни, релевантні для Windows | -| `macos-node` | Етап тестів TypeScript на macOS із використанням спільних зібраних артефактів | Зміни, релевантні для macOS | -| `macos-swift` | Swift lint, build і тести для застосунку macOS | Зміни, релевантні для macOS | -| `android` | Матриця збірки та тестів Android | Зміни, релевантні для Android | +| `checks-windows` | Специфічні для Windows етапи тестування | Зміни, релевантні для Windows | +| `macos-node` | Етап TypeScript-тестів на macOS із використанням спільних зібраних артефактів | Зміни, релевантні для macOS | +| `macos-swift` | Swift lint, збірка і тести для застосунку macOS | Зміни, релевантні для macOS | +| `android` | Матриця збірки і тестів Android | Зміни, релевантні для Android | -## Порядок Fail-Fast +## Порядок швидкого завершення з помилкою -Завдання впорядковано так, щоб дешеві перевірки завершувалися з помилкою раніше, ніж запускаються дорогі: +Завдання впорядковано так, щоб дешеві перевірки завершувалися з помилкою раніше, ніж запустяться дорогі: 1. `preflight` вирішує, які етапи взагалі існують. Логіка `docs-scope` і `changed-scope` — це кроки всередині цього завдання, а не окремі завдання. -2. `security-scm-fast`, `security-dependency-audit`, `security-fast`, `check`, `check-additional`, `check-docs` і `skills-python` завершуються швидко, не чекаючи важчих матричних завдань артефактів і платформ. -3. `build-artifacts` виконується паралельно зі швидкими Linux-етапами, щоб downstream-споживачі могли почати роботу, щойно спільна збірка буде готова. -4. Після цього розгалужуються важчі платформні та runtime-етапи: `checks-fast-core`, `checks-fast-contracts-channels`, `checks-node-extensions`, `checks-node-core-test`, `extension-fast`, `checks`, `checks-windows`, `macos-node`, `macos-swift` і `android`. +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`, `extension-fast`, `checks`, `checks-windows`, `macos-node`, `macos-swift` і `android`. -Логіка області змін розміщена в `scripts/ci-changed-scope.mjs` і покрита unit-тестами в `src/scripts/ci-changed-scope.test.ts`. -Окремий workflow `install-smoke` повторно використовує той самий скрипт області змін через власне завдання `preflight`. Він обчислює `run_install_smoke` із вужчого сигналу changed-smoke, тому Docker/install smoke запускається лише для змін, релевантних до встановлення, пакування та контейнерів. +Логіка областей змін міститься в `scripts/ci-changed-scope.mjs` і покрита unit-тестами в `src/scripts/ci-changed-scope.test.ts`. +Окремий workflow `install-smoke` повторно використовує той самий скрипт обмеження області через власне завдання `preflight`. Він обчислює `run_install_smoke` із вужчого сигналу changed-smoke, тому Docker/install smoke запускається лише для змін, релевантних до install, packaging і container. -Логіка локальних changed-lanes розміщена в `scripts/changed-lanes.mjs` і виконується через `scripts/check-changed.mjs`. Цей локальний шлюз суворіший щодо архітектурних меж, ніж широка область платформ у CI: зміни core production запускають typecheck core prod плюс тести core, зміни лише в core tests запускають лише typecheck/tests для core tests, зміни extension production запускають typecheck extension prod плюс тести розширень, а зміни лише в extension tests запускають лише typecheck/tests для extension tests. Зміни в public Plugin SDK або plugin-contract розширюють перевірку до validation розширень, тому що розширення залежать від цих core-контрактів. Невідомі зміни в корені/config безпечно переводять виконання на всі етапи. +Локальна логіка changed-lane міститься в `scripts/changed-lanes.mjs` і виконується через `scripts/check-changed.mjs`. Цей локальний gate суворіший щодо архітектурних меж, ніж широке платформене обмеження області в CI: зміни core production запускають core prod typecheck плюс core tests, зміни лише core tests запускають лише core test typecheck/tests, зміни extension production запускають extension prod typecheck плюс extension tests, а зміни лише extension tests запускають лише extension test typecheck/tests. Зміни в публічному Plugin SDK або plugin-contract розширюють перевірку на extension, оскільки extensions залежать від цих контрактів core. Підвищення версії лише в release metadata запускають цільові перевірки version/config/root-dependency. Невідомі зміни в root/config безпечно розширюються до всіх етапів. -Для push матриця `checks` додає етап `compat-node22`, який запускається лише для push. Для pull request цей етап пропускається, і матриця залишається зосередженою на звичайних test/channel-етапах. +Для push матриця `checks` додає етап `compat-node22`, який запускається лише для push. Для pull request цей етап пропускається, і матриця зосереджується на звичайних test/channel-етапах. -Найповільніші сімейства тестів Node розбиті на include-file шарди, щоб кожне завдання залишалося невеликим: channel contracts розділяють покриття registry і core на вісім зважених шардів кожне, тести auto-reply reply command поділено на чотири шарди за include-pattern, а інші великі групи auto-reply reply prefix — на два шарди кожна. `check-additional` також відокремлює compile/canary-роботи package-boundary від runtime topology gateway/architecture-робіт. +Найповільніші сімейства Node-тестів розбиті на include-file шарди, щоб кожне завдання залишалося невеликим: контракти каналів розділяють registry і core coverage на вісім зважених шардів кожен, тести команд відповіді auto-reply розділяються на чотири шарди за include-pattern, а інші великі групи префіксів відповідей auto-reply — на два шарди кожна. `check-additional` також відокремлює compile/canary-роботи package-boundary від gateway/architecture-робіт топології runtime. -GitHub може позначати замінені новішими завдання як `cancelled`, коли новіший push потрапляє в той самий PR або ref `main`. Сприймайте це як шум CI, якщо лише найновіший запуск для того самого ref також не завершується з помилкою. Агреговані shard-перевірки явно вказують на цей випадок скасування, щоб його було легше відрізнити від помилки тесту. +GitHub може позначати замінені новішими завдання як `cancelled`, коли новіший push надходить у той самий PR або ref `main`. Сприймайте це як шум CI, якщо тільки найновіший запуск для того самого ref також не завершується з помилкою. Агреговані шардові перевірки явно вказують на цей випадок скасування, щоб його було легше відрізнити від збою тесту. ## Runners | Runner | Завдання | | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| `blacksmith-16vcpu-ubuntu-2404` | `preflight`, `security-scm-fast`, `security-dependency-audit`, `security-fast`, `build-artifacts`, Linux checks, docs checks, Python Skills, `android` | +| `blacksmith-16vcpu-ubuntu-2404` | `preflight`, `security-scm-fast`, `security-dependency-audit`, `security-fast`, `build-artifacts`, Linux-перевірки, перевірки документації, Python Skills, `android` | | `blacksmith-32vcpu-windows-2025` | `checks-windows` | -| `blacksmith-12vcpu-macos-latest` | `macos-node`, `macos-swift` у `openclaw/openclaw`; для forks використовується fallback на `macos-latest` | +| `blacksmith-12vcpu-macos-latest` | `macos-node`, `macos-swift` у `openclaw/openclaw`; для fork використовується запасний варіант `macos-latest` | ## Локальні еквіваленти ```bash -pnpm changed:lanes # переглянути локальний класифікатор changed-lanes для origin/main...HEAD -pnpm check:changed # розумний локальний шлюз: змінені typecheck/lint/tests за boundary-етапом -pnpm check # швидкий локальний шлюз: production tsgo + розшардований lint + паралельні швидкі guards +pnpm changed:lanes # переглянути локальний класифікатор changed-lane для origin/main...HEAD +pnpm check:changed # розумний локальний gate: changed typecheck/lint/tests за граничним етапом +pnpm check # швидкий локальний gate: production tsgo + шардований lint + паралельні швидкі guards pnpm check:test-types -pnpm check:timed # той самий шлюз із вимірюванням часу для кожного етапу +pnpm check:timed # той самий gate з таймінгами для кожного етапу pnpm build:strict-smoke pnpm check:architecture pnpm test:gateway:watch-regression pnpm test # тести vitest pnpm test:channels pnpm test:contracts:channels -pnpm check:docs # форматування docs + lint + перевірка битих посилань -pnpm build # збірка dist, коли важливі етапи CI artifact/build-smoke +pnpm check:docs # форматування документації + lint + биті посилання +pnpm build # зібрати dist, коли важливі етапи CI artifact/build-smoke ``` diff --git a/docs/uk/help/testing.md b/docs/uk/help/testing.md index ffe083120..3251de4da 100644 --- a/docs/uk/help/testing.md +++ b/docs/uk/help/testing.md @@ -1,146 +1,148 @@ --- read_when: - Запуск тестів локально або в CI - - Додавання регресійних тестів для багів моделі/провайдера + - Додавання регресій для помилок моделі/провайдера - Налагодження поведінки Gateway + агента -summary: 'Набір тестування: набори unit/e2e/live, Docker-ранери та що охоплює кожен тест' +summary: 'Набір для тестування: модульні/e2e/live набори, Docker-раннери та що покриває кожен тест' title: Тестування x-i18n: - generated_at: "2026-04-21T20:52:30Z" + generated_at: "2026-04-21T21:27:25Z" model: gpt-5.4 provider: openai - source_hash: 6f890d6aa69925e09c5847b7fa082f3076b3bc79aae3e72445c750633a2451fa + source_hash: 9e69c0080dc8fd07e91e89171b5b67c27f4768e99db0fcdaf98eb9830c57d80e source_path: help/testing.md workflow: 15 --- # Тестування -OpenClaw має три набори Vitest (unit/integration, e2e, live) і невеликий набір Docker-ранерів. +OpenClaw має три набори Vitest (unit/integration, e2e, live) і невеликий набір Docker-раннерів. Цей документ — посібник «як ми тестуємо»: -- Що охоплює кожен набір (і що він навмисно _не_ охоплює) -- Які команди запускати для типових сценаріїв роботи (локально, перед push, налагодження) +- Що покриває кожен набір (і що він навмисно _не_ покриває) +- Які команди запускати для типових робочих процесів (локально, перед push, налагодження) - Як live-тести знаходять облікові дані та вибирають моделі/провайдерів -- Як додавати регресійні тести для реальних проблем моделей/провайдерів +- Як додавати регресії для реальних проблем моделі/провайдера ## Швидкий старт У більшості випадків: -- Повний контрольний прогін (очікується перед push): `pnpm build && pnpm check && pnpm check:test-types && pnpm test` +- Повний gate (очікується перед push): `pnpm build && pnpm check && pnpm check:test-types && pnpm test` - Швидший локальний запуск повного набору на потужній машині: `pnpm test:max` - Прямий цикл спостереження Vitest: `pnpm test:watch` - Пряме націлювання на файл тепер також маршрутизує шляхи extension/channel: `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` -- Під час ітерації над однією помилкою спочатку віддавайте перевагу точковим запускам. +- Коли ітеруєте над однією помилкою, спочатку віддавайте перевагу цільовим запускам. - QA-сайт на базі Docker: `pnpm qa:lab:up` -- QA-набір у Linux VM: `pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline` +- QA lane на базі Linux VM: `pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline` -Коли ви змінюєте тести або хочете більше впевненості: +Коли ви змінюєте тести або хочете додаткової впевненості: -- Контрольний прогін покриття: `pnpm test: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` -- Перевірка вартості Moonshot/Kimi: якщо встановлено `MOONSHOT_API_KEY`, виконайте - `openclaw models list --provider moonshot --json`, потім виконайте ізольований +- Набір live (моделі + probe tool/image для Gateway): `pnpm test:live` +- Тихо націлитися на один live-файл: `pnpm test:live -- src/agents/models.profiles.live.test.ts` +- Smoke-тест вартості Moonshot/Kimi: коли встановлено `MOONSHOT_API_KEY`, запустіть + `openclaw models list --provider moonshot --json`, потім запустіть ізольований `openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json` - для `moonshot/kimi-k2.6`. Переконайтеся, що JSON показує Moonshot/K2.6, а - транскрипт асистента зберігає нормалізований `usage.cost`. + проти `moonshot/kimi-k2.6`. Переконайтеся, що JSON повідомляє про Moonshot/K2.6, а + транскрипт помічника зберігає нормалізований `usage.cost`. -Порада: коли вам потрібен лише один проблемний випадок, звужуйте live-тести через змінні середовища allowlist, описані нижче. +Порада: коли вам потрібен лише один випадок, що падає, віддавайте перевагу звуженню live-тестів через змінні середовища allowlist, описані нижче. -## QA-ранери для окремих сценаріїв +## Раннери, специфічні для QA -Ці команди доповнюють основні набори тестів, коли вам потрібен реалістичний QA-lab: +Ці команди розташовані поруч з основними тестовими наборами, коли вам потрібен реалізм qa-lab: - `pnpm openclaw qa suite` - - Запускає QA-сценарії з репозиторію безпосередньо на хості. - - За замовчуванням запускає кілька вибраних сценаріїв паралельно з ізольованими Gateway-воркерами. Для `qa-channel` типовий рівень паралельності — 4 (обмежений кількістю вибраних сценаріїв). Використовуйте `--concurrency `, щоб налаштувати кількість воркерів, або `--concurrency 1` для старого послідовного режиму. - - Завершується з ненульовим кодом, якщо будь-який сценарій падає. Використовуйте `--allow-failures`, якщо вам потрібні артефакти без аварійного коду завершення. - - Підтримує режими провайдерів `live-frontier`, `mock-openai` і `aimock`. - `aimock` запускає локальний сервер провайдера на базі AIMock для експериментального покриття фікстур і моків протоколу без заміни сценарно-орієнтованого режиму `mock-openai`. + - Запускає QA-сценарії на базі репозиторію безпосередньо на хості. + - За замовчуванням запускає кілька вибраних сценаріїв паралельно з ізольованими worker Gateway. Для `qa-channel` за замовчуванням використовується concurrency 4 (обмежується кількістю вибраних сценаріїв). Використовуйте `--concurrency `, щоб налаштувати кількість worker, або `--concurrency 1` для старішого послідовного lane. + - Завершується з ненульовим кодом, якщо будь-який сценарій завершується помилкою. Використовуйте `--allow-failures`, коли вам потрібні артефакти без коду завершення з помилкою. + - Підтримує режими провайдера `live-frontier`, `mock-openai` і `aimock`. + `aimock` запускає локальний сервер провайдера на базі AIMock для експериментального + покриття fixture і protocol-mock без заміни lane `mock-openai`, що враховує сценарії. - `pnpm openclaw qa suite --runner multipass` - - Запускає той самий QA-набір у тимчасовій Linux VM через Multipass. - - Використовує ту саму поведінку вибору сценаріїв, що й `qa suite` на хості. + - Запускає той самий QA-набір усередині тимчасової Multipass Linux VM. + - Зберігає ту саму поведінку вибору сценаріїв, що й `qa suite` на хості. - Повторно використовує ті самі прапорці вибору провайдера/моделі, що й `qa suite`. - - У live-запусках передає підтримувані QA-входи автентифікації, які практично використовувати в гостьовій системі: - ключі провайдерів із env, шлях до конфігурації QA live provider та `CODEX_HOME`, якщо він є. - - Каталоги виводу мають залишатися в межах кореня репозиторію, щоб гостьова система могла записувати назад через змонтовану робочу область. - - Записує стандартний QA-звіт і підсумок, а також логи Multipass у + - Live-запуски пересилають підтримувані QA-входи автентифікації, які практичні для guest: + ключі провайдера на основі env, шлях конфігурації QA live provider і `CODEX_HOME`, + якщо він присутній. + - Каталоги виводу мають залишатися в межах кореня репозиторію, щоб guest міг записувати назад через змонтований workspace. + - Записує звичайний QA-звіт і підсумок, а також логи Multipass у `.artifacts/qa-e2e/...`. - `pnpm qa:lab:up` - Запускає QA-сайт на базі Docker для QA-роботи в операторському стилі. - `pnpm test:docker:bundled-channel-deps` - - Пакує та встановлює поточну збірку OpenClaw у Docker, запускає Gateway - зі сконфігурованим OpenAI, потім вмикає Telegram і Discord через редагування конфігурації. - - Перевіряє, що перший перезапуск Gateway встановлює runtime-залежності кожного вбудованого channel Plugin на вимогу, а другий перезапуск не перевстановлює залежності, які вже були активовані. + - Пакує й установлює поточну збірку OpenClaw у Docker, запускає Gateway + з налаштованим OpenAI, потім вмикає Telegram і Discord через редагування config. + - Перевіряє, що перезапуск Gateway уперше встановлює runtime-залежності кожного bundled channel plugin на вимогу, а другий перезапуск не перевстановлює залежності, які вже були активовані. - `pnpm openclaw qa aimock` - Запускає лише локальний сервер провайдера AIMock для прямого smoke-тестування протоколу. - `pnpm openclaw qa matrix` - - Запускає Matrix live QA lane проти тимчасового homeserver Tuwunel на базі Docker. - - Цей QA-хост наразі призначений лише для репозиторію/розробки. Пакетні інсталяції OpenClaw не постачають `qa-lab`, тому не надають `openclaw qa`. - - Чекаути репозиторію завантажують вбудований ранер напряму; окремий крок встановлення Plugin не потрібен. - - Створює трьох тимчасових користувачів Matrix (`driver`, `sut`, `observer`) і одну приватну кімнату, потім запускає дочірній QA Gateway із реальним Matrix Plugin як транспортом SUT. - - За замовчуванням використовує закріплений стабільний образ Tuwunel `ghcr.io/matrix-construct/tuwunel:v1.5.1`. Замініть через `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE`, якщо потрібно протестувати інший образ. - - Matrix не надає спільних прапорців джерела облікових даних, оскільки цей lane локально створює тимчасових користувачів. - - Записує Matrix QA-звіт, підсумок, артефакт observed-events і комбінований лог stdout/stderr у `.artifacts/qa-e2e/...`. + - Запускає lane live QA Matrix проти тимчасового homeserver Tuwunel на базі Docker. + - Цей QA host наразі призначений лише для repo/dev. Запаковані інсталяції OpenClaw не постачають `qa-lab`, тому не надають `openclaw qa`. + - Checkout-и репозиторію завантажують bundled runner безпосередньо; окремий крок встановлення plugin не потрібен. + - Підготовлює трьох тимчасових користувачів Matrix (`driver`, `sut`, `observer`) плюс одну приватну кімнату, а потім запускає дочірній QA gateway із реальним Matrix plugin як транспортом SUT. + - За замовчуванням використовує pinned stable-образ Tuwunel `ghcr.io/matrix-construct/tuwunel:v1.5.1`. Перевизначайте через `OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE`, коли потрібно протестувати інший образ. + - Matrix не надає спільних прапорців джерела облікових даних, оскільки lane локально створює тимчасових користувачів. + - Записує QA-звіт Matrix, підсумок, артефакт observed-events і комбінований лог виводу stdout/stderr у `.artifacts/qa-e2e/...`. - `pnpm openclaw qa telegram` - - Запускає Telegram live QA lane проти реальної приватної групи, використовуючи токени ботів driver і SUT з env. + - Запускає lane live QA Telegram проти реальної приватної групи, використовуючи токени ботів driver і SUT із env. - Потребує `OPENCLAW_QA_TELEGRAM_GROUP_ID`, `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` і `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`. Ідентифікатор групи має бути числовим Telegram chat id. - - Підтримує `--credential-source convex` для спільних пулінгових облікових даних. Типово використовуйте режим env, або встановіть `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`, щоб перейти на pooled leases. - - Завершується з ненульовим кодом, якщо будь-який сценарій падає. Використовуйте `--allow-failures`, якщо вам потрібні артефакти без аварійного коду завершення. + - Підтримує `--credential-source convex` для спільних pooled credentials. За замовчуванням використовуйте режим env або встановіть `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`, щоб увімкнути pooled lease. + - Завершується з ненульовим кодом, якщо будь-який сценарій завершується помилкою. Використовуйте `--allow-failures`, коли вам потрібні артефакти без коду завершення з помилкою. - Потребує двох різних ботів в одній приватній групі, причому бот SUT має мати Telegram username. - Для стабільного спостереження bot-to-bot увімкніть Bot-to-Bot Communication Mode у `@BotFather` для обох ботів і переконайтеся, що бот driver може спостерігати трафік ботів у групі. - - Записує Telegram QA-звіт, підсумок і артефакт observed-messages у `.artifacts/qa-e2e/...`. + - Записує QA-звіт Telegram, підсумок і артефакт observed-messages у `.artifacts/qa-e2e/...`. -Live transport lanes мають спільний стандартний контракт, щоб нові транспорти не розходилися в поведінці: +Live transport lane мають спільний стандартний контракт, щоб нові транспорти не дрейфували: -`qa-channel` залишається широким синтетичним QA-набором і не входить до матриці покриття live transport. +`qa-channel` залишається широким синтетичним QA-набором і не є частиною матриці покриття live transport. -| Lane | Canary | Блокування згадок | Блок allowlist | Відповідь верхнього рівня | Відновлення після перезапуску | Подальша відповідь у треді | Ізоляція тредів | Спостереження за реакціями | Команда help | -| -------- | ------ | ----------------- | -------------- | ------------------------- | ----------------------------- | -------------------------- | --------------- | -------------------------- | ------------ | -| Matrix | x | x | x | x | x | x | x | x | | -| Telegram | x | | | | | | | | x | +| Lane | Canary | Gating згадок | Блок allowlist | Відповідь верхнього рівня | Відновлення після перезапуску | Подальша відповідь у thread | Ізоляція thread | Спостереження реакцій | Команда help | +| -------- | ------ | -------------- | --------------- | ------------------------- | ----------------------------- | --------------------------- | --------------- | --------------------- | ------------ | +| Matrix | x | x | x | x | x | x | x | x | | +| Telegram | x | | | | | | | | x | -### Спільні Telegram-облікові дані через Convex (v1) +### Спільні облікові дані Telegram через Convex (v1) Коли для `openclaw qa telegram` увімкнено `--credential-source convex` (або `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`), -QA lab отримує ексклюзивну оренду з пулу на базі Convex, надсилає Heartbeat -для цієї оренди, поки lane працює, і звільняє оренду під час завершення. +QA lab отримує ексклюзивний lease із пулу на базі Convex, надсилає Heartbeat +цього lease, поки lane працює, і звільняє lease під час завершення роботи. -Каркас еталонного проєкту Convex: +Еталонний scaffold проєкту Convex: - `qa/convex-credential-broker/` Обов’язкові змінні середовища: -- `OPENCLAW_QA_CONVEX_SITE_URL` (наприклад, `https://your-deployment.convex.site`) +- `OPENCLAW_QA_CONVEX_SITE_URL` (наприклад `https://your-deployment.convex.site`) - Один секрет для вибраної ролі: - `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` для `maintainer` - `OPENCLAW_QA_CONVEX_SECRET_CI` для `ci` - Вибір ролі облікових даних: - CLI: `--credential-role maintainer|ci` - - Значення env за замовчуванням: `OPENCLAW_QA_CREDENTIAL_ROLE` (типово `ci` у CI, інакше `maintainer`) + - Значення env за замовчуванням: `OPENCLAW_QA_CREDENTIAL_ROLE` (у CI за замовчуванням `ci`, інакше `maintainer`) Необов’язкові змінні середовища: -- `OPENCLAW_QA_CREDENTIAL_LEASE_TTL_MS` (типово `1200000`) -- `OPENCLAW_QA_CREDENTIAL_HEARTBEAT_INTERVAL_MS` (типово `30000`) -- `OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS` (типово `90000`) -- `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS` (типово `15000`) -- `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX` (типово `/qa-credentials/v1`) +- `OPENCLAW_QA_CREDENTIAL_LEASE_TTL_MS` (за замовчуванням `1200000`) +- `OPENCLAW_QA_CREDENTIAL_HEARTBEAT_INTERVAL_MS` (за замовчуванням `30000`) +- `OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS` (за замовчуванням `90000`) +- `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS` (за замовчуванням `15000`) +- `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX` (за замовчуванням `/qa-credentials/v1`) - `OPENCLAW_QA_CREDENTIAL_OWNER_ID` (необов’язковий trace id) -- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` дозволяє loopback URL-адреси Convex `http://` лише для локальної розробки. +- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` дозволяє loopback `http://` URL Convex лише для локальної розробки. У звичайному режимі `OPENCLAW_QA_CONVEX_SITE_URL` має використовувати `https://`. -Адміністраторські команди maintainer (додавання/видалення/перелік пулу) вимагають саме -`OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`. +Адміністративні команди maintainer (додавання/видалення/перелік пулу) потребують +саме `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`. CLI-хелпери для maintainer: @@ -150,7 +152,7 @@ pnpm openclaw qa credentials list --kind telegram pnpm openclaw qa credentials remove --credential-id ``` -Використовуйте `--json` для машиночитаного виводу в скриптах і утилітах CI. +Використовуйте `--json` для машиночитаного виводу в скриптах та утилітах CI. Контракт endpoint за замовчуванням (`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): @@ -170,7 +172,7 @@ pnpm openclaw qa credentials remove --credential-id - `POST /admin/remove` (лише секрет maintainer) - Запит: `{ credentialId, actorId }` - Успіх: `{ status: "ok", changed, credential }` - - Захист активної оренди: `{ status: "error", code: "LEASE_ACTIVE", ... }` + - Захист активного lease: `{ status: "error", code: "LEASE_ACTIVE", ... }` - `POST /admin/list` (лише секрет maintainer) - Запит: `{ kind?, status?, includePayload?, limit? }` - Успіх: `{ status: "ok", credentials, count }` @@ -183,55 +185,55 @@ pnpm openclaw qa credentials remove --credential-id ### Додавання каналу до QA -Щоб додати канал до markdown-системи QA, потрібні рівно дві речі: +Додавання каналу до markdown QA system потребує рівно двох речей: -1. Транспортний адаптер для каналу. -2. Набір сценаріїв, який перевіряє контракт каналу. +1. Транспортного адаптера для каналу. +2. Пакета сценаріїв, який перевіряє контракт каналу. -Не додавайте новий кореневий QA-командний простір верхнього рівня, якщо спільний хост `qa-lab` -може керувати цим процесом. +Не додавайте новий корінь команди QA верхнього рівня, коли спільний host `qa-lab` +може володіти цим процесом. -`qa-lab` відповідає за спільну хостову механіку: +`qa-lab` володіє спільною механікою host: -- кореневу команду `openclaw qa` -- запуск і зупинку наборів -- паралельність воркерів -- запис артефактів -- генерацію звітів -- виконання сценаріїв +- коренем команди `openclaw qa` +- запуском і завершенням набору +- concurrency worker +- записом артефактів +- генерацією звітів +- виконанням сценаріїв - alias сумісності для старіших сценаріїв `qa-channel` -Runner Plugins відповідають за транспортний контракт: +Plugin раннера володіють транспортним контрактом: - як `openclaw qa ` монтується під спільним коренем `qa` -- як конфігурується Gateway для цього транспорту +- як Gateway налаштовується для цього транспорту - як перевіряється готовність - як інжектуються вхідні події - як спостерігаються вихідні повідомлення -- як надаються транскрипти та нормалізований стан транспорту -- як виконуються дії, що спираються на транспорт -- як обробляється специфічне для транспорту скидання або очищення +- як надаються транскрипти та нормалізований транспортний стан +- як виконуються дії на базі транспорту +- як обробляються скидання або очищення, специфічні для транспорту -Мінімальний поріг впровадження нового каналу: +Мінімальна планка впровадження для нового каналу така: 1. Залишайте `qa-lab` власником спільного кореня `qa`. -2. Реалізуйте transport runner на спільному хостовому seam `qa-lab`. -3. Залишайте транспортно-специфічну механіку всередині runner Plugin або channel harness. -4. Монтуйте ранер як `openclaw qa ` замість реєстрації конкуруючої кореневої команди. - Runner Plugins повинні оголошувати `qaRunners` у `openclaw.plugin.json` і експортувати відповідний масив `qaRunnerCliRegistrations` з `runtime-api.ts`. - Підтримуйте `runtime-api.ts` легким; ліниве виконання CLI і раннера має залишатися за окремими entrypoint. +2. Реалізуйте transport runner на спільному host seam `qa-lab`. +3. Залишайте механіку, специфічну для транспорту, усередині plugin раннера або channel harness. +4. Монтуйте раннер як `openclaw qa `, а не реєструйте конкуруючий кореневий command. + Plugin раннера мають оголошувати `qaRunners` у `openclaw.plugin.json` і експортувати відповідний масив `qaRunnerCliRegistrations` із `runtime-api.ts`. + Зберігайте `runtime-api.ts` легким; ліниве виконання CLI та раннера має залишатися за окремими entrypoint. 5. Створюйте або адаптуйте markdown-сценарії в тематичних каталогах `qa/scenarios/`. -6. Використовуйте узагальнені хелпери сценаріїв для нових сценаріїв. -7. Зберігайте наявні alias сумісності робочими, якщо в репозиторії не виконується навмисна міграція. +6. Для нових сценаріїв використовуйте загальні helper сценаріїв. +7. Зберігайте працездатність наявних alias сумісності, якщо лише репозиторій не виконує навмисну міграцію. -Правило прийняття рішення суворе: +Правило ухвалення рішення є суворим: - Якщо поведінку можна один раз виразити в `qa-lab`, розміщуйте її в `qa-lab`. -- Якщо поведінка залежить від одного channel transport, залишайте її в цьому runner Plugin або plugin harness. -- Якщо сценарію потрібна нова можливість, яку може використовувати більше ніж один канал, додайте узагальнений хелпер замість channel-specific гілки в `suite.ts`. -- Якщо поведінка має сенс лише для одного транспорту, залишайте сценарій transport-specific і явно зазначайте це в контракті сценарію. +- Якщо поведінка залежить від одного channel transport, зберігайте її в plugin раннера цього каналу або в harness plugin. +- Якщо сценарію потрібна нова можливість, яку може використовувати більше ніж один канал, додайте загальний helper замість channel-specific branch у `suite.ts`. +- Якщо певна поведінка має сенс лише для одного transport, залишайте сценарій transport-specific і явно вказуйте це в контракті сценарію. -Бажані назви узагальнених хелперів для нових сценаріїв: +Бажані назви загальних helper для нових сценаріїв: - `waitForTransportReady` - `waitForChannelReady` @@ -246,7 +248,7 @@ Runner Plugins відповідають за транспортний контр - `formatTransportTranscript` - `resetTransport` -Для наявних сценаріїв залишаються доступними alias сумісності, зокрема: +Alias сумісності залишаються доступними для наявних сценаріїв, зокрема: - `waitForQaChannelReady` - `waitForOutboundMessage` @@ -254,248 +256,248 @@ Runner Plugins відповідають за транспортний контр - `formatConversationTranscript` - `resetBus` -Нова робота над каналами має використовувати узагальнені назви хелперів. -Alias сумісності існують, щоб уникнути міграції одним днем, а не як зразок для -авторингу нових сценаріїв. +Нова робота з каналами має використовувати загальні назви helper. +Alias сумісності існують, щоб уникнути міграції в один день, а не як модель для +створення нових сценаріїв. -## Набори тестів (що і де запускається) +## Набори тестів (що де запускається) -Сприймайте набори як «зростання реалістичності» (і зростання нестабільності/вартості): +Думайте про набори як про «зростаючий реалізм» (і зростаючу нестабільність/вартість): -### Unit / integration (типово) +### Unit / integration (за замовчуванням) - Команда: `pnpm test` -- Конфігурація: десять послідовних shard-запусків (`vitest.full-*.config.ts`) поверх наявних scoped Vitest project -- Файли: інвентарі core/unit у `src/**/*.test.ts`, `packages/**/*.test.ts`, `test/**/*.test.ts` і whitelisted node-тести `ui`, охоплені `vitest.unit.config.ts` +- Config: десять послідовних запусків shard (`vitest.full-*.config.ts`) по наявних scoped Vitest project +- Файли: інвентарі core/unit у `src/**/*.test.ts`, `packages/**/*.test.ts`, `test/**/*.test.ts` і whitelist-тести node в `ui`, що покриваються `vitest.unit.config.ts` - Обсяг: - Чисті unit-тести - - In-process integration-тести (автентифікація gateway, маршрутизація, інструменти, парсинг, конфігурація) - - Детерміновані регресії для відомих багів + - In-process integration-тести (автентифікація gateway, маршрутизація, tooling, парсинг, config) + - Детерміновані регресії для відомих помилок - Очікування: - Запускається в CI - Реальні ключі не потрібні - Має бути швидким і стабільним -- Примітка про projects: - - `pnpm test` без цільового файлу тепер запускає одинадцять менших shard-конфігурацій (`core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-support-boundary`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`) замість одного гігантського процесу native root-project. Це зменшує піковий RSS на завантажених машинах і не дає роботі auto-reply/extension виснажувати нерелевантні набори. - - `pnpm test --watch` усе ще використовує граф project із native root `vitest.config.ts`, оскільки цикл watch із кількома shard непрактичний. - - `pnpm test`, `pnpm test:watch` і `pnpm test:perf:imports` спочатку маршрутизують явні цілі файлів/каталогів через scoped lanes, тому `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` уникає повної вартості запуску root project. - - `pnpm test:changed` розгортає змінені git-шляхи в ті самі scoped lanes, коли diff торкається лише routable source/test-файлів; редагування config/setup все ще повертаються до широкого повторного запуску root-project. - - `pnpm check:changed` — це звичайний розумний локальний контрольний прогін для вузької роботи. Він класифікує diff на core, core tests, extensions, extension tests, apps, docs і tooling, а потім запускає відповідні lanes typecheck/lint/test. Зміни в публічному Plugin SDK і plugin-contract включають перевірку extension, оскільки extensions залежать від цих core-контрактів. - - Import-light unit-тести з agents, commands, plugins, helper auto-reply, `plugin-sdk` та подібних чистих утилітних областей маршрутизуються через lane `unit-fast`, який пропускає `test/setup-openclaw-runtime.ts`; stateful/runtime-heavy файли залишаються на наявних lanes. - - Окремі helper source-файли `plugin-sdk` і `commands` також зіставляють запуски в changed-режимі з явними sibling-тестами в цих легких lanes, тому редагування helper уникають повторного запуску повного важкого набору для цього каталогу. - - `auto-reply` тепер має три окремі bucket: top-level core helper, top-level integration-тести `reply.*` і піддерево `src/auto-reply/reply/**`. Це прибирає найважчу роботу harness reply з дешевих тестів status/chunk/token. -- Примітка про embedded runner: - - Коли ви змінюєте входи виявлення message-tool або runtime-контекст compaction, +- Примітка щодо project: + - Ненацілений `pnpm test` тепер запускає одинадцять менших shard config (`core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-support-boundary`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`) замість одного гігантського native root-project process. Це зменшує піковий RSS на завантажених машинах і не дозволяє роботі auto-reply/extension витісняти не пов’язані набори. + - `pnpm test --watch` усе ще використовує native root-граф project `vitest.config.ts`, оскільки цикл watch із багатьма shard непрактичний. + - `pnpm test`, `pnpm test:watch` і `pnpm test:perf:imports` спочатку маршрутизують явні цілі файлів/каталогів через scoped lane, тому `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` не сплачує повну ціну запуску root project. + - `pnpm test:changed` розгортає змінені git-шляхи в ті самі scoped lane, коли diff торкається лише routable source/test-файлів; редагування config/setup все ще повертаються до широкого повторного запуску root-project. + - `pnpm check:changed` — це звичайний розумний локальний gate для вузької роботи. Він класифікує diff на core, тести core, extensions, тести extension, apps, docs, метадані релізу та tooling, а потім запускає відповідні lane typecheck/lint/test. Зміни public Plugin SDK і plugin-contract включають валідацію extension, оскільки extensions залежать від цих контрактів core. Зміни версій лише в метаданих релізу запускають цільові перевірки version/config/root-dependency замість повного набору, із guard, який відхиляє зміни package поза полем версії верхнього рівня. + - Unit-тести з легкими імпортами з agents, commands, plugins, helper auto-reply, `plugin-sdk` та подібних чистих утилітних областей маршрутизуються через lane `unit-fast`, який пропускає `test/setup-openclaw-runtime.ts`; stateful/runtime-heavy файли залишаються в наявних lane. + - Вибрані helper source-файли `plugin-sdk` і `commands` також зіставляють запуски в режимі changed з явними sibling-тестами в цих легких lane, тому редагування helper не призводять до повторного запуску повного важкого набору для цього каталогу. + - `auto-reply` тепер має три спеціальні bucket: helper верхнього рівня core, integration-тести верхнього рівня `reply.*` і піддерево `src/auto-reply/reply/**`. Це не дозволяє найважчій роботі harness reply потрапляти до дешевих тестів status/chunk/token. +- Примітка щодо embedded runner: + - Коли ви змінюєте входи виявлення message-tool або runtime-контекст Compaction, зберігайте обидва рівні покриття. - - Додавайте точкові helper-регресії для чистих меж routing/normalization. - - Також підтримуйте в доброму стані integration-набори embedded runner: + - Додавайте цільові helper-регресії для чистих меж routing/normalization. + - Також підтримуйте здоровими integration-набори embedded runner: `src/agents/pi-embedded-runner/compact.hooks.test.ts`, `src/agents/pi-embedded-runner/run.overflow-compaction.test.ts` і `src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts`. - - Ці набори перевіряють, що scoped id і поведінка compaction усе ще проходять - через реальні шляхи `run.ts` / `compact.ts`; лише helper-тести не є - достатньою заміною для цих integration-шляхів. -- Примітка про pool: - - Базова конфігурація Vitest тепер типово використовує `threads`. - - Спільна конфігурація Vitest також фіксує `isolate: false` і використовує non-isolated runner для root projects, e2e і live configs. - - Кореневий lane UI зберігає свій `jsdom` setup та optimizer, але тепер також працює на спільному non-isolated runner. - - Кожен shard `pnpm test` успадковує ті самі типові значення `threads` + `isolate: false` зі спільної конфігурації Vitest. - - Спільний launcher `scripts/run-vitest.mjs` тепер також типово додає `--no-maglev` для дочірніх Node-процесів Vitest, щоб зменшити churn компіляції V8 під час великих локальних запусків. Встановіть `OPENCLAW_VITEST_ENABLE_MAGLEV=1`, якщо потрібно порівняти зі стандартною поведінкою V8. -- Примітка про швидку локальну ітерацію: - - `pnpm changed:lanes` показує, які архітектурні lanes запускає diff. - - Pre-commit hook запускає `pnpm check:changed --staged` після staged formatting/linting, тому core-only commits не платять ціну extension-тестів, якщо не торкаються публічних контрактів для extensions. - - `pnpm test:changed` маршрутизує через scoped lanes, коли змінені шляхи чисто зіставляються з меншим набором. - - `pnpm test:max` і `pnpm test:changed:max` зберігають ту саму поведінку маршрутизації, лише з вищим лімітом воркерів. - - Автоматичне масштабування локальних воркерів тепер навмисно консервативне й також знижує навантаження, коли host load average вже високе, тому кілька одночасних запусків Vitest типово завдають менше шкоди. - - Базова конфігурація Vitest позначає files projects/config як `forceRerunTriggers`, щоб rerun у changed-режимі залишалися коректними, коли змінюється test wiring. - - Конфігурація зберігає `OPENCLAW_VITEST_FS_MODULE_CACHE` увімкненим на підтримуваних хостах; встановіть `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`, якщо хочете одну явну локацію кешу для прямого профілювання. -- Примітка про perf-debug: - - `pnpm test:perf:imports` вмикає звітність Vitest про тривалість import плюс вивід деталізації import. - - `pnpm test:perf:imports:changed` обмежує той самий вигляд профілювання файлами, зміненими від `origin/main`. -- `pnpm test:perf:changed:bench -- --ref ` порівнює маршрутизований `test:changed` із native шляхом root-project для цього committed diff і виводить wall time плюс macOS max RSS. -- `pnpm test:perf:changed:bench -- --worktree` виконує benchmark поточного брудного дерева, маршрутизуючи список змінених файлів через `scripts/test-projects.mjs` і root-конфігурацію Vitest. - - `pnpm test:perf:profile:main` записує main-thread CPU profile для накладних витрат запуску і transform у Vitest/Vite. - - `pnpm test:perf:profile:runner` записує профілі CPU+heap runner для unit-набору з вимкненим file parallelism. + - Ці набори перевіряють, що scoped id і поведінка Compaction усе ще проходять + через реальні шляхи `run.ts` / `compact.ts`; тести лише helper не є + достатньою заміною цим integration-шляхам. +- Примітка щодо pool: + - Базовий config Vitest тепер за замовчуванням використовує `threads`. + - Спільний config Vitest також фіксує `isolate: false` і використовує non-isolated runner у root project, e2e і live config. + - Root lane UI зберігає свої налаштування `jsdom` і optimizer, але тепер теж працює на спільному non-isolated runner. + - Кожен shard `pnpm test` успадковує ті самі значення за замовчуванням `threads` + `isolate: false` зі спільного config Vitest. + - Спільний launcher `scripts/run-vitest.mjs` тепер також за замовчуванням додає `--no-maglev` для дочірніх Node-process Vitest, щоб зменшити churn компіляції V8 під час великих локальних запусків. Установіть `OPENCLAW_VITEST_ENABLE_MAGLEV=1`, якщо потрібно порівняти зі стандартною поведінкою V8. +- Примітка щодо швидких локальних ітерацій: + - `pnpm changed:lanes` показує, які архітектурні lane запускає diff. + - Хук pre-commit запускає `pnpm check:changed --staged` після staged formatting/linting, тому commit-и лише core не оплачують вартість тестів extension, якщо не торкаються публічних контрактів для extension. Commit-и лише з метаданими релізу залишаються на цільовому lane version/config/root-dependency. + - `pnpm test:changed` маршрутизує через scoped lane, коли змінені шляхи чисто зіставляються з меншим набором. + - `pnpm test:max` і `pnpm test:changed:max` зберігають ту саму поведінку маршрутизації, лише з вищим лімітом worker. + - Автомасштабування локальних worker тепер навмисно консервативне та також зменшує навантаження, коли середнє навантаження хоста вже високе, тому кілька одночасних запусків Vitest за замовчуванням завдають менше шкоди. + - Базовий config Vitest позначає файли project/config як `forceRerunTriggers`, щоб повторні запуски в режимі changed залишалися коректними, коли змінюється wiring тестів. + - Config зберігає ввімкненим `OPENCLAW_VITEST_FS_MODULE_CACHE` на підтримуваних хостах; установіть `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`, якщо хочете одну явну локацію кешу для прямого профілювання. +- Примітка щодо налагодження продуктивності: + - `pnpm test:perf:imports` вмикає звітування Vitest про тривалість імпортів плюс вивід розбивки імпортів. + - `pnpm test:perf:imports:changed` обмежує той самий профілювальний вигляд файлами, зміненими від `origin/main`. +- `pnpm test:perf:changed:bench -- --ref ` порівнює маршрутизований `test:changed` із native root-project path для цього зафіксованого diff і виводить wall time плюс macOS max RSS. +- `pnpm test:perf:changed:bench -- --worktree` вимірює поточне dirty tree, маршрутизуючи список змінених файлів через `scripts/test-projects.mjs` і root Vitest config. + - `pnpm test:perf:profile:main` записує CPU-profile основного потоку для накладних витрат запуску та transform Vitest/Vite. + - `pnpm test:perf:profile:runner` записує CPU+heap profile раннера для unit-набору з вимкненим паралелізмом файлів. -### E2E (gateway smoke) +### E2E (smoke Gateway) - Команда: `pnpm test:e2e` -- Конфігурація: `vitest.e2e.config.ts` +- Config: `vitest.e2e.config.ts` - Файли: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts` -- Типові параметри runtime: +- Значення runtime за замовчуванням: - Використовує Vitest `threads` з `isolate: false`, як і решта репозиторію. - - Використовує адаптивну кількість воркерів (CI: до 2, локально: 1 за замовчуванням). - - Типово запускається в тихому режимі, щоб зменшити накладні витрати на console I/O. -- Корисні override: - - `OPENCLAW_E2E_WORKERS=`, щоб примусово задати кількість воркерів (максимум 16). + - Використовує адаптивних worker (CI: до 2, локально: 1 за замовчуванням). + - За замовчуванням працює в silent mode, щоб зменшити накладні витрати на console I/O. +- Корисні перевизначення: + - `OPENCLAW_E2E_WORKERS=`, щоб примусово задати кількість worker (обмежено 16). - `OPENCLAW_E2E_VERBOSE=1`, щоб знову ввімкнути докладний вивід у консоль. - Обсяг: - - End-to-end поведінка gateway із кількома екземплярами - - Поверхні WebSocket/HTTP, спарювання вузлів і складніша мережева взаємодія + - Наскрізна поведінка багатьох екземплярів Gateway + - Поверхні WebSocket/HTTP, pairing Node і важчий networking - Очікування: - Запускається в CI (коли ввімкнено в pipeline) - Реальні ключі не потрібні - - Більше рухомих частин, ніж у unit-тестах (може бути повільніше) + - Більше рухомих частин, ніж у unit-тестах (може бути повільнішим) -### E2E: smoke OpenShell backend +### E2E: smoke backend OpenShell - Команда: `pnpm test:e2e:openshell` - Файл: `test/openshell-sandbox.e2e.test.ts` - Обсяг: - Запускає ізольований Gateway OpenShell на хості через Docker - Створює sandbox із тимчасового локального Dockerfile - - Перевіряє backend OpenShell в OpenClaw через реальні `sandbox ssh-config` + SSH exec - - Перевіряє remote-canonical поведінку файлової системи через sandbox fs bridge + - Перевіряє backend OpenShell в OpenClaw через реальні `sandbox ssh-config` + виконання SSH + - Перевіряє remote-canonical поведінку файлової системи через міст fs sandbox - Очікування: - - Лише opt-in; не входить до типового запуску `pnpm test:e2e` + - Лише opt-in; не є частиною стандартного запуску `pnpm test:e2e` - Потребує локального CLI `openshell` і працездатного Docker daemon - - Використовує ізольовані `HOME` / `XDG_CONFIG_HOME`, потім знищує тестові gateway і sandbox -- Корисні override: - - `OPENCLAW_E2E_OPENSHELL=1`, щоб увімкнути тест під час ручного запуску ширшого e2e-набору - - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell`, щоб вказати нестандартний CLI-бінарник або wrapper script + - Використовує ізольовані `HOME` / `XDG_CONFIG_HOME`, а потім знищує test gateway і sandbox +- Корисні перевизначення: + - `OPENCLAW_E2E_OPENSHELL=1`, щоб увімкнути тест під час ручного запуску ширшого набору e2e + - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell`, щоб указати нестандартний бінарний файл CLI або wrapper-скрипт ### Live (реальні провайдери + реальні моделі) - Команда: `pnpm test:live` -- Конфігурація: `vitest.live.config.ts` +- Config: `vitest.live.config.ts` - Файли: `src/**/*.live.test.ts` -- Типово: **увімкнено** через `pnpm test:live` (встановлює `OPENCLAW_LIVE_TEST=1`) +- За замовчуванням: **увімкнено** через `pnpm test:live` (встановлює `OPENCLAW_LIVE_TEST=1`) - Обсяг: - «Чи справді цей провайдер/модель працює _сьогодні_ з реальними обліковими даними?» - - Виявлення змін формату провайдера, особливостей виклику інструментів, проблем автентифікації та поведінки rate limit + - Виявлення змін формату провайдера, особливостей виклику tool, проблем автентифікації та поведінки rate limit - Очікування: - - За задумом нестабільний у CI (реальні мережі, реальні політики провайдерів, квоти, збої) - - Коштує грошей / використовує rate limits - - Краще запускати звужені піднабори, а не «все» -- Live-запуски підвантажують `~/.profile`, щоб отримати відсутні API-ключі. -- За замовчуванням live-запуски все одно ізолюють `HOME` і копіюють матеріали config/auth у тимчасовий test home, щоб unit-фікстури не могли змінити ваш реальний `~/.openclaw`. -- Встановлюйте `OPENCLAW_LIVE_USE_REAL_HOME=1` лише тоді, коли вам свідомо потрібно, щоб live-тести використовували ваш реальний домашній каталог. -- `pnpm test:live` тепер типово використовує тихіший режим: він зберігає вивід прогресу `[live] ...`, але приглушує додаткове повідомлення `~/.profile` і вимикає логи bootstrap Gateway/шум Bonjour. Встановіть `OPENCLAW_LIVE_TEST_QUIET=0`, якщо хочете повернути повні стартові логи. -- Ротація API-ключів (залежно від провайдера): встановіть `*_API_KEYS` у форматі з комами/крапками з комою або `*_API_KEY_1`, `*_API_KEY_2` (наприклад, `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) або override для конкретного live-запуску через `OPENCLAW_LIVE_*_KEY`; тести повторюються у відповідь на rate limit. -- Вивід progress/Heartbeat: - - Live-набори тепер виводять рядки прогресу в stderr, щоб довгі виклики провайдера було видно як активні, навіть коли перехоплення консолі Vitest тихе. - - `vitest.live.config.ts` вимикає перехоплення консолі у Vitest, тому рядки progress провайдера/gateway одразу транслюються під час live-запусків. + - Навмисно нестабільний для CI (реальні мережі, реальні політики провайдерів, квоти, збої) + - Коштує грошей / використовує rate limit + - Краще запускати звужені підмножини, а не «все» +- Live-запуски використовують `~/.profile`, щоб підхопити відсутні API-ключі. +- За замовчуванням live-запуски все ще ізолюють `HOME` і копіюють material config/auth у тимчасовий test home, щоб unit-fixture не могли змінити ваш реальний `~/.openclaw`. +- Установлюйте `OPENCLAW_LIVE_USE_REAL_HOME=1` лише тоді, коли свідомо хочете, щоб live-тести використовували ваш реальний домашній каталог. +- `pnpm test:live` тепер за замовчуванням працює в тихішому режимі: він зберігає вивід прогресу `[live] ...`, але приховує додаткове повідомлення `~/.profile` і приглушує логи bootstrap Gateway/шум Bonjour. Установіть `OPENCLAW_LIVE_TEST_QUIET=0`, якщо хочете знову отримати повні логи запуску. +- Ротація API-ключів (специфічно для провайдера): установіть `*_API_KEYS` у форматі з комами/крапками з комою або `*_API_KEY_1`, `*_API_KEY_2` (наприклад, `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) або використовуйте перевизначення для конкретного live-запуску через `OPENCLAW_LIVE_*_KEY`; тести повторюють спроби у відповідь на rate limit. +- Вивід прогресу/Heartbeat: + - Live-набори тепер виводять рядки прогресу до stderr, щоб довгі виклики провайдера було видно як активні навіть тоді, коли захоплення консолі Vitest працює тихо. + - `vitest.live.config.ts` вимикає перехоплення консолі Vitest, тому рядки прогресу провайдера/Gateway одразу транслюються під час live-запусків. - Налаштовуйте Heartbeat для direct-model через `OPENCLAW_LIVE_HEARTBEAT_MS`. - - Налаштовуйте Heartbeat gateway/probe через `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS`. + - Налаштовуйте Heartbeat для gateway/probe через `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS`. ## Який набір мені запускати? Використовуйте цю таблицю рішень: - Редагуєте логіку/тести: запускайте `pnpm test` (і `pnpm test:coverage`, якщо змінили багато) -- Торкаєтесь мережевої взаємодії gateway / протоколу WS / спарювання: додайте `pnpm test:e2e` -- Налагоджуєте «мій бот не працює» / збої конкретного провайдера / виклик інструментів: запускайте звужений `pnpm test:live` +- Торкаєтеся мережевої взаємодії Gateway / протоколу WS / pairing: додайте `pnpm test:e2e` +- Налагоджуєте «мій бот не працює» / збої, специфічні для провайдера / виклик tool: запускайте звужений `pnpm test:live` -## Live: перевірка можливостей Android Node +## Live: огляд можливостей Android Node - Тест: `src/gateway/android-node.capabilities.live.test.ts` - Скрипт: `pnpm android:test:integration` -- Мета: викликати **кожну команду, яку наразі оголошує** підключений Android Node, і перевірити поведінку контракту команд. +- Мета: викликати **кожну команду, яку наразі рекламує** підключений Android Node, і перевірити поведінку контракту команд. - Обсяг: - - Попередньо підготовлене/ручне налаштування (набір не встановлює, не запускає і не спаровує застосунок). - - Перевірка `node.invoke` у Gateway команда за командою для вибраного Android Node. + - Попередньо підготовлене/ручне налаштування (набір не встановлює/не запускає/не pair-ить app). + - Перевірка gateway `node.invoke` для вибраного Android Node, команда за командою. - Обов’язкове попереднє налаштування: - - Android-застосунок уже підключений і спарений із Gateway. - - Застосунок утримується на передньому плані. - - Дозволи/згода на захоплення надані для можливостей, які ви очікуєте успішно пройти. -- Необов’язкові override цілі: + - Android app уже підключено й pair-ено з Gateway. + - App має залишатися на передньому плані. + - Для можливостей, які ви очікуєте як успішні, мають бути надані дозволи/згода на захоплення. +- Необов’язкові перевизначення цілі: - `OPENCLAW_ANDROID_NODE_ID` або `OPENCLAW_ANDROID_NODE_NAME`. - `OPENCLAW_ANDROID_GATEWAY_URL` / `OPENCLAW_ANDROID_GATEWAY_TOKEN` / `OPENCLAW_ANDROID_GATEWAY_PASSWORD`. -- Повні деталі налаштування Android: [Android App](/uk/platforms/android) +- Повні відомості про налаштування Android: [Android App](/uk/platforms/android) -## Live: smoke моделей (ключі профілів) +## Live: smoke-тест моделі (ключі profile) Live-тести поділено на два шари, щоб можна було ізолювати збої: -- «Direct model» показує, чи взагалі провайдер/модель може відповідати з наданим ключем. -- «Gateway smoke» показує, що повний конвеєр gateway+agent працює для цієї моделі (сесії, історія, інструменти, політика sandbox тощо). +- «Direct model» показує, чи провайдер/модель взагалі може відповісти з наданим ключем. +- «Gateway smoke» показує, чи повний pipeline gateway+agent працює для цієї моделі (сесії, історія, tools, політика sandbox тощо). -### Шар 1: Пряме завершення моделі (без gateway) +### Шар 1: Direct model completion (без Gateway) - Тест: `src/agents/models.profiles.live.test.ts` - Мета: - - Перелічити виявлені моделі - - Використати `getApiKeyForModel` для вибору моделей, для яких у вас є облікові дані + - Перерахувати виявлені моделі + - Використати `getApiKeyForModel`, щоб вибрати моделі, для яких у вас є облікові дані - Виконати невелике completion для кожної моделі (і цільові регресії там, де потрібно) - Як увімкнути: - `pnpm test:live` (або `OPENCLAW_LIVE_TEST=1`, якщо викликаєте Vitest напряму) -- Встановіть `OPENCLAW_LIVE_MODELS=modern` (або `all`, alias для modern), щоб справді запустити цей набір; інакше його буде пропущено, щоб `pnpm test:live` залишався зосередженим на gateway smoke +- Установіть `OPENCLAW_LIVE_MODELS=modern` (або `all`, alias для modern), щоб справді запустити цей набір; інакше його буде пропущено, щоб `pnpm test:live` залишався зосередженим на gateway smoke - Як вибирати моделі: - - `OPENCLAW_LIVE_MODELS=modern`, щоб запустити сучасний allowlist (Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4) - - `OPENCLAW_LIVE_MODELS=all` — це alias для сучасного allowlist + - `OPENCLAW_LIVE_MODELS=modern`, щоб запустити modern allowlist (Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4) + - `OPENCLAW_LIVE_MODELS=all` — це alias для modern allowlist - або `OPENCLAW_LIVE_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,..."` (allowlist через кому) - - Прогони modern/all типово мають підібрану межу з високим сигналом; встановіть `OPENCLAW_LIVE_MAX_MODELS=0` для вичерпного modern-прогону або додатне число для меншої межі. + - Режими modern/all sweep за замовчуванням мають підібрану межу з високим сигналом; установіть `OPENCLAW_LIVE_MAX_MODELS=0` для вичерпного modern sweep або додатне число для меншої межі. - Як вибирати провайдерів: - `OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"` (allowlist через кому) - Звідки беруться ключі: - - Типово: зі сховища профілів і резервних env-джерел - - Встановіть `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб вимагати **лише сховище профілів** + - За замовчуванням: сховище profile і резервні значення з env + - Установіть `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати **лише сховище profile** - Навіщо це існує: - - Відокремлює «API провайдера зламане / ключ недійсний» від «конвеєр gateway agent зламаний» - - Містить невеликі ізольовані регресії (приклад: replay reasoning у OpenAI Responses/Codex Responses + потоки tool-call) + - Відокремлює «API провайдера зламане / ключ недійсний» від «pipeline gateway agent зламаний» + - Містить невеликі ізольовані регресії (приклад: OpenAI Responses/Codex Responses reasoning replay + потоки tool-call) ### Шар 2: Gateway + smoke dev agent (що насправді робить "@openclaw") - Тест: `src/gateway/gateway-models.profiles.live.test.ts` - Мета: - - Підняти in-process Gateway - - Створити/оновити сесію `agent:dev:*` (override моделі для кожного запуску) - - Ітеруватися по моделях із ключами та перевіряти: - - «змістовну» відповідь (без інструментів) - - що реальний виклик інструмента працює (перевірка `read`) - - необов’язкові додаткові перевірки інструментів (перевірка `exec+read`) - - що шляхи регресій OpenAI (лише tool-call → наступний крок) і далі працюють -- Деталі перевірок probe (щоб можна було швидко пояснювати збої): - - probe `read`: тест записує файл із nonce у workspace і просить агента `read` його та повернути nonce. - - probe `exec+read`: тест просить агента через `exec` записати nonce у тимчасовий файл, а потім прочитати його назад через `read`. - - image probe: тест додає згенерований PNG (cat + рандомізований код) і очікує, що модель поверне `cat `. + - Запустити in-process Gateway + - Створити/пропатчити сесію `agent:dev:*` (перевизначення моделі для кожного запуску) + - Ітерувати моделі-з-ключами й перевіряти: + - «змістовну» відповідь (без tools) + - що реальний виклик tool працює (probe `read`) + - необов’язкові додаткові probe tool (probe `exec+read`) + - що шляхи регресії OpenAI (лише tool-call → подальша відповідь) продовжують працювати +- Деталі probe (щоб ви могли швидко пояснювати збої): + - probe `read`: тест записує файл із nonce у workspace і просить agent виконати `read` цього файла та повернути nonce назад. + - probe `exec+read`: тест просить agent через `exec` записати nonce у тимчасовий файл, а потім через `read` прочитати його назад. + - probe image: тест прикріплює згенерований PNG (cat + рандомізований код) і очікує, що модель поверне `cat `. - Посилання на реалізацію: `src/gateway/gateway-models.profiles.live.test.ts` і `src/gateway/live-image-probe.ts`. - Як увімкнути: - `pnpm test:live` (або `OPENCLAW_LIVE_TEST=1`, якщо викликаєте Vitest напряму) - Як вибирати моделі: - - Типово: сучасний allowlist (Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4) - - `OPENCLAW_LIVE_GATEWAY_MODELS=all` — це alias для сучасного allowlist + - За замовчуванням: modern allowlist (Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4) + - `OPENCLAW_LIVE_GATEWAY_MODELS=all` — це alias для modern allowlist - Або встановіть `OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"` (або список через кому), щоб звузити вибір - - Прогони modern/all для gateway типово мають підібрану межу з високим сигналом; встановіть `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0` для вичерпного modern-прогону або додатне число для меншої межі. -- Як вибирати провайдерів (уникнути «все з OpenRouter»): + - Режими modern/all для gateway sweep за замовчуванням мають підібрану межу з високим сигналом; установіть `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0` для вичерпного modern sweep або додатне число для меншої межі. +- Як вибирати провайдерів (уникайте «усе через OpenRouter»): - `OPENCLAW_LIVE_GATEWAY_PROVIDERS="google,google-antigravity,google-gemini-cli,openai,anthropic,zai,minimax"` (allowlist через кому) -- Перевірки tool + image завжди увімкнені в цьому live-тесті: - - probe `read` + probe `exec+read` (навантаження на інструменти) - - image probe запускається, коли модель оголошує підтримку image input - - Потік (на високому рівні): - - Тест генерує крихітний PNG із «CAT» + випадковим кодом (`src/gateway/live-image-probe.ts`) +- Probe tool + image у цьому live-тесті завжди ввімкнені: + - probe `read` + probe `exec+read` (навантаження на tool) + - probe image запускається, коли модель рекламує підтримку image input + - Потік (високорівнево): + - Тест генерує крихітний PNG з «CAT» + випадковим кодом (`src/gateway/live-image-probe.ts`) - Надсилає його через `agent` `attachments: [{ mimeType: "image/png", content: "" }]` - Gateway парсить attachments у `images[]` (`src/gateway/server-methods/agent.ts` + `src/gateway/chat-attachments.ts`) - - Embedded agent пересилає мультимодальне повідомлення користувача моделі - - Перевірка: відповідь містить `cat` + код (OCR tolerance: незначні помилки дозволені) + - Embedded agent пересилає multimodal user message моделі + - Перевірка: відповідь містить `cat` + код (допуск OCR: незначні помилки дозволені) -Порада: щоб побачити, що можна протестувати на вашій машині (і точні ідентифікатори `provider/model`), виконайте: +Порада: щоб побачити, що саме можна тестувати на вашій машині (і точні ідентифікатори `provider/model`), запустіть: ```bash openclaw models list openclaw models list --json ``` -## Live: smoke CLI backend (Claude, Codex, Gemini або інші локальні CLI) +## Live: smoke-тест backend CLI (Claude, Codex, Gemini або інші локальні CLI) - Тест: `src/gateway/gateway-cli-backend.live.test.ts` -- Мета: перевірити конвеєр Gateway + agent за допомогою локального CLI backend, не торкаючись вашої типової конфігурації. -- Типові значення smoke для конкретного backend живуть у визначенні `cli-backend.ts` extension-власника. +- Мета: перевірити pipeline Gateway + agent, використовуючи локальний backend CLI, не торкаючись вашого config за замовчуванням. +- Значення smoke за замовчуванням, специфічні для backend, містяться у визначенні `cli-backend.ts` extension-власника. - Увімкнення: - `pnpm test:live` (або `OPENCLAW_LIVE_TEST=1`, якщо викликаєте Vitest напряму) - `OPENCLAW_LIVE_CLI_BACKEND=1` -- Типові значення: - - Типовий provider/model: `claude-cli/claude-sonnet-4-6` - - Поведінка command/args/image береться з метаданих Plugin CLI backend-власника. -- Override (необов’язково): +- Значення за замовчуванням: + - Провайдер/модель за замовчуванням: `claude-cli/claude-sonnet-4-6` + - Поведінка command/args/image походить із метаданих plugin CLI backend-власника. +- Перевизначення (необов’язково): - `OPENCLAW_LIVE_CLI_BACKEND_MODEL="codex-cli/gpt-5.4"` - `OPENCLAW_LIVE_CLI_BACKEND_COMMAND="/full/path/to/codex"` - `OPENCLAW_LIVE_CLI_BACKEND_ARGS='["exec","--json","--color","never","--sandbox","read-only","--skip-git-repo-check"]'` - - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE=1`, щоб надіслати реальне image-вкладення (шляхи інжектуються в prompt). - - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"`, щоб передавати шляхи файлів зображень як CLI args замість інжекції в prompt. - - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"` (або `"list"`), щоб керувати способом передавання image args, коли встановлено `IMAGE_ARG`. + - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE=1`, щоб надіслати реальне image attachment (шляхи інжектуються в prompt). + - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"`, щоб передавати шляхи до файлів image як аргументи CLI замість інжекції в prompt. + - `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"` (або `"list"`), щоб керувати тим, як передаються аргументи image, коли встановлено `IMAGE_ARG`. - `OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1`, щоб надіслати другий хід і перевірити потік resume. - - `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0`, щоб вимкнути типову перевірку безперервності тієї самої сесії Claude Sonnet -> Opus (встановіть `1`, щоб примусово ввімкнути її, коли вибрана модель підтримує ціль перемикання). + - `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0`, щоб вимкнути стандартний probe безперервності тієї самої сесії Claude Sonnet -> Opus (установіть `1`, щоб примусово ввімкнути його, коли вибрана модель підтримує ціль перемикання). Приклад: @@ -505,13 +507,13 @@ OPENCLAW_LIVE_CLI_BACKEND=1 \ pnpm test:live src/gateway/gateway-cli-backend.live.test.ts ``` -Docker-рецепт: +Рецепт Docker: ```bash pnpm test:docker:live-cli-backend ``` -Docker-рецепти для одного провайдера: +Рецепти Docker для одного провайдера: ```bash pnpm test:docker:live-cli-backend:claude @@ -522,38 +524,38 @@ pnpm test:docker:live-cli-backend:gemini Примітки: -- Docker-ранер розташовано в `scripts/test-live-cli-backend-docker.sh`. -- Він запускає live smoke CLI-backend усередині Docker-образу репозиторію від імені непривілейованого користувача `node`. -- Він визначає метадані CLI smoke із extension-власника, а потім встановлює відповідний Linux CLI-пакет (`@anthropic-ai/claude-code`, `@openai/codex` або `@google/gemini-cli`) у кешований записуваний префікс `OPENCLAW_DOCKER_CLI_TOOLS_DIR` (типово: `~/.cache/openclaw/docker-cli-tools`). -- `pnpm test:docker:live-cli-backend:claude-subscription` потребує portable Claude Code subscription OAuth через `~/.claude/.credentials.json` з `claudeAiOauth.subscriptionType` або `CLAUDE_CODE_OAUTH_TOKEN` із `claude setup-token`. Спочатку він доводить прямий `claude -p` у Docker, потім запускає два ходи Gateway CLI-backend без збереження env-змінних ключа Anthropic API. Цей lane підписки типово вимикає probe Claude MCP/tool та image, оскільки Claude зараз маршрутизує використання сторонніх застосунків через додаткове usage billing замість звичайних лімітів плану підписки. -- Live smoke CLI-backend тепер перевіряє той самий наскрізний потік для Claude, Codex і Gemini: текстовий хід, хід із класифікацією зображення, потім виклик інструмента MCP `cron`, перевірений через Gateway CLI. -- Типовий smoke для Claude також оновлює сесію із Sonnet до Opus і перевіряє, що відновлена сесія все ще пам’ятає попередню нотатку. +- Docker-раннер розташований у `scripts/test-live-cli-backend-docker.sh`. +- Він запускає live smoke CLI-backend усередині Docker-образу репозиторію від імені non-root користувача `node`. +- Він визначає метадані smoke CLI із extension-власника, а потім установлює відповідний Linux-пакет CLI (`@anthropic-ai/claude-code`, `@openai/codex` або `@google/gemini-cli`) у кешований записуваний префікс за адресою `OPENCLAW_DOCKER_CLI_TOOLS_DIR` (за замовчуванням: `~/.cache/openclaw/docker-cli-tools`). +- `pnpm test:docker:live-cli-backend:claude-subscription` потребує portable OAuth підписки Claude Code через `~/.claude/.credentials.json` з `claudeAiOauth.subscriptionType` або `CLAUDE_CODE_OAUTH_TOKEN` із `claude setup-token`. Спочатку він перевіряє прямий `claude -p` у Docker, а потім запускає два ходи Gateway CLI-backend без збереження env API-ключів Anthropic. Цей lane підписки за замовчуванням вимикає Claude MCP/tool і probe image, оскільки Claude наразі маршрутизує використання стороннього застосунку через білінг додаткового використання, а не звичайні ліміти плану підписки. +- Live smoke CLI-backend тепер перевіряє той самий наскрізний потік для Claude, Codex і Gemini: текстовий хід, хід класифікації image, потім виклик tool MCP `cron`, перевірений через CLI Gateway. +- Стандартний smoke для Claude також патчить сесію із Sonnet на Opus і перевіряє, що відновлена сесія все ще пам’ятає попередню нотатку. -## Live: smoke ACP bind (`/acp spawn ... --bind here`) +## Live: smoke-тест ACP bind (`/acp spawn ... --bind here`) - Тест: `src/gateway/gateway-acp-bind.live.test.ts` -- Мета: перевірити реальний потік conversation-bind ACP із live ACP agent: +- Мета: перевірити реальний потік bind conversation ACP з live ACP agent: - надіслати `/acp spawn --bind here` - - прив’язати синтетичну розмову message-channel на місці - - надіслати звичайне подальше повідомлення в тій самій розмові - - перевірити, що подальше повідомлення потрапляє до транскрипту прив’язаної ACP session + - прив’язати синтетичну conversation message-channel на місці + - надіслати звичайну подальшу відповідь у цій самій conversation + - переконатися, що подальша відповідь потрапляє в transcript прив’язаної сесії ACP - Увімкнення: - `pnpm test:live src/gateway/gateway-acp-bind.live.test.ts` - `OPENCLAW_LIVE_ACP_BIND=1` -- Типові значення: - - ACP agents у Docker: `claude,codex,gemini` +- Значення за замовчуванням: + - ACP agent у Docker: `claude,codex,gemini` - ACP agent для прямого `pnpm test:live ...`: `claude` - - Синтетичний канал: контекст розмови в стилі Slack DM + - Синтетичний channel: контекст conversation у стилі Slack DM - ACP backend: `acpx` -- Override: +- Перевизначення: - `OPENCLAW_LIVE_ACP_BIND_AGENT=claude` - `OPENCLAW_LIVE_ACP_BIND_AGENT=codex` - `OPENCLAW_LIVE_ACP_BIND_AGENT=gemini` - `OPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex,gemini` - `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND='npx -y @agentclientprotocol/claude-agent-acp@'` - Примітки: - - Цей lane використовує поверхню gateway `chat.send` з admin-only synthetic originating-route fields, щоб тести могли прикріплювати контекст message-channel, не вдаючи зовнішню доставку. - - Коли `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND` не встановлено, тест використовує вбудований реєстр агентів Plugin `acpx` для вибраного ACP harness agent. + - Цей lane використовує поверхню gateway `chat.send` з admin-only синтетичними полями originating-route, щоб тести могли прикріплювати контекст message-channel, не імітуючи зовнішню доставку. + - Коли `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND` не встановлено, тест використовує вбудований реєстр agent plugin `acpx` для вибраного harness agent ACP. Приклад: @@ -563,13 +565,13 @@ OPENCLAW_LIVE_ACP_BIND=1 \ pnpm test:live src/gateway/gateway-acp-bind.live.test.ts ``` -Docker-рецепт: +Рецепт Docker: ```bash pnpm test:docker:live-acp-bind ``` -Docker-рецепти для одного агента: +Рецепти Docker для одного agent: ```bash pnpm test:docker:live-acp-bind:claude @@ -579,31 +581,31 @@ pnpm test:docker:live-acp-bind:gemini Примітки щодо Docker: -- Docker-ранер розташовано в `scripts/test-live-acp-bind-docker.sh`. -- За замовчуванням він запускає smoke ACP bind послідовно для всіх підтримуваних live CLI agents: `claude`, `codex`, потім `gemini`. +- Docker-раннер розташований у `scripts/test-live-acp-bind-docker.sh`. +- За замовчуванням він запускає smoke ACP bind для всіх підтримуваних live CLI agent послідовно: `claude`, `codex`, потім `gemini`. - Використовуйте `OPENCLAW_LIVE_ACP_BIND_AGENTS=claude`, `OPENCLAW_LIVE_ACP_BIND_AGENTS=codex` або `OPENCLAW_LIVE_ACP_BIND_AGENTS=gemini`, щоб звузити матрицю. -- Він підвантажує `~/.profile`, переносить відповідні матеріали CLI auth у контейнер, встановлює `acpx` у записуваний npm-префікс, а потім встановлює потрібний live CLI (`@anthropic-ai/claude-code`, `@openai/codex` або `@google/gemini-cli`), якщо його бракує. -- Усередині Docker ранер встановлює `OPENCLAW_LIVE_ACP_BIND_ACPX_COMMAND=$HOME/.npm-global/bin/acpx`, щоб acpx зберігав env-змінні провайдера з підвантаженого профілю доступними для дочірнього harness CLI. +- Він використовує `~/.profile`, переносить відповідний auth material CLI до контейнера, установлює `acpx` у записуваний npm-префікс, а потім установлює потрібний live CLI (`@anthropic-ai/claude-code`, `@openai/codex` або `@google/gemini-cli`), якщо його немає. +- Усередині Docker раннер установлює `OPENCLAW_LIVE_ACP_BIND_ACPX_COMMAND=$HOME/.npm-global/bin/acpx`, щоб acpx зберігав env-змінні провайдера з підключеного profile доступними для дочірнього harness CLI. -## Live: smoke harness app-server Codex +## Live: smoke-тест harness app-server Codex -- Мета: перевірити Codex harness, яким володіє Plugin, через звичайний метод gateway +- Мета: перевірити harness Codex, яким володіє plugin, через звичайний метод gateway `agent`: - - завантажити вбудований Plugin `codex` + - завантажити bundled plugin `codex` - вибрати `OPENCLAW_AGENT_RUNTIME=codex` - надіслати перший хід gateway agent до `codex/gpt-5.4` - - надіслати другий хід до тієї самої сесії OpenClaw і перевірити, що потік + - надіслати другий хід до тієї самої сесії OpenClaw і перевірити, що thread app-server може відновитися - - запустити `/codex status` і `/codex models` через той самий шлях gateway - command + - запустити `/codex status` і `/codex models` через той самий шлях + команди gateway - Тест: `src/gateway/gateway-codex-harness.live.test.ts` - Увімкнення: `OPENCLAW_LIVE_CODEX_HARNESS=1` -- Типова модель: `codex/gpt-5.4` -- Необов’язковий image probe: `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1` -- Необов’язковий MCP/tool probe: `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1` -- Smoke-тест встановлює `OPENCLAW_AGENT_HARNESS_FALLBACK=none`, щоб зламаний Codex - harness не міг пройти, тихо переключившись назад на PI. -- Автентифікація: `OPENAI_API_KEY` із shell/profile, плюс необов’язково скопійовані +- Модель за замовчуванням: `codex/gpt-5.4` +- Необов’язковий probe image: `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1` +- Необов’язковий probe MCP/tool: `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1` +- Цей smoke встановлює `OPENCLAW_AGENT_HARNESS_FALLBACK=none`, щоб зламаний Codex + harness не міг пройти перевірку через тихий fallback до Pi. +- Auth: `OPENAI_API_KEY` з shell/profile, плюс необов’язково скопійовані `~/.codex/auth.json` і `~/.codex/config.toml` Локальний рецепт: @@ -617,7 +619,7 @@ OPENCLAW_LIVE_CODEX_HARNESS=1 \ pnpm test:live -- src/gateway/gateway-codex-harness.live.test.ts ``` -Docker-рецепт: +Рецепт Docker: ```bash source ~/.profile @@ -626,52 +628,52 @@ pnpm test:docker:live-codex-harness Примітки щодо Docker: -- Docker-ранер розташовано в `scripts/test-live-codex-harness-docker.sh`. -- Він підвантажує змонтований `~/.profile`, передає `OPENAI_API_KEY`, копіює файли - автентифікації Codex CLI, якщо вони є, встановлює `@openai/codex` у записуваний змонтований npm - префікс, готує дерево вихідного коду, а потім запускає лише live-тест Codex-harness. -- Docker типово вмикає image і MCP/tool probes. Встановіть +- Docker-раннер розташований у `scripts/test-live-codex-harness-docker.sh`. +- Він використовує змонтований `~/.profile`, передає `OPENAI_API_KEY`, копіює файли + auth Codex CLI, якщо вони є, установлює `@openai/codex` у записуваний змонтований npm + префікс, підготовлює дерево вихідного коду, а потім запускає лише live-тест Codex-harness. +- Docker за замовчуванням вмикає probe image і MCP/tool. Установіть `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0` або - `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0`, коли вам потрібен вужчий налагоджувальний запуск. + `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0`, коли потрібен вужчий запуск для налагодження. - Docker також експортує `OPENCLAW_AGENT_HARNESS_FALLBACK=none`, як і live - конфігурація тесту, тому fallback `openai-codex/*` або PI не може приховати регресію + config тесту, щоб fallback `openai-codex/*` або Pi не міг приховати регресію Codex harness. ### Рекомендовані live-рецепти -Вузькі, явні allowlist найшвидші й найменш нестабільні: +Вузькі, явні allowlist — найшвидші та найменш нестабільні: -- Одна модель, direct (без gateway): +- Одна модель, direct (без Gateway): - `OPENCLAW_LIVE_MODELS="openai/gpt-5.4" pnpm test:live src/agents/models.profiles.live.test.ts` - Одна модель, gateway smoke: - `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` -- Виклик інструментів для кількох провайдерів: +- Виклик tool для кількох провайдерів: - `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,google/gemini-3-flash-preview,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` -- Фокус на Google (ключ API Gemini + Antigravity): - - Gemini (ключ API): `OPENCLAW_LIVE_GATEWAY_MODELS="google/gemini-3-flash-preview" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` +- Фокус на Google (API-ключ Gemini + Antigravity): + - Gemini (API-ключ): `OPENCLAW_LIVE_GATEWAY_MODELS="google/gemini-3-flash-preview" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` - Antigravity (OAuth): `OPENCLAW_LIVE_GATEWAY_MODELS="google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-pro-high" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` Примітки: -- `google/...` використовує Gemini API (ключ API). -- `google-antigravity/...` використовує міст OAuth Antigravity (endpoint агента в стилі Cloud Code Assist). -- `google-gemini-cli/...` використовує локальний Gemini CLI на вашій машині (окрема автентифікація + особливості tooling). +- `google/...` використовує Gemini API (API-ключ). +- `google-antigravity/...` використовує міст OAuth Antigravity (endpoint agent у стилі Cloud Code Assist). +- `google-gemini-cli/...` використовує локальний Gemini CLI на вашій машині (окрема auth + особливості tooling). - Gemini API проти Gemini CLI: - - API: OpenClaw викликає розміщений Google Gemini API через HTTP (автентифікація ключем API / профілем); саме це більшість користувачів мають на увазі під «Gemini». - - CLI: OpenClaw викликає локальний бінарник `gemini`; він має власну автентифікацію та може поводитися інакше (streaming/підтримка інструментів/розсинхрон версій). + - API: OpenClaw викликає хостований Gemini API від Google через HTTP (auth через API-ключ / profile); це те, що більшість користувачів мають на увазі під «Gemini». + - CLI: OpenClaw звертається до локального бінарного файла `gemini`; він має власну auth і може поводитися інакше (streaming/підтримка tool/розбіжність версій). -## Live: матриця моделей (що ми охоплюємо) +## Live: матриця моделей (що ми покриваємо) -Фіксованого «списку моделей CI» немає (live — це opt-in), але це **рекомендовані** моделі, які варто регулярно покривати на dev-машині з ключами. +Фіксованого «списку моделей CI» немає (live — це opt-in), але це **рекомендовані** моделі, які варто регулярно покривати на машині розробника з ключами. -### Сучасний smoke-набір (виклик інструментів + image) +### Modern smoke-набір (виклик tool + image) -Це запуск «поширених моделей», який ми очікуємо підтримувати в робочому стані: +Це запуск «поширених моделей», який ми очікуємо підтримувати працездатним: -- OpenAI (не Codex): `openai/gpt-5.4` (необов’язково: `openai/gpt-5.4-mini`) +- OpenAI (не-Codex): `openai/gpt-5.4` (необов’язково: `openai/gpt-5.4-mini`) - OpenAI Codex: `openai-codex/gpt-5.4` - Anthropic: `anthropic/claude-opus-4-6` (або `anthropic/claude-sonnet-4-6`) - Google (Gemini API): `google/gemini-3.1-pro-preview` і `google/gemini-3-flash-preview` (уникайте старіших моделей Gemini 2.x) @@ -679,12 +681,12 @@ pnpm test:docker:live-codex-harness - Z.AI (GLM): `zai/glm-4.7` - MiniMax: `minimax/MiniMax-M2.7` -Запустіть gateway smoke з інструментами + image: +Запуск gateway smoke з tools + image: `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,openai-codex/gpt-5.4,anthropic/claude-opus-4-6,google/gemini-3.1-pro-preview,google/gemini-3-flash-preview,google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-flash,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` -### Базовий рівень: виклик інструментів (Read + необов’язковий Exec) +### Базовий рівень: виклик tool (Read + необов’язковий Exec) -Оберіть щонайменше одну модель для кожного сімейства провайдерів: +Виберіть щонайменше одну модель для кожної родини провайдерів: - OpenAI: `openai/gpt-5.4` (або `openai/gpt-5.4-mini`) - Anthropic: `anthropic/claude-opus-4-6` (або `anthropic/claude-sonnet-4-6`) @@ -692,81 +694,81 @@ pnpm test:docker:live-codex-harness - Z.AI (GLM): `zai/glm-4.7` - MiniMax: `minimax/MiniMax-M2.7` -Необов’язкове додаткове покриття (бажано мати): +Необов’язкове додаткове покриття (було б добре мати): - xAI: `xai/grok-4` (або найновіша доступна) -- Mistral: `mistral/`… (оберіть одну модель із підтримкою інструментів, яку у вас увімкнено) +- Mistral: `mistral/`… (виберіть одну модель із підтримкою `tools`, яку у вас ввімкнено) - Cerebras: `cerebras/`… (якщо у вас є доступ) -- LM Studio: `lmstudio/`… (локально; виклик інструментів залежить від режиму API) +- LM Studio: `lmstudio/`… (локально; виклик tool залежить від режиму API) -### Vision: надсилання image (вкладення → мультимодальне повідомлення) +### Vision: надсилання image (attachment → multimodal message) -Додайте щонайменше одну модель із підтримкою image у `OPENCLAW_LIVE_GATEWAY_MODELS` (варіанти Claude/Gemini/OpenAI із підтримкою vision тощо), щоб перевірити image probe. +Додайте принаймні одну модель із підтримкою image до `OPENCLAW_LIVE_GATEWAY_MODELS` (Claude/Gemini/OpenAI vision-capable варіанти тощо), щоб перевірити probe image. -### Агрегатори / альтернативні gateway +### Aggregator-и / альтернативні Gateway Якщо у вас увімкнені ключі, ми також підтримуємо тестування через: -- OpenRouter: `openrouter/...` (сотні моделей; використовуйте `openclaw models scan`, щоб знайти кандидатів із підтримкою інструментів та image) -- OpenCode: `opencode/...` для Zen і `opencode-go/...` для Go (автентифікація через `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY`) +- OpenRouter: `openrouter/...` (сотні моделей; використовуйте `openclaw models scan`, щоб знайти кандидатів із підтримкою tool+image) +- OpenCode: `opencode/...` для Zen і `opencode-go/...` для Go (auth через `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY`) -Інші провайдери, які можна включити до live-матриці (якщо у вас є облікові дані/конфігурація): +Більше провайдерів, які можна включити до live-матриці (якщо у вас є облікові дані/config): - Вбудовані: `openai`, `openai-codex`, `anthropic`, `google`, `google-vertex`, `google-antigravity`, `google-gemini-cli`, `zai`, `openrouter`, `opencode`, `opencode-go`, `xai`, `groq`, `cerebras`, `mistral`, `github-copilot` -- Через `models.providers` (кастомні endpoint): `minimax` (cloud/API), а також будь-який сумісний із OpenAI/Anthropic proxy (LM Studio, vLLM, LiteLLM тощо) +- Через `models.providers` (custom endpoint): `minimax` (cloud/API), а також будь-який сумісний із OpenAI/Anthropic proxy (LM Studio, vLLM, LiteLLM тощо) -Порада: не намагайтеся жорстко прописати в документації «усі моделі». Авторитетний список — це те, що повертає `discoverModels(...)` на вашій машині, плюс ті ключі, які доступні. +Порада: не намагайтеся жорстко прописати в документації «усі моделі». Авторитетний список — це те, що повертає `discoverModels(...)` на вашій машині + які ключі доступні. ## Облікові дані (ніколи не комітьте) Live-тести знаходять облікові дані так само, як і CLI. Практичні наслідки: -- Якщо CLI працює, live-тести мають знаходити ті самі ключі. -- Якщо live-тест каже «немає облікових даних», налагоджуйте це так само, як налагоджували б `openclaw models list` / вибір моделі. +- Якщо CLI працює, live-тести повинні знаходити ті самі ключі. +- Якщо live-тест повідомляє «немає облікових даних», налагоджуйте це так само, як налагоджували б `openclaw models list` / вибір моделі. -- Профілі автентифікації для кожного агента: `~/.openclaw/agents//agent/auth-profiles.json` (саме це означає «ключі профілів» у live-тестах) -- Конфігурація: `~/.openclaw/openclaw.json` (або `OPENCLAW_CONFIG_PATH`) -- Застарілий каталог стану: `~/.openclaw/credentials/` (копіюється до staged live home, якщо існує, але це не основне сховище ключів профілів) -- Локальні live-запуски типово копіюють активну конфігурацію, файли `auth-profiles.json` для кожного агента, застарілий каталог `credentials/` і підтримувані зовнішні каталоги CLI auth у тимчасовий test home; staged live home пропускають `workspace/` і `sandboxes/`, а override шляхів `agents.*.workspace` / `agentDir` видаляються, щоб probes не працювали у вашому реальному host workspace. +- Auth profile для кожного agent: `~/.openclaw/agents//agent/auth-profiles.json` (це і є те, що в live-тестах означає «ключі profile») +- Config: `~/.openclaw/openclaw.json` (або `OPENCLAW_CONFIG_PATH`) +- Каталог legacy state: `~/.openclaw/credentials/` (копіюється до staged live home, якщо існує, але це не основне сховище ключів profile) +- Локальні live-запуски за замовчуванням копіюють активний config, файли `auth-profiles.json` для кожного agent, legacy `credentials/` і підтримувані зовнішні каталоги auth CLI до тимчасового test home; staged live home пропускають `workspace/` і `sandboxes/`, а перевизначення шляху `agents.*.workspace` / `agentDir` видаляються, щоб probe не торкалися вашого реального workspace хоста. -Якщо ви хочете покладатися на env-ключі (наприклад, експортовані у вашому `~/.profile`), запускайте локальні тести після `source ~/.profile`, або використовуйте Docker-ранери нижче (вони можуть монтувати `~/.profile` у контейнер). +Якщо ви хочете покладатися на ключі з env (наприклад, експортовані у вашому `~/.profile`), запускайте локальні тести після `source ~/.profile` або використовуйте Docker-раннери нижче (вони можуть монтувати `~/.profile` у контейнер). -## Live: Deepgram (транскрипція аудіо) +## Live Deepgram (транскрипція аудіо) - Тест: `src/media-understanding/providers/deepgram/audio.live.test.ts` - Увімкнення: `DEEPGRAM_API_KEY=... DEEPGRAM_LIVE_TEST=1 pnpm test:live src/media-understanding/providers/deepgram/audio.live.test.ts` -## Live: планування кодування BytePlus +## Live BytePlus coding plan - Тест: `src/agents/byteplus.live.test.ts` - Увімкнення: `BYTEPLUS_API_KEY=... BYTEPLUS_LIVE_TEST=1 pnpm test:live src/agents/byteplus.live.test.ts` -- Необов’язковий override моделі: `BYTEPLUS_CODING_MODEL=ark-code-latest` +- Необов’язкове перевизначення моделі: `BYTEPLUS_CODING_MODEL=ark-code-latest` -## Live: медіа workflow ComfyUI +## Live ComfyUI workflow media - Тест: `extensions/comfy/comfy.live.test.ts` - Увімкнення: `OPENCLAW_LIVE_TEST=1 COMFY_LIVE_TEST=1 pnpm test:live -- extensions/comfy/comfy.live.test.ts` - Обсяг: - - Перевіряє вбудовані шляхи comfy для зображень, відео та `music_generate` - - Пропускає кожну можливість, якщо `models.providers.comfy.` не налаштовано - - Корисно після змін у надсиланні workflow comfy, polling, завантаженнях або реєстрації Plugin + - Перевіряє bundled-шляхи comfy для image, video і `music_generate` + - Пропускає кожну можливість, якщо не налаштовано `models.providers.comfy.` + - Корисно після змін у поданні workflow comfy, polling, завантаженнях або реєстрації plugin -## Live: генерація зображень +## Live: генерація image - Тест: `src/image-generation/runtime.live.test.ts` - Команда: `pnpm test:live src/image-generation/runtime.live.test.ts` - Harness: `pnpm test:live:media image` - Обсяг: - - Перелічує кожен зареєстрований Plugin провайдера генерації зображень - - Завантажує відсутні env-змінні провайдера з вашого login shell (`~/.profile`) перед виконанням probe - - Типово використовує live/env API-ключі раніше за збережені профілі auth, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні облікові дані shell + - Перераховує кожен зареєстрований plugin провайдера генерації image + - Завантажує відсутні env-змінні провайдера з вашого login shell (`~/.profile`) перед probe + - За замовчуванням віддає перевагу live/env API-ключам над збереженими auth profile, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні облікові дані shell - Пропускає провайдерів без придатної auth/profile/model - - Запускає стандартні варіанти генерації зображень через спільну runtime-можливість: + - Запускає стандартні варіанти генерації image через спільну runtime-можливість: - `google:flash-generate` - `google:pro-generate` - `google:pro-edit` - `openai:default-generate` -- Поточні вбудовані провайдери, які покриваються: +- Поточні bundled-провайдери, що покриваються: - `openai` - `google` - Необов’язкове звуження: @@ -774,7 +776,7 @@ Live-тести знаходять облікові дані так само, я - `OPENCLAW_LIVE_IMAGE_GENERATION_MODELS="openai/gpt-image-2,google/gemini-3.1-flash-image-preview"` - `OPENCLAW_LIVE_IMAGE_GENERATION_CASES="google:flash-generate,google:pro-edit"` - Необов’язкова поведінка auth: - - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати auth зі сховища профілів та ігнорувати override лише з env + - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати auth сховища profile й ігнорувати перевизначення лише з env ## Live: генерація музики @@ -782,23 +784,23 @@ Live-тести знаходять облікові дані так само, я - Увімкнення: `OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/music-generation-providers.live.test.ts` - Harness: `pnpm test:live:media music` - Обсяг: - - Перевіряє спільний вбудований шлях провайдерів генерації музики - - Наразі охоплює Google і MiniMax - - Завантажує env-змінні провайдера з вашого login shell (`~/.profile`) перед виконанням probe - - Типово використовує live/env API-ключі раніше за збережені профілі auth, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні облікові дані shell + - Перевіряє спільний bundled-шлях провайдера генерації музики + - Наразі покриває Google і MiniMax + - Завантажує env-змінні провайдера з вашого login shell (`~/.profile`) перед probe + - За замовчуванням віддає перевагу live/env API-ключам над збереженими auth profile, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні облікові дані shell - Пропускає провайдерів без придатної auth/profile/model - Запускає обидва оголошені runtime-режими, коли вони доступні: - - `generate` з введенням лише prompt + - `generate` з input лише на основі prompt - `edit`, коли провайдер оголошує `capabilities.edit.enabled` - Поточне покриття спільного lane: - `google`: `generate`, `edit` - `minimax`: `generate` - - `comfy`: окремий live-файл Comfy, а не цей спільний прогін + - `comfy`: окремий live-файл Comfy, а не цей спільний sweep - Необов’язкове звуження: - `OPENCLAW_LIVE_MUSIC_GENERATION_PROVIDERS="google,minimax"` - `OPENCLAW_LIVE_MUSIC_GENERATION_MODELS="google/lyria-3-clip-preview,minimax/music-2.5+"` - Необов’язкова поведінка auth: - - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати auth зі сховища профілів та ігнорувати override лише з env + - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати auth сховища profile й ігнорувати перевизначення лише з env ## Live: генерація відео @@ -806,42 +808,42 @@ Live-тести знаходять облікові дані так само, я - Увімкнення: `OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/video-generation-providers.live.test.ts` - Harness: `pnpm test:live:media video` - Обсяг: - - Перевіряє спільний вбудований шлях провайдерів генерації відео - - Типово використовує безпечний для релізу шлях smoke: провайдери без FAL, один запит text-to-video на провайдера, односекундний prompt про лобстера та обмеження операції для кожного провайдера з `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` (типово `180000`) - - Типово пропускає FAL, тому що затримка черги на боці провайдера може домінувати над часом релізу; передайте `--video-providers fal` або `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="fal"`, щоб запустити його явно - - Завантажує env-змінні провайдера з вашого login shell (`~/.profile`) перед виконанням probe - - Типово використовує live/env API-ключі раніше за збережені профілі auth, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні облікові дані shell + - Перевіряє спільний bundled-шлях провайдера генерації відео + - За замовчуванням використовує безпечний для релізу smoke-шлях: провайдери не-FAL, один запит text-to-video на провайдера, односекундний lobster prompt і обмеження операції для кожного провайдера через `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` (за замовчуванням `180000`) + - За замовчуванням пропускає FAL, оскільки затримка черги на боці провайдера може домінувати в часі релізу; передайте `--video-providers fal` або `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="fal"`, щоб запустити його явно + - Завантажує env-змінні провайдера з вашого login shell (`~/.profile`) перед probe + - За замовчуванням віддає перевагу live/env API-ключам над збереженими auth profile, щоб застарілі тестові ключі в `auth-profiles.json` не маскували реальні облікові дані shell - Пропускає провайдерів без придатної auth/profile/model - - Типово запускає лише `generate` - - Встановіть `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1`, щоб також запускати оголошені режими transform, коли вони доступні: - - `imageToVideo`, коли провайдер оголошує `capabilities.imageToVideo.enabled`, а вибраний провайдер/модель приймає локальний image input на основі buffer у спільному прогоні - - `videoToVideo`, коли провайдер оголошує `capabilities.videoToVideo.enabled`, а вибраний провайдер/модель приймає локальний video input на основі buffer у спільному прогоні - - Поточні оголошені, але пропущені провайдери `imageToVideo` у спільному прогоні: - - `vydra`, тому що вбудований `veo3` підтримує лише text, а вбудований `kling` вимагає віддалений image URL - - Покриття Vydra для конкретного провайдера: + - За замовчуванням запускає лише `generate` + - Установіть `OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1`, щоб також запускати оголошені режими transform, коли вони доступні: + - `imageToVideo`, коли провайдер оголошує `capabilities.imageToVideo.enabled` і вибраний провайдер/модель приймає локальний input image на основі buffer у спільному sweep + - `videoToVideo`, коли провайдер оголошує `capabilities.videoToVideo.enabled` і вибраний провайдер/модель приймає локальний input video на основі buffer у спільному sweep + - Поточні оголошені, але пропущені провайдери `imageToVideo` у спільному sweep: + - `vydra`, тому що bundled `veo3` підтримує лише text, а bundled `kling` вимагає віддалений URL image + - Покриття Vydra, специфічне для провайдера: - `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_VYDRA_VIDEO=1 pnpm test:live -- extensions/vydra/vydra.live.test.ts` - - цей файл запускає `veo3` text-to-video плюс lane `kling`, який типово використовує фікстуру віддаленого image URL + - цей файл запускає `veo3` text-to-video, а також lane `kling`, який за замовчуванням використовує fixture із віддаленим URL image - Поточне live-покриття `videoToVideo`: - лише `runway`, коли вибрана модель — `runway/gen4_aleph` - - Поточні оголошені, але пропущені провайдери `videoToVideo` у спільному прогоні: - - `alibaba`, `qwen`, `xai`, тому що ці шляхи зараз вимагають віддалені URL-адреси посилань `http(s)` / MP4 - - `google`, тому що поточний спільний lane Gemini/Veo використовує локальний input на основі buffer, і цей шлях не приймається у спільному прогоні - - `openai`, тому що поточний спільний lane не має гарантій доступу до специфічних для org можливостей video inpaint/remix + - Поточні оголошені, але пропущені провайдери `videoToVideo` у спільному sweep: + - `alibaba`, `qwen`, `xai`, тому що ці шляхи наразі вимагають віддалені референсні URL `http(s)` / MP4 + - `google`, тому що поточний спільний lane Gemini/Veo використовує локальний input на основі buffer, а цей шлях не приймається у спільному sweep + - `openai`, тому що поточний спільний lane не гарантує доступ до org-specific inpaint/remix відео - Необов’язкове звуження: - `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="google,openai,runway"` - `OPENCLAW_LIVE_VIDEO_GENERATION_MODELS="google/veo-3.1-fast-generate-preview,openai/sora-2,runway/gen4_aleph"` - - `OPENCLAW_LIVE_VIDEO_GENERATION_SKIP_PROVIDERS=""`, щоб включити кожного провайдера в типовий прогін, включно з FAL - - `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS=60000`, щоб зменшити обмеження операції для кожного провайдера під час агресивного smoke-прогону + - `OPENCLAW_LIVE_VIDEO_GENERATION_SKIP_PROVIDERS=""`, щоб включити кожного провайдера у стандартний sweep, зокрема FAL + - `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS=60000`, щоб зменшити ліміт операції для кожного провайдера для агресивного smoke-запуску - Необов’язкова поведінка auth: - - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати auth зі сховища профілів та ігнорувати override лише з env + - `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб примусово використовувати auth сховища profile й ігнорувати перевизначення лише з env -## Media live harness +## Harness live media - Команда: `pnpm test:live:media` - Призначення: - - Запускає спільні live-набори для image, music і video через один native entrypoint репозиторію + - Запускає спільні live-набори image, music і video через один repo-native entrypoint - Автоматично завантажує відсутні env-змінні провайдера з `~/.profile` - - Типово автоматично звужує кожен набір до провайдерів, які зараз мають придатну auth + - За замовчуванням автоматично звужує кожен набір до провайдерів, які зараз мають придатну auth - Повторно використовує `scripts/test-live.mjs`, тому поведінка Heartbeat і тихого режиму залишається узгодженою - Приклади: - `pnpm test:live:media` @@ -849,89 +851,90 @@ Live-тести знаходять облікові дані так само, я - `pnpm test:live:media video --video-providers openai,runway --all-providers` - `pnpm test:live:media music --quiet` -## Docker-ранери (необов’язкові перевірки «працює в Linux») +## Docker-раннери (необов’язкові перевірки «працює в Linux») -Ці Docker-ранери поділяються на дві групи: +Ці Docker-раннери поділяються на дві групи: -- Ранери live-model: `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`), монтують ваш локальний каталог конфігурації та workspace (і підвантажують `~/.profile`, якщо його змонтовано). Відповідні локальні entrypoint — `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-model раннери: `test:docker:live-models` і `test:docker:live-gateway` запускають лише відповідний їм live-файл ключів profile усередині Docker-образу репозиторію (`src/agents/models.profiles.live.test.ts` і `src/gateway/gateway-models.profiles.live.test.ts`), монтують ваш локальний каталог config і workspace (а також використовують `~/.profile`, якщо його змонтовано). Відповідні локальні entrypoint — `test:live:models-profiles` і `test:live:gateway-profiles`. +- Docker live-раннери за замовчуванням використовують менший smoke-ліміт, щоб повний Docker sweep залишався практичним: + `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-змінні, коли + `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`. Перевизначайте ці env-змінні, коли вам явно потрібне більше вичерпне сканування. -- `test:docker:all` один раз збирає live Docker-образ через `test:docker:live-build`, а потім повторно використовує його для двох Docker live-lane. -- Ранери smoke контейнерів: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:gateway-network`, `test:docker:mcp-channels` і `test:docker:plugins` піднімають один або кілька реальних контейнерів і перевіряють інтеграційні шляхи вищого рівня. +- `test:docker:all` один раз збирає live Docker-образ через `test:docker:live-build`, а потім повторно використовує його для двох Docker lane live. +- Smoke-раннери контейнерів: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:gateway-network`, `test:docker:mcp-channels` і `test:docker:plugins` запускають один або кілька реальних контейнерів і перевіряють інтеграційні шляхи вищого рівня. -Docker-ранери live-model також bind-mount лише потрібні CLI auth home (або всі підтримувані, коли запуск не звужено), а потім копіюють їх у home контейнера перед запуском, щоб OAuth зовнішнього CLI міг оновлювати токени без змінення сховища auth на хості: +Docker-раннери live-model також bind-mount-ять лише потрібні home-каталоги auth CLI (або всі підтримувані, якщо запуск не звужено), а потім копіюють їх у home контейнера перед запуском, щоб OAuth зовнішнього CLI міг оновлювати токени, не змінюючи auth store хоста: - Direct models: `pnpm test:docker:live-models` (скрипт: `scripts/test-live-models-docker.sh`) - Smoke ACP bind: `pnpm test:docker:live-acp-bind` (скрипт: `scripts/test-live-acp-bind-docker.sh`) -- Smoke CLI backend: `pnpm test:docker:live-cli-backend` (скрипт: `scripts/test-live-cli-backend-docker.sh`) -- Smoke app-server harness Codex: `pnpm test:docker:live-codex-harness` (скрипт: `scripts/test-live-codex-harness-docker.sh`) +- Smoke backend CLI: `pnpm test:docker:live-cli-backend` (скрипт: `scripts/test-live-cli-backend-docker.sh`) +- Smoke harness app-server Codex: `pnpm test:docker:live-codex-harness` (скрипт: `scripts/test-live-codex-harness-docker.sh`) - Gateway + dev agent: `pnpm test:docker:live-gateway` (скрипт: `scripts/test-live-gateway-models-docker.sh`) - Live smoke Open WebUI: `pnpm test:docker:openwebui` (скрипт: `scripts/e2e/openwebui-docker.sh`) -- Майстер onboarding (TTY, повне scaffold): `pnpm test:docker:onboard` (скрипт: `scripts/e2e/onboard-docker.sh`) +- Wizard onboarding (TTY, повне scaffolding): `pnpm test:docker:onboard` (скрипт: `scripts/e2e/onboard-docker.sh`) - Мережева взаємодія Gateway (два контейнери, автентифікація WS + health): `pnpm test:docker:gateway-network` (скрипт: `scripts/e2e/gateway-network-docker.sh`) -- Міст каналу MCP (ініціалізований Gateway + stdio bridge + smoke сирого notification-frame Claude): `pnpm test:docker:mcp-channels` (скрипт: `scripts/e2e/mcp-channels-docker.sh`) -- Plugins (smoke встановлення + alias `/plugin` + семантика перезапуску Claude-bundle): `pnpm test:docker:plugins` (скрипт: `scripts/e2e/plugins-docker.sh`) +- Міст каналу MCP (seeded Gateway + stdio bridge + raw smoke notification-frame Claude): `pnpm test:docker:mcp-channels` (скрипт: `scripts/e2e/mcp-channels-docker.sh`) +- Plugin-и (smoke встановлення + alias `/plugin` + семантика перезапуску Claude-bundle): `pnpm test:docker:plugins` (скрипт: `scripts/e2e/plugins-docker.sh`) -Docker-ранери live-model також bind-mount поточний checkout лише для читання та -готують його у тимчасовий workdir усередині контейнера. Це зберігає runtime-образ -компактним, водночас дозволяючи запускати Vitest точно на вашому локальному вихідному коді/конфігурації. -Етап підготовки пропускає великі локальні кеші та вихідні дані збірки застосунків, як-от -`.pnpm-store`, `.worktrees`, `__openclaw_vitest__` і локальні для застосунку каталоги `.build` або +Docker-раннери live-model також bind-mount-ять поточний checkout лише для читання і +розгортають його у тимчасовий workdir усередині контейнера. Це зберігає runtime-образ +тонким, але водночас дозволяє запускати Vitest точно на вашому локальному source/config. +Крок підготовки пропускає великі локальні кеші та результати збірки app, як-от +`.pnpm-store`, `.worktrees`, `__openclaw_vitest__` і локальні для app каталоги `.build` або виводу Gradle, щоб Docker live-запуски не витрачали хвилини на копіювання машинно-специфічних артефактів. -Вони також встановлюють `OPENCLAW_SKIP_CHANNELS=1`, щоб live-probe Gateway не запускали -реальні воркери каналів Telegram/Discord тощо всередині контейнера. +Вони також установлюють `OPENCLAW_SKIP_CHANNELS=1`, щоб live-probe Gateway не запускали +реальні worker каналів Telegram/Discord тощо всередині контейнера. `test:docker:live-models` усе ще запускає `pnpm test:live`, тому також передавайте -`OPENCLAW_LIVE_GATEWAY_*`, коли вам потрібно звузити або виключити live-покриття gateway з цього Docker lane. -`test:docker:openwebui` — це smoke вищого рівня на сумісність: він запускає -контейнер Gateway OpenClaw з увімкненими сумісними з OpenAI HTTP endpoint, -запускає закріплений контейнер Open WebUI проти цього gateway, входить через +`OPENCLAW_LIVE_GATEWAY_*`, коли потрібно звузити або виключити live-покриття Gateway +з цього Docker lane. +`test:docker:openwebui` — це smoke сумісності вищого рівня: він запускає +контейнер Gateway OpenClaw з увімкненими HTTP-endpoint, сумісними з OpenAI, +запускає pinned-контейнер Open WebUI проти цього Gateway, входить через Open WebUI, перевіряє, що `/api/models` показує `openclaw/default`, а потім надсилає -реальний chat-запит через proxy Open WebUI `/api/chat/completions`. -Перший запуск може бути помітно повільнішим, тому що Docker може потребувати завантаження -образу Open WebUI, а Open WebUI може потребувати завершення власного cold-start налаштування. +реальний chat-запит через proxy `/api/chat/completions` Open WebUI. +Перший запуск може бути помітно повільнішим, оскільки Docker може потребувати завантаження +образу Open WebUI, а самому Open WebUI може знадобитися завершити власне cold-start налаштування. Цей lane очікує придатний ключ live-моделі, а `OPENCLAW_PROFILE_FILE` -(типово `~/.profile`) — основний спосіб надати його в Dockerized-запусках. +(за замовчуванням `~/.profile`) є основним способом надати його в Dockerized-запусках. Успішні запуски виводять невеликий JSON payload на кшталт `{ "ok": true, "model": "openclaw/default", ... }`. `test:docker:mcp-channels` навмисно детермінований і не потребує -реального облікового запису Telegram, Discord або iMessage. Він піднімає ініціалізований контейнер Gateway, -запускає другий контейнер, який виконує `openclaw mcp serve`, а потім -перевіряє виявлення маршрутизованих розмов, читання транскриптів, метадані вкладень, -поведінку черги live-подій, маршрутизацію вихідного надсилання та сповіщення в стилі Claude про канал + -дозволи через реальний stdio MCP bridge. Перевірка сповіщень -безпосередньо аналізує сирі stdio MCP frames, тож smoke перевіряє те, що -міст справді випромінює, а не лише те, що випадково показує конкретний клієнтський SDK. +реального облікового запису Telegram, Discord або iMessage. Він запускає seeded +контейнер Gateway, запускає другий контейнер, який стартує `openclaw mcp serve`, а потім +перевіряє виявлення conversation із маршрутизацією, читання transcript, метадані attachment, +поведінку черги live-подій, маршрутизацію outbound send і сповіщення про канал + +дозволи у стилі Claude через реальний stdio MCP bridge. Перевірка сповіщень +напряму аналізує raw-кадри stdio MCP, тому smoke перевіряє те, що міст +насправді випромінює, а не лише те, що певний SDK клієнта випадково надає на поверхню. -Ручний smoke plain-language thread для ACP (не CI): +Ручний smoke thread ACP простою мовою (не CI): - `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...` -- Залишайте цей скрипт для регресійних робочих процесів і налагодження. Він може знову знадобитися для перевірки маршрутизації ACP thread, тому не видаляйте його. +- Зберігайте цей скрипт для робочих процесів регресії/налагодження. Він може знову знадобитися для перевірки маршрутизації thread ACP, тому не видаляйте його. Корисні env-змінні: -- `OPENCLAW_CONFIG_DIR=...` (типово: `~/.openclaw`) монтується в `/home/node/.openclaw` -- `OPENCLAW_WORKSPACE_DIR=...` (типово: `~/.openclaw/workspace`) монтується в `/home/node/.openclaw/workspace` -- `OPENCLAW_PROFILE_FILE=...` (типово: `~/.profile`) монтується в `/home/node/.profile` і підвантажується перед запуском тестів -- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1`, щоб перевіряти лише env-змінні, підвантажені з `OPENCLAW_PROFILE_FILE`, використовуючи тимчасові каталоги config/workspace та без зовнішніх mount для CLI auth -- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...` (типово: `~/.cache/openclaw/docker-cli-tools`) монтується в `/home/node/.npm-global` для кешованих CLI-інсталяцій усередині Docker -- Зовнішні каталоги/файли CLI auth у `$HOME` монтуються лише для читання під `/host-auth...`, а потім копіюються в `/home/node/...` перед стартом тестів - - Типові каталоги: `.minimax` - - Типові файли: `~/.codex/auth.json`, `~/.codex/config.toml`, `.claude.json`, `~/.claude/.credentials.json`, `~/.claude/settings.json`, `~/.claude/settings.local.json` - - Звужені запуски провайдерів монтують лише потрібні каталоги/файли, визначені з `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` - - Override вручну через `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none` або список через кому, наприклад `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` +- `OPENCLAW_CONFIG_DIR=...` (за замовчуванням: `~/.openclaw`) монтується в `/home/node/.openclaw` +- `OPENCLAW_WORKSPACE_DIR=...` (за замовчуванням: `~/.openclaw/workspace`) монтується в `/home/node/.openclaw/workspace` +- `OPENCLAW_PROFILE_FILE=...` (за замовчуванням: `~/.profile`) монтується в `/home/node/.profile` і використовується перед запуском тестів +- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1`, щоб перевіряти лише env-змінні, отримані з `OPENCLAW_PROFILE_FILE`, використовуючи тимчасові каталоги config/workspace і без монтування auth зовнішнього CLI +- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...` (за замовчуванням: `~/.cache/openclaw/docker-cli-tools`) монтується в `/home/node/.npm-global` для кешованих установлень CLI всередині Docker +- Зовнішні каталоги/файли auth CLI під `$HOME` монтуються лише для читання під `/host-auth...`, а потім копіюються в `/home/node/...` перед стартом тестів + - Каталоги за замовчуванням: `.minimax` + - Файли за замовчуванням: `~/.codex/auth.json`, `~/.codex/config.toml`, `.claude.json`, `~/.claude/.credentials.json`, `~/.claude/settings.json`, `~/.claude/settings.local.json` + - Звужені запуски провайдера монтують лише потрібні каталоги/файли, які визначаються з `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` + - Можна перевизначити вручну через `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none` або список через кому, наприклад `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` - `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...`, щоб звузити запуск -- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...`, щоб фільтрувати провайдерів у контейнері -- `OPENCLAW_SKIP_DOCKER_BUILD=1`, щоб повторно використовувати наявний образ `openclaw:local-live` для повторних запусків, яким не потрібна перебудова -- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб переконатися, що облікові дані беруться зі сховища профілів (а не з env) -- `OPENCLAW_OPENWEBUI_MODEL=...`, щоб вибрати модель, яку gateway відкриває для smoke Open WebUI -- `OPENCLAW_OPENWEBUI_PROMPT=...`, щоб override nonce-check prompt, використаний smoke Open WebUI -- `OPENWEBUI_IMAGE=...`, щоб override закріплений тег образу Open WebUI +- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...`, щоб відфільтрувати провайдерів у контейнері +- `OPENCLAW_SKIP_DOCKER_BUILD=1`, щоб повторно використовувати наявний образ `openclaw:local-live` для повторних запусків, яким не потрібна нова збірка +- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`, щоб переконатися, що облікові дані походять зі сховища profile (а не з env) +- `OPENCLAW_OPENWEBUI_MODEL=...`, щоб вибрати модель, яку Gateway надає для smoke Open WebUI +- `OPENCLAW_OPENWEBUI_PROMPT=...`, щоб перевизначити prompt перевірки nonce, який використовує smoke Open WebUI +- `OPENWEBUI_IMAGE=...`, щоб перевизначити pinned-тег образу Open WebUI ## Перевірка документації @@ -940,95 +943,95 @@ Open WebUI, перевіряє, що `/api/models` показує `openclaw/defa ## Офлайнова регресія (безпечна для CI) -Це регресії «реального конвеєра» без реальних провайдерів: +Це регресії «реального pipeline» без реальних провайдерів: -- Виклик інструментів Gateway (mock OpenAI, реальний цикл gateway + agent): `src/gateway/gateway.test.ts` (випадок: "runs a mock OpenAI tool call end-to-end via gateway agent loop") -- Майстер Gateway (WS `wizard.start`/`wizard.next`, запис конфігурації + примусова auth): `src/gateway/gateway.test.ts` (випадок: "runs wizard over ws and writes auth token config") +- Виклик tool у Gateway (mock OpenAI, реальний цикл gateway + agent): `src/gateway/gateway.test.ts` (випадок: "runs a mock OpenAI tool call end-to-end via gateway agent loop") +- Wizard Gateway (WS `wizard.start`/`wizard.next`, записує config + примусову auth): `src/gateway/gateway.test.ts` (випадок: "runs wizard over ws and writes auth token config") -## Оцінювання надійності агента (Skills) +## Оцінювання надійності agent (Skills) -У нас уже є кілька безпечних для CI тестів, які поводяться як «оцінювання надійності агента»: +У нас уже є кілька безпечних для CI тестів, які поводяться як «оцінювання надійності agent»: -- Mock tool-calling через реальний цикл gateway + agent (`src/gateway/gateway.test.ts`). -- Наскрізні потоки майстра, які перевіряють wiring сесії та ефекти конфігурації (`src/gateway/gateway.test.ts`). +- Mock-виклик tool через реальний цикл gateway + agent (`src/gateway/gateway.test.ts`). +- Наскрізні потоки wizard, які перевіряють wiring сесії та ефекти config (`src/gateway/gateway.test.ts`). -Що ще бракує для Skills (див. [Skills](/uk/tools/skills)): +Чого все ще бракує для Skills (див. [Skills](/uk/tools/skills)): -- **Прийняття рішень:** коли Skills перелічено в prompt, чи вибирає агент правильний skill (або уникає нерелевантних)? -- **Відповідність:** чи читає агент `SKILL.md` перед використанням і чи дотримується обов’язкових кроків/args? -- **Контракти робочих процесів:** багатокрокові сценарії, які перевіряють порядок інструментів, перенесення історії сесії та межі sandbox. +- **Вибір рішення:** коли Skills перелічені в prompt, чи вибирає agent правильний skill (або уникає нерелевантних)? +- **Відповідність:** чи читає agent `SKILL.md` перед використанням і чи виконує потрібні кроки/аргументи? +- **Контракти workflow:** багатокрокові сценарії, які перевіряють порядок tool, перенесення історії сесії та межі sandbox. -Майбутні eval мають насамперед залишатися детермінованими: +Майбутні eval спочатку мають залишатися детермінованими: -- Runner сценаріїв із mock-провайдерами для перевірки викликів інструментів + порядку, читання skill-файлів і wiring сесії. -- Невеликий набір сценаріїв, зосереджених на skills (використати чи уникнути, gating, prompt injection). -- Необов’язкові live eval (opt-in, з обмеженням через env) лише після того, як безпечний для CI набір буде готовий. +- Раннер сценаріїв, що використовує mock-провайдерів для перевірки викликів tool + порядку, читання skill-файлів і wiring сесії. +- Невеликий набір сценаріїв, зосереджених на skill (використовувати чи уникати, gating, prompt injection). +- Необов’язкові live eval (opt-in, з керуванням через env) — лише після того, як буде готовий безпечний для CI набір. -## Контрактні тести (форма Plugin і channel) +## Контрактні тести (форма plugin і channel) -Контрактні тести перевіряють, що кожен зареєстрований Plugin і channel відповідає своєму -контракту інтерфейсу. Вони ітеруються по всіх виявлених Plugin і запускають набір -перевірок форми та поведінки. Типовий unit lane `pnpm test` навмисно -пропускає ці спільні seam- і smoke-файли; запускайте контрактні команди явно, +Контрактні тести перевіряють, що кожен зареєстрований plugin і channel відповідає +контракту свого інтерфейсу. Вони проходять по всіх виявлених plugin і запускають +набір перевірок форми та поведінки. Стандартний unit lane `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) -- **setup** - Контракт майстра налаштування +- **plugin** - Базова форма plugin (id, name, capabilities) +- **setup** - Контракт wizard налаштування - **session-binding** - Поведінка прив’язки сесії - **outbound-payload** - Структура payload повідомлення - **inbound** - Обробка вхідних повідомлень -- **actions** - Обробники дій каналу -- **threading** - Обробка ID тредів -- **directory** - API каталогу/ростеру -- **group-policy** - Застосування групової політики +- **actions** - Обробники дій channel +- **threading** - Обробка ID thread +- **directory** - API каталогу/списку учасників +- **group-policy** - Застосування політики групи -### Контракти статусу провайдера +### Контракти статусу provider Розташовані в `src/plugins/contracts/*.contract.test.ts`. -- **status** - Перевірки статусу каналу -- **registry** - Форма реєстру Plugin +- **status** - Probe статусу channel +- **registry** - Форма реєстру plugin -### Контракти провайдерів +### Контракти provider Розташовані в `src/plugins/contracts/*.contract.test.ts`: -- **auth** - Контракт потоку автентифікації -- **auth-choice** - Вибір/селектор автентифікації +- **auth** - Контракт потоку auth +- **auth-choice** - Вибір/selection auth - **catalog** - API каталогу моделей -- **discovery** - Виявлення Plugin -- **loader** - Завантаження Plugin -- **runtime** - Runtime провайдера -- **shape** - Форма/інтерфейс Plugin -- **wizard** - Майстер налаштування +- **discovery** - Виявлення plugin +- **loader** - Завантаження plugin +- **runtime** - Runtime provider +- **shape** - Форма/інтерфейс plugin +- **wizard** - Wizard налаштування ### Коли запускати -- Після зміни export або subpath у plugin-sdk -- Після додавання або зміни channel чи provider Plugin -- Після рефакторингу реєстрації або виявлення Plugin +- Після зміни export або підшляхів plugin-sdk +- Після додавання чи зміни channel або provider plugin +- Після рефакторингу реєстрації plugin або виявлення Контрактні тести запускаються в CI і не потребують реальних API-ключів. ## Додавання регресій (рекомендації) -Коли ви виправляєте проблему провайдера/моделі, виявлену в live: +Коли ви виправляєте проблему provider/model, виявлену в live: -- Якщо можливо, додайте безпечну для CI регресію (mock/stub провайдер або фіксація точної трансформації форми запиту) -- Якщо це за своєю природою лише live-випадок (rate limits, політики auth), залишайте live-тест вузьким і opt-in через env-змінні -- Віддавайте перевагу найменшому шару, який виявляє баг: - - баг перетворення/повторення запиту провайдера → direct models test - - баг у конвеєрі session/history/tool gateway → gateway live smoke або безпечний для CI gateway mock test -- Захисна межа traversal SecretRef: - - `src/secrets/exec-secret-ref-id-parity.test.ts` виводить одну вибіркову ціль для кожного класу SecretRef з метаданих реєстру (`listSecretTargetRegistryEntries()`), а потім перевіряє, що exec id сегментів traversal відхиляються. - - Якщо ви додаєте нове сімейство цілей SecretRef `includeInPlan` у `src/secrets/target-registry-data.ts`, оновіть `classifyTargetClass` у цьому тесті. Тест навмисно падає на некласифікованих target id, щоб нові класи не можна було тихо пропустити. +- За можливості додайте безпечну для CI регресію (mock/stub provider або захопіть точне перетворення форми запиту) +- Якщо проблема за своєю природою лише live (rate limit, політики auth), залишайте live-тест вузьким і opt-in через env-змінні +- Віддавайте перевагу найменшому шару, який виявляє помилку: + - помилка перетворення/повторного відтворення запиту provider → тест direct models + - помилка pipeline Gateway session/history/tool → gateway live smoke або безпечний для CI mock-тест Gateway +- Захисне правило обходу SecretRef: + - `src/secrets/exec-secret-ref-id-parity.test.ts` виводить одну вибіркову ціль для кожного класу SecretRef із метаданих реєстру (`listSecretTargetRegistryEntries()`), а потім перевіряє, що exec id сегмента обходу відхиляються. + - Якщо ви додаєте нову родину цілей SecretRef `includeInPlan` у `src/secrets/target-registry-data.ts`, оновіть `classifyTargetClass` у цьому тесті. Тест навмисно падає на некласифікованих target id, щоб нові класи не можна було тихо пропустити. diff --git a/docs/uk/providers/index.md b/docs/uk/providers/index.md index f4d906f55..0f748ddaa 100644 --- a/docs/uk/providers/index.md +++ b/docs/uk/providers/index.md @@ -1,29 +1,29 @@ --- read_when: - Ви хочете вибрати постачальника моделей - - Вам потрібен швидкий огляд підтримуваних бекендів LLM -summary: Постачальники моделей (LLM), які підтримуються OpenClaw + - Вам потрібен короткий огляд підтримуваних бекендів LLM +summary: Постачальники моделей (LLM), що підтримуються OpenClaw title: Каталог постачальників x-i18n: - generated_at: "2026-04-13T07:24:23Z" + generated_at: "2026-04-21T21:27:20Z" model: gpt-5.4 provider: openai - source_hash: 3bc682d008119719826f71f74959ab32bedf14214459f5e6ac9cb70371d3c540 + source_hash: 7d77e5da93d71c48ea97460c6be56fbbe8279d9240a8101e1b35fdafb657737e source_path: providers/index.md workflow: 15 --- # Постачальники моделей -OpenClaw може використовувати багато постачальників LLM. Виберіть постачальника, пройдіть автентифікацію, а потім установіть -модель за замовчуванням як `provider/model`. +OpenClaw може використовувати багато постачальників LLM. Виберіть постачальника, пройдіть автентифікацію, а потім задайте +модель за замовчуванням у форматі `provider/model`. -Шукаєте документацію щодо каналів чату (WhatsApp/Telegram/Discord/Slack/Mattermost (Plugin)/тощо)? Див. [Channels](/uk/channels). +Шукаєте документацію для чат-каналів (WhatsApp/Telegram/Discord/Slack/Mattermost (plugin)/тощо)? Див. [Channels](/uk/channels). ## Швидкий старт 1. Пройдіть автентифікацію у постачальника (зазвичай через `openclaw onboard`). -2. Установіть модель за замовчуванням: +2. Задайте модель за замовчуванням: ```json5 { @@ -37,21 +37,21 @@ OpenClaw може використовувати багато постачаль - [Amazon Bedrock](/uk/providers/bedrock) - [Anthropic (API + Claude CLI)](/uk/providers/anthropic) - [Arcee AI (моделі Trinity)](/uk/providers/arcee) -- [BytePlus (міжнародний)](/uk/concepts/model-providers#byteplus-international) +- [BytePlus (міжнародна версія)](/uk/concepts/model-providers#byteplus-international) - [Chutes](/uk/providers/chutes) -- [ComfyUI](/uk/providers/comfy) - [Cloudflare AI Gateway](/uk/providers/cloudflare-ai-gateway) +- [ComfyUI](/uk/providers/comfy) - [DeepSeek](/uk/providers/deepseek) - [fal](/uk/providers/fal) - [Fireworks](/uk/providers/fireworks) - [GitHub Copilot](/uk/providers/github-copilot) -- [моделі GLM](/uk/providers/glm) +- [Моделі GLM](/uk/providers/glm) - [Google (Gemini)](/uk/providers/google) -- [Groq (LPU inference)](/uk/providers/groq) -- [Hugging Face (Inference)](/uk/providers/huggingface) +- [Groq (LPU-інференс)](/uk/providers/groq) +- [Hugging Face (інференс)](/uk/providers/huggingface) - [inferrs (локальні моделі)](/uk/providers/inferrs) - [Kilocode](/uk/providers/kilocode) -- [LiteLLM (уніфікований Gateway)](/uk/providers/litellm) +- [LiteLLM (уніфікований шлюз)](/uk/providers/litellm) - [LM Studio (локальні моделі)](/uk/providers/lmstudio) - [MiniMax](/uk/providers/minimax) - [Mistral](/uk/providers/mistral) @@ -70,28 +70,29 @@ OpenClaw може використовувати багато постачаль - [StepFun](/uk/providers/stepfun) - [Synthetic](/uk/providers/synthetic) - [Together AI](/uk/providers/together) -- [Venice (Venice AI, з акцентом на конфіденційність)](/uk/providers/venice) +- [Venice (Venice AI, з акцентом на приватність)](/uk/providers/venice) - [Vercel AI Gateway](/uk/providers/vercel-ai-gateway) -- [Vydra](/uk/providers/vydra) - [vLLM (локальні моделі)](/uk/providers/vllm) - [Volcengine (Doubao)](/uk/providers/volcengine) +- [Vydra](/uk/providers/vydra) - [xAI](/uk/providers/xai) - [Xiaomi](/uk/providers/xiaomi) - [Z.AI](/uk/providers/zai) -## Спільні сторінки огляду +## Спільні оглядові сторінки -- [Додаткові вбудовані варіанти](/uk/providers/models#additional-bundled-provider-variants) - Anthropic Vertex, Copilot Proxy і Gemini CLI OAuth -- [Генерація зображень](/uk/tools/image-generation) - спільний інструмент `image_generate`, вибір постачальника та перемикання при відмові -- [Генерація музики](/uk/tools/music-generation) - спільний інструмент `music_generate`, вибір постачальника та перемикання при відмові -- [Генерація відео](/uk/tools/video-generation) - спільний інструмент `video_generate`, вибір постачальника та перемикання при відмові +- [Додаткові вбудовані варіанти](/uk/providers/models#additional-bundled-provider-variants) - Anthropic Vertex, Copilot Proxy та Gemini CLI OAuth +- [Генерація зображень](/uk/tools/image-generation) - Спільний інструмент `image_generate`, вибір постачальника та failover +- [Генерація музики](/uk/tools/music-generation) - Спільний інструмент `music_generate`, вибір постачальника та failover +- [Генерація відео](/uk/tools/video-generation) - Спільний інструмент `video_generate`, вибір постачальника та failover -## Постачальники транскрибування +## Постачальники транскрипції -- [Deepgram (транскрибування аудіо)](/uk/providers/deepgram) +- [Deepgram (транскрипція аудіо)](/uk/providers/deepgram) ## Інструменти спільноти - [Claude Max API Proxy](/uk/providers/claude-max-api-proxy) - Проксі спільноти для облікових даних підписки Claude (перед використанням перевірте політику/умови Anthropic) -Повний каталог постачальників (xAI, Groq, Mistral тощо) і розширену конфігурацію див. у розділі [Постачальники моделей](/uk/concepts/model-providers). +Щоб переглянути повний каталог постачальників (xAI, Groq, Mistral тощо) і розширену конфігурацію, +див. [Постачальники моделей](/uk/concepts/model-providers). diff --git a/docs/uk/reference/test.md b/docs/uk/reference/test.md index 2f4f54a8c..9b40e8eb5 100644 --- a/docs/uk/reference/test.md +++ b/docs/uk/reference/test.md @@ -1,13 +1,13 @@ --- read_when: - Запуск або виправлення тестів -summary: Як запускати тести локально (`vitest`) і коли використовувати режими force/coverage +summary: Як запускати тести локально (`vitest`) і коли використовувати режими `force`/`coverage` title: Тести x-i18n: - generated_at: "2026-04-20T22:38:11Z" + generated_at: "2026-04-21T21:27:24Z" model: gpt-5.4 provider: openai - source_hash: 04bdcbc3a1121f4c460cd9060f581a49dfc6fa65c4b9ddb9c87db81c4a535166 + source_hash: ed665840ef2c7728da8ec923eb3ea2878d9b20a841cb2fe4116a7f6334567b8e source_path: reference/test.md workflow: 15 --- @@ -16,35 +16,35 @@ x-i18n: - Повний набір для тестування (набори тестів, live, Docker): [Тестування](/uk/help/testing) -- `pnpm test:force`: Завершує будь-який завислий процес gateway, який утримує стандартний control port, а потім запускає повний набір Vitest з ізольованим портом gateway, щоб серверні тести не конфліктували із запущеним екземпляром. Використовуйте це, якщо попередній запуск gateway залишив зайнятим порт 18789. -- `pnpm test:coverage`: Запускає набір unit-тестів із покриттям V8 (через `vitest.unit.config.ts`). Це перевірка покриття unit-тестів для завантажених файлів, а не загальнорепозиторне покриття всіх файлів. Порогові значення: 70% для lines/functions/statements і 55% для branches. Оскільки `coverage.all` має значення false, перевірка вимірює файли, завантажені набором unit coverage, замість того щоб вважати всі вихідні файли розділених lane непокритими. -- `pnpm test:coverage:changed`: Запускає unit coverage лише для файлів, змінених відносно `origin/main`. -- `pnpm test:changed`: розгортає змінені git-шляхи у scoped lane Vitest, коли diff торкається лише routable source/test файлів. Зміни конфігурації/налаштування все одно повертаються до native root projects run, щоб за потреби зміни wiring запускали ширший повторний прогін. -- `pnpm changed:lanes`: показує архітектурні lane, які запускаються diff відносно `origin/main`. -- `pnpm check:changed`: запускає smart changed gate для diff відносно `origin/main`. Він запускає core-роботу з core test lane, роботу extensions — з extension test lane, зміни лише в тестах — тільки з test typecheck/tests, а також розширює зміни в публічному Plugin SDK або plugin-contract до валідації extensions. -- `pnpm test`: маршрутизує явні цілі файлів/директорій через scoped lane Vitest. Запуски без цілі використовують фіксовані shard groups і розгортаються до leaf config для локального паралельного виконання; група extension завжди розгортається до per-extension shard config, а не до одного великого root-project process. -- Повні запуски та запуски extension shard оновлюють локальні дані таймінгів у `.artifacts/vitest-shard-timings.json`; наступні запуски використовують ці таймінги для балансування повільних і швидких shard. Встановіть `OPENCLAW_TEST_PROJECTS_TIMINGS=0`, щоб ігнорувати локальний артефакт таймінгів. -- Вибрані файли тестів `plugin-sdk` і `commands` тепер маршрутизуються через окремі легкі lane, які зберігають лише `test/setup.ts`, залишаючи resource-heavy випадки на їхніх наявних lane. -- Вибрані вихідні helper-файли `plugin-sdk` і `commands` також маплять `pnpm test:changed` на явні sibling-тести в цих легких lane, щоб дрібні зміни helper не перезапускали важкі набори, що спираються на runtime. -- `auto-reply` тепер також розділено на три окремі config (`core`, `top-level`, `reply`), щоб harness для reply не домінував над легшими top-level тестами status/token/helper. -- Базова конфігурація Vitest тепер за замовчуванням використовує `pool: "threads"` і `isolate: false`, а спільний non-isolated runner увімкнено в конфігураціях усього репозиторію. +- `pnpm test:force`: Завершує будь-який завислий процес gateway, що утримує типовий порт керування, а потім запускає повний набір Vitest з ізольованим портом gateway, щоб тести сервера не конфліктували із запущеним екземпляром. Використовуйте це, коли попередній запуск gateway залишив зайнятим порт 18789. +- `pnpm test:coverage`: Запускає набір unit-тестів із покриттям V8 (через `vitest.unit.config.ts`). Це перевірка покриття unit-тестів для завантажених файлів, а не покриття всіх файлів у всьому репозиторії. Порогові значення: 70% для lines/functions/statements і 55% для branches. Оскільки `coverage.all` має значення false, перевірка вимірює файли, завантажені набором unit-тестів із покриттям, замість того щоб вважати всі файли вихідного коду у розбитих lane непокритими. +- `pnpm test:coverage:changed`: Запускає unit-покриття лише для файлів, змінених відносно `origin/main`. +- `pnpm test:changed`: розгортає змінені git-шляхи в scoped lane Vitest, коли diff зачіпає лише routable файли вихідного коду/тестів. Зміни конфігурації/налаштування все одно повертаються до нативного запуску root projects, щоб за потреби зміни у зв’язуванні запускали ширший прогін. +- `pnpm changed:lanes`: показує архітектурні lane, що запускаються diff відносно `origin/main`. +- `pnpm check:changed`: запускає розумну перевірку changed gate для diff відносно `origin/main`. Вона запускає core-роботу разом із core test lanes, роботу extension — разом із extension test lanes, зміни лише в тестах — лише з test typecheck/tests, розширює зміни публічного Plugin SDK або plugin-contract до перевірки extension, а також залишає version bump лише в release metadata на цільових перевірках version/config/root-dependency. +- `pnpm test`: маршрутизує явні цілі файлів/каталогів через scoped lane Vitest. Запуски без цілі використовують фіксовані shard-групи й розгортаються до leaf configs для локального паралельного виконання; група extension завжди розгортається до per-extension shard configs, а не до одного великого процесу root-project. +- Повні запуски та запуски extension shard оновлюють локальні дані часу в `.artifacts/vitest-shard-timings.json`; наступні запуски використовують ці значення часу для балансування повільних і швидких shard. Встановіть `OPENCLAW_TEST_PROJECTS_TIMINGS=0`, щоб ігнорувати локальний артефакт часу. +- Вибрані тестові файли `plugin-sdk` і `commands` тепер маршрутизуються через окремі легкі lane, які зберігають лише `test/setup.ts`, залишаючи важкі з погляду runtime кейси в їхніх наявних lane. +- Вибрані допоміжні файли вихідного коду `plugin-sdk` і `commands` також зіставляють `pnpm test:changed` з явними sibling tests у цих легких lane, щоб невеликі зміни helper не перезапускали важкі набори, прив’язані до runtime. +- `auto-reply` тепер також розбивається на три окремі конфігурації (`core`, `top-level`, `reply`), щоб harness для reply не домінував над легшими top-level тестами status/token/helper. +- Базова конфігурація Vitest тепер типово використовує `pool: "threads"` і `isolate: false`, а спільний неізольований runner увімкнено в конфігураціях усього репозиторію. - `pnpm test:channels` запускає `vitest.channels.config.ts`. -- `pnpm test:extensions` і `pnpm test extensions` запускають усі shard extensions/plugins. Важкі channel extensions і OpenAI працюють як окремі shard; інші групи extensions залишаються згрупованими. Використовуйте `pnpm test extensions/` для одного lane вбудованого Plugin. -- `pnpm test:perf:imports`: вмикає звітність Vitest про import-duration та import-breakdown, при цьому все ще використовує маршрутизацію scoped lane для явних цілей файлів/директорій. -- `pnpm test:perf:imports:changed`: те саме профілювання import, але лише для файлів, змінених відносно `origin/main`. -- `pnpm test:perf:changed:bench -- --ref ` порівнює продуктивність маршрутизованого режиму changed із native root-project run для того самого закоміченого git diff. -- `pnpm test:perf:changed:bench -- --worktree` порівнює продуктивність поточного набору змін у worktree без попереднього коміту. -- `pnpm test:perf:profile:main`: записує CPU profile для головного потоку Vitest (`.artifacts/vitest-main-profile`). -- `pnpm test:perf:profile:runner`: записує CPU + heap profiles для unit runner (`.artifacts/vitest-runner-profile`). -- Інтеграція Gateway: opt-in через `OPENCLAW_TEST_INCLUDE_GATEWAY=1 pnpm test` або `pnpm test:gateway`. -- `pnpm test:e2e`: запускає наскрізні smoke-тести gateway (парування multi-instance WS/HTTP/node). За замовчуванням використовує `threads` + `isolate: false` з adaptive workers у `vitest.e2e.config.ts`; налаштовуйте через `OPENCLAW_E2E_WORKERS=` і встановіть `OPENCLAW_E2E_VERBOSE=1` для докладних логів. -- `pnpm test:live`: запускає live-тести provider (minimax/zai). Потрібні API keys і `LIVE=1` (або provider-specific `*_LIVE_TEST=1`) для зняття skip. -- `pnpm test:docker:openwebui`: запускає Dockerized OpenClaw + Open WebUI, виконує вхід через Open WebUI, перевіряє `/api/models`, а потім запускає реальний проксійований чат через `/api/chat/completions`. Потребує придатного live model key (наприклад, OpenAI у `~/.profile`), завантажує зовнішній образ Open WebUI і не вважається стабільним для CI так, як звичайні unit/e2e набори. -- `pnpm test:docker:mcp-channels`: запускає seeded контейнер Gateway і другий контейнер клієнта, який запускає `openclaw mcp serve`, а потім перевіряє routed conversation discovery, читання transcript, metadata вкладень, поведінку live event queue, маршрутизацію outbound send і сповіщення про channel + permissions у стилі Claude через реальний stdio bridge. Перевірка сповіщень Claude читає сирі stdio MCP frames безпосередньо, щоб smoke-тест відображав те, що bridge реально надсилає. +- `pnpm test:extensions` і `pnpm test extensions` запускають усі shard extension/plugin. Важкі channel extensions і OpenAI запускаються як окремі shard; інші групи extension залишаються згрупованими. Використовуйте `pnpm test extensions/` для одного lane вбудованого plugin. +- `pnpm test:perf:imports`: вмикає звіти Vitest про тривалість імпорту та деталізацію імпортів, при цьому все ще використовує маршрутизацію scoped lane для явних цілей файлів/каталогів. +- `pnpm test:perf:imports:changed`: те саме профілювання імпортів, але лише для файлів, змінених відносно `origin/main`. +- `pnpm test:perf:changed:bench -- --ref ` виконує benchmark маршрутизованого changed-режиму проти нативного запуску root-project для того самого закоміченого git diff. +- `pnpm test:perf:changed:bench -- --worktree` виконує benchmark поточного набору змін у worktree без попереднього коміту. +- `pnpm test:perf:profile:main`: записує CPU-профіль для головного потоку Vitest (`.artifacts/vitest-main-profile`). +- `pnpm test:perf:profile:runner`: записує CPU + heap-профілі для unit runner (`.artifacts/vitest-runner-profile`). +- Інтеграція Gateway: вмикається через `OPENCLAW_TEST_INCLUDE_GATEWAY=1 pnpm test` або `pnpm test:gateway`. +- `pnpm test:e2e`: запускає smoke-тести gateway end-to-end (парування multi-instance WS/HTTP/node). Типово використовує `threads` + `isolate: false` з адаптивною кількістю workers у `vitest.e2e.config.ts`; налаштовуйте через `OPENCLAW_E2E_WORKERS=` і встановіть `OPENCLAW_E2E_VERBOSE=1` для докладних журналів. +- `pnpm test:live`: запускає live-тести provider (minimax/zai). Потребує API-ключів і `LIVE=1` (або provider-specific `*_LIVE_TEST=1`) для зняття пропуску. +- `pnpm test:docker:openwebui`: запускає Dockerized OpenClaw + Open WebUI, виконує вхід через Open WebUI, перевіряє `/api/models`, а потім запускає реальний проксійований чат через `/api/chat/completions`. Потребує придатного ключа live model (наприклад, OpenAI у `~/.profile`), завантажує зовнішній образ Open WebUI і не вважається настільки стабільним для CI, як звичайні набори unit/e2e. +- `pnpm test:docker:mcp-channels`: запускає seeded контейнер Gateway і другий контейнер-клієнт, який запускає `openclaw mcp serve`, а потім перевіряє routed conversation discovery, читання transcript, метадані вкладень, поведінку черги live events, outbound send routing і сповіщення про channel + permissions у стилі Claude через реальний міст stdio. Перевірка сповіщень Claude читає сирі stdio MCP-кадри безпосередньо, щоб smoke-тест відображав те, що міст справді надсилає. ## Локальний PR gate -Для локальних перевірок перед злиттям/проходження gate PR виконайте: +Для локальних перевірок перед приземленням PR/gate запустіть: - `pnpm check:changed` - `pnpm check` @@ -53,27 +53,27 @@ x-i18n: - `pnpm test` - `pnpm check:docs` -Якщо `pnpm test` дає flaky-результат на навантаженому хості, перезапустіть один раз, перш ніж вважати це регресією, а потім ізолюйте через `pnpm test `. Для хостів з обмеженою пам’яттю використовуйте: +Якщо `pnpm test` дає флейк на навантаженому хості, перезапустіть один раз, перш ніж вважати це регресією, а потім ізолюйте через `pnpm test `. Для хостів з обмеженою пам’яттю використовуйте: - `OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test` - `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/tmp/openclaw-vitest-cache pnpm test:changed` -## Бенч затримки моделі (локальні ключі) +## Benchmark затримки моделі (локальні ключі) Скрипт: [`scripts/bench-model.ts`](https://github.com/openclaw/openclaw/blob/main/scripts/bench-model.ts) Використання: - `source ~/.profile && pnpm tsx scripts/bench-model.ts --runs 10` -- Необов’язкові змінні середовища: `MINIMAX_API_KEY`, `MINIMAX_BASE_URL`, `MINIMAX_MODEL`, `ANTHROPIC_API_KEY` -- Типовий prompt: “Reply with a single word: ok. No punctuation or extra text.” +- Необов’язкові env: `MINIMAX_API_KEY`, `MINIMAX_BASE_URL`, `MINIMAX_MODEL`, `ANTHROPIC_API_KEY` +- Типовий prompt: “Відповідай одним словом: ok. Без розділових знаків або додаткового тексту.” Останній запуск (2025-12-31, 20 запусків): - minimax median 1279ms (min 1114, max 2431) - opus median 2454ms (min 1224, max 3170) -## Бенч запуску CLI +## Benchmark запуску CLI Скрипт: [`scripts/bench-cli-startup.ts`](https://github.com/openclaw/openclaw/blob/main/scripts/bench-cli-startup.ts) @@ -94,29 +94,29 @@ x-i18n: - `pnpm tsx scripts/bench-cli-startup.ts --preset real --cpu-prof-dir .artifacts/cli-cpu` - `pnpm tsx scripts/bench-cli-startup.ts --json` -Пресети: +Набори preset: - `startup`: `--version`, `--help`, `health`, `health --json`, `status --json`, `status` - `real`: `health`, `status`, `status --json`, `sessions`, `sessions --json`, `agents list --json`, `gateway status`, `gateway status --json`, `gateway health --json`, `config get gateway.port` -- `all`: обидва пресети +- `all`: обидва набори preset -Вивід містить `sampleCount`, avg, p50, p95, min/max, розподіл exit-code/signal і зведення max RSS для кожної команди. Необов’язкові `--cpu-prof-dir` / `--heap-prof-dir` записують V8 profiles для кожного запуску, тож збір таймінгів і profiles використовує той самий harness. +Вивід містить `sampleCount`, avg, p50, p95, min/max, розподіл exit-code/signal і підсумки max RSS для кожної команди. Необов’язкові `--cpu-prof-dir` / `--heap-prof-dir` записують V8-профілі для кожного запуску, щоб вимірювання часу та збирання профілів використовували один і той самий harness. -Правила збереження виводу: +Умовності для збереженого виводу: - `pnpm test:startup:bench:smoke` записує цільовий smoke-артефакт у `.artifacts/cli-startup-bench-smoke.json` -- `pnpm test:startup:bench:save` записує артефакт повного набору в `.artifacts/cli-startup-bench-all.json` з `runs=5` і `warmup=1` -- `pnpm test:startup:bench:update` оновлює закомічений baseline fixture у `test/fixtures/cli-startup-bench.json` з `runs=5` і `warmup=1` +- `pnpm test:startup:bench:save` записує артефакт повного набору в `.artifacts/cli-startup-bench-all.json`, використовуючи `runs=5` і `warmup=1` +- `pnpm test:startup:bench:update` оновлює закомічений baseline fixture у `test/fixtures/cli-startup-bench.json`, використовуючи `runs=5` і `warmup=1` Закомічений fixture: - `test/fixtures/cli-startup-bench.json` -- Оновіть через `pnpm test:startup:bench:update` -- Порівняйте поточні результати з fixture через `pnpm test:startup:bench:check` +- Оновлення через `pnpm test:startup:bench:update` +- Порівняння поточних результатів із fixture через `pnpm test:startup:bench:check` ## Onboarding E2E (Docker) -Docker є необов’язковим; це потрібно лише для containerized smoke-тестів onboarding. +Docker необов’язковий; це потрібно лише для containerized smoke-тестів onboarding. Повний cold-start flow у чистому Linux-контейнері: @@ -124,11 +124,11 @@ Docker є необов’язковим; це потрібно лише для c scripts/e2e/onboard-docker.sh ``` -Цей скрипт керує інтерактивним wizard через pseudo-tty, перевіряє файли config/workspace/session, а потім запускає gateway і виконує `openclaw health`. +Цей скрипт проходить інтерактивний майстер через pseudo-tty, перевіряє файли config/workspace/session, потім запускає gateway і виконує `openclaw health`. -## QR import smoke (Docker) +## Smoke-тест імпорту QR (Docker) -Гарантує, що `qrcode-terminal` завантажується в підтримуваних Docker runtime Node (Node 24 за замовчуванням, Node 22 сумісний): +Гарантує, що `qrcode-terminal` завантажується в підтримуваних runtime Node у Docker (типово Node 24, сумісність із Node 22): ```bash pnpm test:docker:qr