From aa205d3f3916e367352deb0731c7976e2eee0f8a Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Tue, 21 Apr 2026 20:44:04 +0000 Subject: [PATCH] chore(i18n): refresh uk translations --- docs/uk/channels/msteams.md | 484 ++++---- docs/uk/channels/qqbot.md | 109 +- docs/uk/channels/telegram.md | 531 ++++----- docs/uk/plan/ui-channels.md | 261 +++++ docs/uk/plugins/architecture.md | 1401 ++++++++++++----------- docs/uk/plugins/manifest.md | 547 ++++----- docs/uk/plugins/message-presentation.md | 344 ++++++ docs/uk/plugins/sdk-overview.md | 530 ++++----- docs/uk/plugins/skill-workshop.md | 737 ++++++++++++ docs/uk/tools/skills.md | 308 ++--- docs/uk/tools/web.md | 232 ++-- 11 files changed, 3458 insertions(+), 2026 deletions(-) create mode 100644 docs/uk/plan/ui-channels.md create mode 100644 docs/uk/plugins/message-presentation.md create mode 100644 docs/uk/plugins/skill-workshop.md diff --git a/docs/uk/channels/msteams.md b/docs/uk/channels/msteams.md index a8e73c2f3..47da116f9 100644 --- a/docs/uk/channels/msteams.md +++ b/docs/uk/channels/msteams.md @@ -1,28 +1,28 @@ --- read_when: - - Робота над функціями каналу Microsoft Teams -summary: Статус підтримки бота Microsoft Teams, можливості та налаштування + - Працюємо над функціями каналу Microsoft Teams +summary: Статус підтримки бота Microsoft Teams, можливості та конфігурація title: Microsoft Teams x-i18n: - generated_at: "2026-04-11T18:30:42Z" + generated_at: "2026-04-21T20:37:36Z" model: gpt-5.4 provider: openai - source_hash: 3e6841a618fb030e4c2029b3652d45dedd516392e2ae17309ff46b93648ffb79 + source_hash: ed973d8948bc5c5b44f5bc28f361e883389ececc70403c6631fb18ee1254d542 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 постачається як вбудований плагін у поточних релізах OpenClaw, тож у звичайній пакетованій збірці окреме встановлення не потрібне. +Microsoft Teams постачається як вбудований Plugin у поточних релізах OpenClaw, тому в звичайній пакетованій збірці окреме встановлення не потрібне. Якщо ви використовуєте старішу збірку або власне встановлення без вбудованого Teams, встановіть його вручну: @@ -31,23 +31,23 @@ Microsoft Teams постачається як вбудований плагін openclaw plugins install @openclaw/msteams ``` -Локальний checkout (під час запуску з git-репозиторію): +Локальний checkout (коли запускаєте з git-репозиторію): ```bash openclaw plugins install ./path/to/local/msteams-plugin ``` -Докладніше: [Плагіни](/uk/tools/plugin) +Докладніше: [Plugins](/uk/tools/plugin) ## Швидке налаштування (для початківців) -1. Переконайтеся, що плагін Microsoft Teams доступний. - - У поточних пакетованих релізах OpenClaw він уже вбудований. +1. Переконайтеся, що Plugin Microsoft Teams доступний. + - Поточні пакетовані релізи OpenClaw уже містять його вбудованим. - У старіших/власних встановленнях його можна додати вручну командами вище. 2. Створіть **Azure Bot** (App ID + client secret + tenant ID). -3. Налаштуйте OpenClaw із цими обліковими даними. -4. Відкрийте `/api/messages` (типово порт 3978) через публічну URL-адресу або тунель. -5. Установіть пакет застосунку Teams і запустіть gateway. +3. Налаштуйте OpenClaw з цими обліковими даними. +4. Відкрийте `/api/messages` (типово порт 3978) через публічний URL або тунель. +5. Встановіть пакет застосунку Teams і запустіть Gateway. Мінімальна конфігурація (client secret): @@ -67,17 +67,17 @@ 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`). Вимкнути можна так: @@ -87,21 +87,21 @@ openclaw plugins install ./path/to/local/msteams-plugin } ``` -## Керування доступом (DM + групи) +## Контроль доступу (DM + групи) -**Доступ у DM** +**Доступ до DM** -- Типово: `channels.msteams.dmPolicy = "pairing"`. Невідомі відправники ігноруються до схвалення. +- Типово: `channels.msteams.dmPolicy = "pairing"`. Невідомі відправники ігноруються, доки їх не буде схвалено. - `channels.msteams.allowFrom` має використовувати стабільні AAD object ID. -- UPN/display name можуть змінюватися; пряме зіставлення типово вимкнене й вмикається лише через `channels.msteams.dangerouslyAllowNameMatching: true`. -- Майстер налаштування може зіставляти імена з ID через Microsoft Graph, якщо облікові дані це дозволяють. +- UPN/display name є змінними; пряме зіставлення типово вимкнене й вмикається лише через `channels.msteams.dangerouslyAllowNameMatching: true`. +- Майстер налаштування може зіставляти імена з ID через Microsoft Graph, якщо це дозволяють облікові дані. **Груповий доступ** -- Типово: `channels.msteams.groupPolicy = "allowlist"` (заблоковано, доки ви не додасте `groupAllowFrom`). Використовуйте `channels.defaults.groupPolicy`, щоб перевизначити типове значення, якщо його не задано. -- `channels.msteams.groupAllowFrom` визначає, які відправники можуть ініціювати дії в групових чатах/каналах (із fallback на `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 +118,12 @@ openclaw plugins install ./path/to/local/msteams-plugin **Teams + allowlist каналів** -- Обмежуйте відповіді в групах/каналах, перелічивши teams і channels у `channels.msteams.teams`. -- Як ключі слід використовувати стабільні team ID і channel conversation ID. -- Коли `groupPolicy="allowlist"` і присутній teams allowlist, приймаються лише перелічені teams/channels (із вимогою згадки). -- Майстер налаштування приймає записи `Team/Channel` і зберігає їх за вас. -- Під час запуску OpenClaw зіставляє імена team/channel і user в allowlist з ID (коли це дозволяють дозволи Graph) - і записує це зіставлення в лог; невизначені імена team/channel зберігаються як введені, але типово ігноруються для маршрутизації, якщо не ввімкнено `channels.msteams.dangerouslyAllowNameMatching: true`. +- Обмежуйте відповіді в групах/каналах, перелічивши команди 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`. Приклад: @@ -146,13 +146,13 @@ openclaw plugins install ./path/to/local/msteams-plugin ## Як це працює -1. Переконайтеся, що плагін Microsoft Teams доступний. - - У поточних пакетованих релізах OpenClaw він уже вбудований. +1. Переконайтеся, що Plugin Microsoft Teams доступний. + - Поточні пакетовані релізи OpenClaw уже містять його вбудованим. - У старіших/власних встановленнях його можна додати вручну командами вище. 2. Створіть **Azure Bot** (App ID + secret + tenant ID). -3. Зберіть **пакет застосунку Teams**, який посилається на бота та включає наведені нижче дозволи RSC. -4. Завантажте/встановіть застосунок Teams у команду (або в особисту область для DM). -5. Налаштуйте `msteams` у `~/.openclaw/openclaw.json` (або змінні середовища) і запустіть gateway. +3. Створіть **пакет застосунку Teams**, який посилається на бота й містить наведені нижче дозволи RSC. +4. Завантажте/встановіть застосунок Teams у команду (або в особистий scope для DM). +5. Налаштуйте `msteams` у `~/.openclaw/openclaw.json` (або через env vars) і запустіть Gateway. 6. Gateway типово слухає webhook-трафік Bot Framework на `/api/messages`. ## Налаштування Azure Bot (передумови) @@ -167,30 +167,30 @@ openclaw plugins install ./path/to/local/msteams-plugin | Поле | Значення | | ------------------ | -------------------------------------------------------- | | **Bot handle** | Назва вашого бота, наприклад `openclaw-msteams` (має бути унікальною) | - | **Subscription** | Виберіть вашу Azure subscription | + | **Subscription** | Виберіть свою підписку Azure | | **Resource group** | Створіть нову або використайте наявну | - | **Pricing tier** | **Free** для розробки/тестування | + | **Pricing tier** | **Free** для dev/тестування | | **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: Отримайте облікові дані 1. Перейдіть до ресурсу Azure Bot → **Configuration** 2. Скопіюйте **Microsoft App ID** → це ваш `appId` 3. Натисніть **Manage Password** → перейдіть до App Registration -4. У **Certificates & secrets** → **New client secret** → скопіюйте **Value** → це ваш `appPassword` +4. У розділі **Certificates & secrets** → **New client secret** → скопіюйте **Value** → це ваш `appPassword` 5. Перейдіть до **Overview** → скопіюйте **Directory (tenant) ID** → це ваш `tenantId` -### Крок 3: Налаштуйте endpoint повідомлень +### Крок 3: Налаштуйте Messaging endpoint 1. У Azure Bot → **Configuration** -2. Установіть **Messaging endpoint** на вашу webhook URL-адресу: +2. Установіть **Messaging endpoint** на URL вашого webhook: - Production: `https://your-domain.com/api/messages` - - Локальна розробка: використовуйте тунель (див. [Локальна розробка](#local-development-tunneling) нижче) + - Локальна розробка: використайте тунель (див. [Локальна розробка](#local-development-tunneling) нижче) ### Крок 4: Увімкніть канал Teams @@ -198,7 +198,7 @@ openclaw plugins install ./path/to/local/msteams-plugin 2. Натисніть **Microsoft Teams** → Configure → Save 3. Прийміть Terms of Service -## Federated Authentication (сертифікат + Managed Identity) +## Federated Authentication (Certificate + Managed Identity) > Додано в 2026.3.24 @@ -206,7 +206,7 @@ openclaw plugins install ./path/to/local/msteams-plugin ### Варіант A: автентифікація на основі сертифіката -Використовуйте PEM-сертифікат, зареєстрований у реєстрації застосунку Entra ID. +Використовуйте PEM-сертифікат, зареєстрований у вашому застосунку Entra ID app registration. **Налаштування:** @@ -230,26 +230,26 @@ openclaw plugins install ./path/to/local/msteams-plugin } ``` -**Змінні середовища:** +**Env vars:** - `MSTEAMS_AUTH_TYPE=federated` - `MSTEAMS_CERTIFICATE_PATH=/path/to/cert.pem` ### Варіант B: Azure Managed Identity -Використовуйте Azure Managed Identity для автентифікації без пароля. Це ідеально підходить для розгортань в інфраструктурі Azure (AKS, App Service, Azure VM), де доступна managed identity. +Використовуйте Azure Managed Identity для автентифікації без пароля. Це ідеально для розгортань в інфраструктурі Azure (AKS, App Service, Azure VMs), де доступна managed identity. **Як це працює:** -1. Bot pod/VM має managed identity (system-assigned або user-assigned). -2. **Federated identity credential** пов’язує managed identity з реєстрацією застосунку Entra ID. -3. Під час виконання OpenClaw використовує `@azure/identity`, щоб отримати токени з endpoint Azure IMDS (`169.254.169.254`). +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 для автентифікації бота. **Передумови:** - Інфраструктура Azure з увімкненою managed identity (AKS workload identity, App Service, VM) -- Створений federated identity credential у реєстрації застосунку Entra ID +- Створений federated identity credential у застосунку Entra ID app registration - Мережевий доступ до IMDS (`169.254.169.254:80`) з pod/VM **Конфігурація (system-assigned managed identity):** @@ -287,7 +287,7 @@ openclaw plugins install ./path/to/local/msteams-plugin } ``` -**Змінні середовища:** +**Env vars:** - `MSTEAMS_AUTH_TYPE=federated` - `MSTEAMS_USE_MANAGED_IDENTITY=true` @@ -295,10 +295,10 @@ openclaw plugins install ./path/to/local/msteams-plugin ### Налаштування AKS Workload Identity -Для розгортань AKS із використанням workload identity: +Для розгортань AKS із workload identity: -1. **Увімкніть workload identity** у вашому кластері AKS. -2. **Створіть federated identity credential** у реєстрації застосунку Entra ID: +1. **Увімкніть workload identity** у своєму кластері AKS. +2. **Створіть federated identity credential** у застосунку Entra ID app registration: ```bash az ad app federated-credential create --id --parameters '{ @@ -309,7 +309,7 @@ openclaw plugins install ./path/to/local/msteams-plugin }' ``` -3. **Додайте анотацію до Kubernetes service account** з app client ID: +3. **Додайте анотацію до service account Kubernetes** із client ID застосунку: ```yaml apiVersion: v1 @@ -320,7 +320,7 @@ openclaw plugins install ./path/to/local/msteams-plugin azure.workload.identity/client-id: "" ``` -4. **Додайте мітку pod** для ін’єкції workload identity: +4. **Додайте label до pod** для інʼєкції workload identity: ```yaml metadata: @@ -328,21 +328,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. ### Порівняння типів автентифікації -| Метод | Конфігурація | Переваги | Недоліки | -| -------------------- | ---------------------------------------------- | ----------------------------------- | -------------------------------------- | -| **Client secret** | `appPassword` | Просте налаштування | Потрібна ротація секретів, менш безпечно | -| **Certificate** | `authType: "federated"` + `certificatePath` | Немає спільного секрету в мережі | Додаткові витрати на керування сертифікатами | -| **Managed Identity** | `authType: "federated"` + `useManagedIdentity` | Без пароля, не потрібно керувати секретами | Потрібна інфраструктура Azure | +| Метод | Конфігурація | Переваги | Недоліки | +| -------------------- | ---------------------------------------------- | ---------------------------------- | ------------------------------------- | +| **Client secret** | `appPassword` | Просте налаштування | Потрібна ротація секретів, менш безпечно | +| **Certificate** | `authType: "federated"` + `certificatePath` | Немає спільного секрету в мережі | Додаткові витрати на керування сертифікатами | +| **Managed Identity** | `authType: "federated"` + `useManagedIdentity` | Без пароля, не потрібно керувати секретами | Потрібна інфраструктура Azure | **Типова поведінка:** якщо `authType` не задано, OpenClaw типово використовує автентифікацію через client secret. Наявні конфігурації продовжують працювати без змін. ## Локальна розробка (тунелювання) -Teams не може звертатися до `localhost`. Для локальної розробки використовуйте тунель: +Teams не може дістатися до `localhost`. Для локальної розробки використовуйте тунель: **Варіант A: ngrok** @@ -356,22 +356,22 @@ ngrok http 3978 ```bash tailscale funnel 3978 -# Використайте вашу URL-адресу Tailscale funnel як messaging endpoint +# Використовуйте ваш URL Tailscale funnel як messaging endpoint ``` ## Teams Developer Portal (альтернатива) -Замість ручного створення manifest 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. Позначте області: **Personal**, **Team**, **Group Chat** +5. Позначте scope: **Personal**, **Team**, **Group Chat** 6. Натисніть **Distribute** → **Download app package** 7. У Teams: **Apps** → **Manage your apps** → **Upload a custom app** → виберіть ZIP -Часто це простіше, ніж вручну редагувати JSON-маніфести. +Це часто простіше, ніж редагувати JSON-маніфести вручну. ## Тестування бота @@ -383,14 +383,14 @@ tailscale funnel 3978 **Варіант B: Teams (після встановлення застосунку)** -1. Установіть застосунок Teams (sideload або org catalog) +1. Встановіть застосунок Teams (sideload або через org catalog) 2. Знайдіть бота в Teams і надішліть DM -3. Перевірте логи gateway на наявність вхідної activity +3. Перевірте журнали Gateway на вхідну activity -## Налаштування (мінімальне, лише текст) +## Налаштування (мінімальний лише текстовий режим) -1. **Переконайтеся, що плагін Microsoft Teams доступний** - - У поточних пакетованих релізах OpenClaw він уже вбудований. +1. **Переконайтеся, що Plugin Microsoft Teams доступний** + - Поточні пакетовані релізи OpenClaw уже містять його вбудованим. - У старіших/власних встановленнях його можна додати вручну: - З npm: `openclaw plugins install @openclaw/msteams` - Із локального checkout: `openclaw plugins install ./path/to/local/msteams-plugin` @@ -403,8 +403,8 @@ tailscale funnel 3978 3. **Маніфест застосунку Teams** - Додайте запис `bot` із `botId = `. - - Області: `personal`, `team`, `groupChat`. - - `supportsFiles: true` (обов’язково для обробки файлів в особистій області). + - Scope: `personal`, `team`, `groupChat`. + - `supportsFiles: true` (потрібно для обробки файлів в особистому scope). - Додайте дозволи RSC (нижче). - Створіть іконки: `outline.png` (32x32) і `color.png` (192x192). - Заархівуйте всі три файли разом: `manifest.json`, `outline.png`, `color.png`. @@ -439,36 +439,36 @@ tailscale funnel 3978 - Установіть Azure Bot Messaging Endpoint на: - `https://:3978/api/messages` (або ваш вибраний path/port). -6. **Запустіть gateway** - - Канал Teams запускається автоматично, коли доступний вбудований або вручну встановлений плагін і існує конфігурація `msteams` з обліковими даними. +6. **Запустіть Gateway** + - Канал Teams запускається автоматично, коли доступний вбудований або встановлений вручну Plugin і наявна конфігурація `msteams` з обліковими даними. -## Дія member info +## Дія інформації про учасника -OpenClaw надає для Microsoft Teams дію `member-info`, що працює через Graph, щоб агенти й автоматизації могли напряму отримувати дані про учасників каналу (display name, email, role) з Microsoft Graph. +OpenClaw надає підтримувану Graph дію `member-info` для Microsoft Teams, щоб агенти й автоматизації могли напряму отримувати відомості про учасників каналу (display name, email, role) з Microsoft Graph. Вимоги: - Дозвіл RSC `Member.Read.Group` (уже є в рекомендованому маніфесті) -- Для lookups між командами: дозвіл Application `User.Read.All` у Graph з admin consent +- Для міжкомандного пошуку: дозвіл Graph Application `User.Read.All` з admin consent -Дія керується через `channels.msteams.actions.memberInfo` (типово: увімкнена, коли доступні облікові дані Graph). +Дія контролюється `channels.msteams.actions.memberInfo` (типово: увімкнено, коли доступні облікові дані Graph). ## Контекст історії -- `channels.msteams.historyLimit` визначає, скільки останніх повідомлень каналу/групи загортається в prompt. -- Використовується fallback до `messages.groupChat.historyLimit`. Установіть `0`, щоб вимкнути (типово 50). -- Отримана історія thread фільтрується за allowlist відправників (`allowFrom` / `groupAllowFrom`), тож заповнення контексту thread включає лише повідомлення від дозволених відправників. -- Цитований контекст вкладень (`ReplyTo*`, похідний від Teams reply HTML) зараз передається як отримано. -- Іншими словами, allowlist визначають, хто може активувати агента; сьогодні фільтруються лише окремі шляхи додаткового контексту. +- `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`. ## Поточні дозволи Teams RSC (маніфест) -Це **наявні resourceSpecific permissions** у нашому маніфесті застосунку Teams. Вони застосовуються лише в тій команді/чаті, де встановлено застосунок. +Це **наявні resourceSpecific permissions** у нашому маніфесті застосунку Teams. Вони застосовуються лише в межах команди/чату, де встановлено застосунок. -**Для каналів (область команди):** +**Для каналів (scope команди):** -- `ChannelMessage.Read.Group` (Application) - отримання тексту всіх повідомлень каналу без @mention +- `ChannelMessage.Read.Group` (Application) — отримання тексту всіх повідомлень каналу без @mention - `ChannelMessage.Send.Group` (Application) - `Member.Read.Group` (Application) - `Owner.Read.Group` (Application) @@ -478,9 +478,9 @@ OpenClaw надає для Microsoft Teams дію `member-info`, що працю **Для групових чатів:** -- `ChatMessage.Read.Chat` (Application) - отримання всіх повідомлень групового чату без @mention +- `ChatMessage.Read.Chat` (Application) — отримання всіх повідомлень групового чату без @mention -## Приклад маніфесту Teams (із прихованими даними) +## Приклад маніфесту Teams (з редагуванням чутливих даних) Мінімальний, коректний приклад з обов’язковими полями. Замініть ID та URL. @@ -532,26 +532,26 @@ OpenClaw надає для Microsoft Teams дію `member-info`, що працю ### Застереження щодо маніфесту (обов’язкові поля) -- `bots[].botId` **має** збігатися з Azure Bot App ID. -- `webApplicationInfo.id` **має** збігатися з Azure Bot App ID. -- `bots[].scopes` мають включати області, які ви плануєте використовувати (`personal`, `team`, `groupChat`). -- `bots[].supportsFiles: true` є обов’язковим для обробки файлів в особистій області. -- `authorization.permissions.resourceSpecific` має включати channel read/send, якщо ви хочете трафік каналів. +- `bots[].botId` **має** збігатися з App ID Azure Bot. +- `webApplicationInfo.id` **має** збігатися з App ID Azure Bot. +- `bots[].scopes` мають включати поверхні, які ви плануєте використовувати (`personal`, `team`, `groupChat`). +- `bots[].supportsFiles: true` потрібен для обробки файлів в особистому scope. +- `authorization.permissions.resourceSpecific` мають включати читання/надсилання в канали, якщо ви хочете каналовий трафік. ### Оновлення наявного застосунку Щоб оновити вже встановлений застосунок Teams (наприклад, щоб додати дозволи RSC): -1. Оновіть ваш `manifest.json` новими налаштуваннями -2. **Збільшіть поле `version`** (наприклад, `1.0.0` → `1.1.0`) +1. Оновіть `manifest.json` новими налаштуваннями +2. **Збільште поле `version`** (наприклад, `1.0.0` → `1.1.0`) 3. **Повторно заархівуйте** маніфест з іконками (`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. **Для каналів команди:** перевстановіть застосунок у кожній команді, щоб нові дозволи набули чинності +6. **Повністю закрийте й знову запустіть Teams** (не просто закрийте вікно), щоб очистити кешовані метадані застосунку -## Можливості: лише RSC чи Graph +## Можливості: лише RSC проти Graph ### З **лише Teams RSC** (застосунок встановлено, без дозволів Graph API) @@ -559,45 +559,45 @@ OpenClaw надає для Microsoft Teams дію `member-info`, що працю - Читання **текстового** вмісту повідомлень каналу. - Надсилання **текстового** вмісту повідомлень каналу. -- Отримання вкладень файлів у **особистих повідомленнях (DM)**. +- Отримання файлових вкладень у **personal (DM)**. НЕ працює: -- **Вміст зображень або файлів** у каналах/групах (payload містить лише HTML-заглушку). +- **Зображення або вміст файлів** у каналах/групах (payload містить лише HTML-заглушку). - Завантаження вкладень, що зберігаються в SharePoint/OneDrive. -- Читання історії повідомлень (поза межами live webhook event). +- Читання історії повідомлень (поза live webhook event). ### З **Teams RSC + дозволами Microsoft Graph Application** Додається: -- Завантаження hosted content (зображень, вставлених у повідомлення). -- Завантаження вкладень файлів, що зберігаються в SharePoint/OneDrive. -- Читання історії повідомлень каналів/чатів через Graph. +- Завантаження hosted contents (зображення, вставлені в повідомлення). +- Завантаження файлових вкладень, що зберігаються в SharePoint/OneDrive. +- Читання історії повідомлень каналу/чату через Graph. -### RSC і Graph API +### RSC проти Graph API -| Можливість | Дозволи RSC | Graph API | -| ----------------------- | -------------------- | ----------------------------------- | -| **Повідомлення в реальному часі** | Так (через webhook) | Ні (лише polling) | -| **Історичні повідомлення** | Ні | Так (можна отримувати історію) | +| Можливість | Дозволи RSC | Graph API | +| ---------------------- | -------------------- | ----------------------------------- | +| **Повідомлення в реальному часі** | Так (через webhook) | Ні (лише polling) | +| **Історичні повідомлення** | Ні | Так (можна запитувати історію) | | **Складність налаштування** | Лише маніфест застосунку | Потрібні admin consent + token flow | -| **Працює офлайн** | Ні (має бути запущено) | Так (можна запитувати будь-коли) | +| **Працює офлайн** | Ні (має працювати) | Так (можна запитувати будь-коли) | -**Підсумок:** RSC потрібен для прослуховування в реальному часі; Graph API — для історичного доступу. Щоб надолужувати пропущені повідомлення під час офлайн-режиму, потрібен Graph API з `ChannelMessage.Read.All` (потрібен admin consent). +**Висновок:** RSC призначений для прослуховування в реальному часі; Graph API — для історичного доступу. Щоб наздоганяти пропущені повідомлення під час офлайну, вам потрібен Graph API з `ChannelMessage.Read.All` (потрібен admin consent). -## Медіа й історія з Graph (обов’язково для каналів) +## Graph-enabled media + history (потрібно для каналів) -Якщо вам потрібні зображення/файли в **каналах** або ви хочете отримувати **історію повідомлень**, потрібно ввімкнути дозволи Microsoft Graph і надати admin consent. +Якщо вам потрібні зображення/файли в **каналах** або потрібно отримувати **історію повідомлень**, необхідно ввімкнути дозволи Microsoft Graph і надати admin consent. -1. У **App Registration** Entra ID (Azure AD) додайте **Application permissions** Microsoft Graph: +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. ## Відомі обмеження @@ -605,78 +605,78 @@ OpenClaw надає для Microsoft Teams дію `member-info`, що працю Teams доставляє повідомлення через HTTP webhook. Якщо обробка триває надто довго (наприклад, через повільні відповіді LLM), ви можете побачити: -- тайм-аути gateway -- повторні спроби доставки повідомлення з боку Teams (що спричиняє дублікати) +- тайм-аути Gateway +- повторні спроби Teams доставити повідомлення (що спричиняє дублікати) - втрачені відповіді OpenClaw обробляє це, швидко повертаючи відповідь і надсилаючи відповіді проактивно, але дуже повільні відповіді все одно можуть спричиняти проблеми. ### Форматування -Markdown у Teams більш обмежений, ніж у Slack чи Discord: +Markdown у Teams більш обмежений, ніж у Slack або Discord: - Базове форматування працює: **жирний**, _курсив_, `code`, посилання - Складний markdown (таблиці, вкладені списки) може відображатися некоректно -- Adaptive Cards підтримуються для опитувань і довільного надсилання карток (див. нижче) +- 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). Майстер налаштування зіставляє імена з 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.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..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..channels..tools`: перевизначення політики інструментів для каналу (`allow`/`deny`/`alsoAllow`). +- `channels.msteams.teams..channels..toolsBySender`: перевизначення політики інструментів для каналу за відправником (підтримується wildcard `"*"`). - Ключі `toolsBySender` мають використовувати явні префікси: - `id:`, `e164:`, `username:`, `name:` (застарілі ключі без префікса все ще зіставляються лише з `id:`). -- `channels.msteams.actions.memberInfo`: увімкнути або вимкнути дію member info через Graph (типово: увімкнено, коли доступні облікові дані Graph). + `id:`, `e164:`, `username:`, `name:` (застарілі ключі без префікса, як і раніше, зіставляються лише з `id:`). +- `channels.msteams.actions.memberInfo`: увімкнути або вимкнути дію інформації про учасника на основі Graph (типово: увімкнено, коли доступні облікові дані Graph). - `channels.msteams.authType`: тип автентифікації — `"secret"` (типово) або `"federated"`. -- `channels.msteams.certificatePath`: шлях до файлу PEM-сертифіката (federated + certificate auth). -- `channels.msteams.certificateThumbprint`: відбиток сертифіката (необов’язково, не потрібен для автентифікації). +- `channels.msteams.certificatePath`: шлях до PEM-файлу сертифіката (federated + автентифікація сертифікатом). +- `channels.msteams.certificateThumbprint`: thumbprint сертифіката (необов’язково, не потрібен для автентифікації). - `channels.msteams.useManagedIdentity`: увімкнути автентифікацію через managed identity (режим federated). - `channels.msteams.managedIdentityClientId`: client ID для user-assigned managed identity. -- `channels.msteams.sharePointSiteId`: SharePoint site ID для надсилання файлів у групових чатах/каналах (див. [Надсилання файлів у групових чатах](#sending-files-in-group-chats)). +- `channels.msteams.sharePointSiteId`: SharePoint site ID для вивантаження файлів у групових чатах/каналах (див. [Надсилання файлів у групових чатах](#sending-files-in-group-chats)). -## Маршрутизація та сесії +## Маршрутизація й сесії - Ключі сесій відповідають стандартному формату агента (див. [/concepts/session](/uk/concepts/session)): - - Прямі повідомлення використовують основну сесію (`agent::`). + - Direct messages спільно використовують основну сесію (`agent::`). - Повідомлення каналу/групи використовують conversation id: - `agent::msteams:channel:` - `agent::msteams:group:` -## Стиль відповіді: threads чи posts +## Стиль відповіді: Threads проти Posts -Teams нещодавно запровадив два стилі UI каналів поверх тієї самої базової моделі даних: +Нещодавно Teams запровадив два стилі UI каналів поверх тієї самої базової моделі даних: -| Стиль | Опис | Рекомендований `replyStyle` | -| ----------------------- | --------------------------------------------------------- | --------------------------- | -| **Posts** (класичний) | Повідомлення відображаються як картки з thread-відповідями під ними | `thread` (типово) | -| **Threads** (як у Slack) | Повідомлення йдуть лінійно, більше схоже на Slack | `top-level` | +| Стиль | Опис | Рекомендований `replyStyle` | +| ---------------------- | --------------------------------------------------------- | --------------------------- | +| **Posts** (класичний) | Повідомлення відображаються як картки з гілками відповідей під ними | `thread` (типово) | +| **Threads** (як у Slack) | Повідомлення йдуть лінійно, більше схоже на Slack | `top-level` | **Проблема:** API Teams не показує, який стиль UI використовує канал. Якщо використати неправильний `replyStyle`: -- `thread` у каналі зі стилем Threads → відповіді виглядатимуть незграбно вкладеними -- `top-level` у каналі зі стилем Posts → відповіді відображатимуться як окремі повідомлення верхнього рівня, а не в thread +- `thread` у каналі стилю Threads → відповіді виглядають незграбно вкладеними +- `top-level` у каналі стилю Posts → відповіді з’являються як окремі повідомлення верхнього рівня, а не в гілці -**Рішення:** налаштуйте `replyStyle` для кожного каналу залежно від того, як налаштовано канал: +**Рішення:** Налаштуйте `replyStyle` для кожного каналу залежно від того, як налаштований канал: ```json5 { @@ -701,40 +701,40 @@ Teams нещодавно запровадив два стилі UI каналі **Поточні обмеження:** -- **DM:** зображення та вкладення файлів працюють через Teams bot file API. -- **Канали/групи:** вкладення зберігаються в сховищі M365 (SharePoint/OneDrive). Payload webhook містить лише HTML-заглушку, а не фактичні байти файлу. **Для завантаження вкладень каналів потрібні дозволи Graph API**. -- Для явних надсилань, що починаються з файлу, використовуйте `action=upload-file` з `media` / `filePath` / `path`; необов’язковий `message` стає супровідним текстом/коментарем, а `filename` перевизначає ім’я завантаженого файлу. +- **DM:** зображення й файлові вкладення працюють через API файлів ботів Teams. +- **Канали/групи:** вкладення живуть у сховищі M365 (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 завантажує медіа лише з хостів Microsoft/Teams. Перевизначайте це через `channels.msteams.mediaAllowHosts` (використайте `["*"]`, щоб дозволити будь-який хост). +Заголовки Authorization додаються лише для хостів у `channels.msteams.mediaAuthAllowHosts` (типово хости Graph + Bot Framework). Тримайте цей список строгим (уникайте multi-tenant суфіксів). ## Надсилання файлів у групових чатах -Боти можуть надсилати файли в DM за допомогою потоку FileConsentCard (вбудовано). Однак **надсилання файлів у групових чатах/каналах** потребує додаткового налаштування: +Боти можуть надсилати файли в DM через потік FileConsentCard (вбудований). Однак **надсилання файлів у групових чатах/каналах** потребує додаткового налаштування: -| Контекст | Як надсилаються файли | Потрібне налаштування | -| ------------------------ | ------------------------------------------ | -------------------------------------------------- | -| **DM** | FileConsentCard → користувач підтверджує → бот завантажує | Працює одразу | -| **Групові чати/канали** | Завантаження до SharePoint → посилання для спільного доступу | Потрібні `sharePointSiteId` + дозволи Graph | -| **Зображення (будь-який контекст)** | Вбудовано як Base64 | Працює одразу | +| Контекст | Як надсилаються файли | Потрібне налаштування | +| ------------------------ | ---------------------------------------- | ----------------------------------------------- | +| **DM** | FileConsentCard → користувач приймає → бот вивантажує | Працює одразу | +| **Групові чати/канали** | Вивантаження в SharePoint → посилання для спільного доступу | Потрібні `sharePointSiteId` + дозволи Graph | +| **Зображення (будь-який контекст)** | Inline у кодуванні Base64 | Працює одразу | ### Чому груповим чатам потрібен SharePoint -Боти не мають особистого диска OneDrive (endpoint Graph API `/me/drive` не працює для application identities). Щоб надсилати файли в групових чатах/каналах, бот завантажує їх на **сайт SharePoint** і створює посилання для спільного доступу. +Боти не мають особистого диска OneDrive (endpoint 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) - необов’язково, вмикає посилання спільного доступу для окремих користувачів + - `Sites.ReadWrite.All` (Application) — вивантаження файлів у SharePoint + - `Chat.Read.All` (Application) — необов’язково, вмикає посилання для спільного доступу для окремих користувачів 2. **Надайте admin consent** для tenant. -3. **Отримайте SharePoint site ID:** +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}" @@ -751,7 +751,7 @@ Teams нещодавно запровадив два стилі UI каналі { channels: { msteams: { - // ... інша конфігурація ... + // ... other config ... sharePointSiteId: "contoso.sharepoint.com,guid1,guid2", }, }, @@ -760,40 +760,40 @@ Teams нещодавно запровадив два стилі UI каналі ### Поведінка спільного доступу -| Дозвіл | Поведінка спільного доступу | -| ----------------------------------------- | -------------------------------------------------------- | -| `Sites.ReadWrite.All` лише | Посилання спільного доступу для всієї організації (доступ має будь-хто в організації) | -| `Sites.ReadWrite.All` + `Chat.Read.All` | Посилання спільного доступу для окремих користувачів (доступ мають лише учасники чату) | +| Дозвіл | Поведінка спільного доступу | +| --------------------------------------- | ---------------------------------------------------------- | +| `Sites.ReadWrite.All` only | Посилання для спільного доступу на рівні організації (доступне будь-кому в org) | +| `Sites.ReadWrite.All` + `Chat.Read.All` | Посилання для спільного доступу для окремих користувачів (доступне лише учасникам чату) | -Спільний доступ для окремих користувачів безпечніший, оскільки лише учасники чату можуть отримати доступ до файлу. Якщо дозволу `Chat.Read.All` немає, бот повертається до спільного доступу для всієї організації. +Спільний доступ для окремих користувачів безпечніший, оскільки доступ до файлу мають лише учасники чату. Якщо дозвіл `Chat.Read.All` відсутній, бот повертається до спільного доступу на рівні організації. -### Поведінка fallback +### Резервна поведінка -| Сценарій | Результат | -| ------------------------------------------------- | --------------------------------------------------- | -| Груповий чат + файл + налаштовано `sharePointSiteId` | Завантаження у SharePoint, надсилання посилання спільного доступу | -| Груповий чат + файл + без `sharePointSiteId` | Спроба завантаження в OneDrive (може не вдатися), надсилається лише текст | -| Особистий чат + файл | Потік FileConsentCard (працює без SharePoint) | -| Будь-який контекст + зображення | Вбудовано як Base64 (працює без SharePoint) | +| Сценарій | Результат | +| ------------------------------------------------ | --------------------------------------------------- | +| Груповий чат + файл + налаштовано `sharePointSiteId` | Вивантаження в SharePoint, надсилання посилання для спільного доступу | +| Груповий чат + файл + немає `sharePointSiteId` | Спроба вивантаження в OneDrive (може не вдатися), надсилання лише тексту | +| Особистий чат + файл | Потік FileConsentCard (працює без SharePoint) | +| Будь-який контекст + зображення | Inline у кодуванні Base64 (працює без SharePoint) | -### Місце зберігання файлів +### Де зберігаються файли -Завантажені файли зберігаються в папці `/OpenClawShared/` у стандартній бібліотеці документів налаштованого сайту SharePoint. +Вивантажені файли зберігаються в папці `/OpenClawShared/` у типовій бібліотеці документів налаштованого сайту SharePoint. ## Опитування (Adaptive Cards) -OpenClaw надсилає опитування Teams як Adaptive Cards (вбудованого Teams poll API немає). +OpenClaw надсилає опитування Teams як Adaptive Cards (рідного API опитувань Teams немає). - CLI: `openclaw message poll --channel msteams --target conversation: ...` -- Голоси записуються gateway у `~/.openclaw/msteams-polls.json`. -- Щоб записувати голоси, gateway має залишатися онлайн. -- Опитування поки що не публікують підсумки результатів автоматично (за потреби перевіряйте файл сховища). +- Голоси записуються Gateway у `~/.openclaw/msteams-polls.json`. +- Gateway має залишатися онлайн, щоб записувати голоси. +- Опитування поки не публікують підсумки результатів автоматично (за потреби перегляньте файл сховища). -## Adaptive Cards (довільні) +## Картки presentation -Надсилайте будь-який JSON Adaptive Card користувачам або розмовам Teams за допомогою інструмента `message` або CLI. +Надсилайте семантичні payload presentation користувачам Teams або в розмови через інструмент `message` або CLI. OpenClaw відтворює їх як Teams Adaptive Cards із загального контракту presentation. -Параметр `card` приймає JSON-об’єкт Adaptive Card. Коли передано `card`, текст повідомлення необов’язковий. +Параметр `presentation` приймає семантичні блоки. Якщо задано `presentation`, текст повідомлення є необов’язковим. **Інструмент агента:** @@ -802,10 +802,9 @@ OpenClaw надсилає опитування Teams як Adaptive Cards (вбу action: "send", channel: "msteams", target: "user:", - card: { - type: "AdaptiveCard", - version: "1.5", - body: [{ type: "TextBlock", text: "Hello!" }], + presentation: { + title: "Hello", + blocks: [{ type: "text", text: "Hello!" }], }, } ``` @@ -815,21 +814,21 @@ OpenClaw надсилає опитування Teams як Adaptive Cards (вбу ```bash openclaw message send --channel msteams \ --target "conversation:19:abc...@thread.tacv2" \ - --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}' + --presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello!"}]}' ``` -Див. [документацію Adaptive Cards](https://adaptivecards.io/) щодо схеми карток і прикладів. Докладніше про формати цілей див. у [Формати цілей](#target-formats) нижче. +Докладно про формат цілі див. [Формати цілі](#target-formats) нижче. -## Формати цілей +## Формати цілі Цілі 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`) | +| Тип цілі | Формат | Приклад | +| ---------------------- | -------------------------------- | --------------------------------------------------- | +| Користувач (за 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:** @@ -837,15 +836,15 @@ openclaw message send --channel msteams \ # Надіслати користувачу за ID openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello" -# Надіслати користувачу за display name (викликає lookup через Graph API) +# Надіслати користувачу за display name (викликає пошук через Graph API) openclaw message send --channel msteams --target "user:John Smith" --message "Hello" # Надіслати в груповий чат або канал openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello" -# Надіслати Adaptive Card у розмову +# Надіслати картку presentation у розмову openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" \ - --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello"}]}' + --presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello"}]}' ``` **Приклади інструмента агента:** @@ -864,31 +863,30 @@ openclaw message send --channel msteams --target "conversation:19:abc...@thread. action: "send", channel: "msteams", target: "conversation:19:abc...@thread.tacv2", - card: { - type: "AdaptiveCard", - version: "1.5", - body: [{ type: "TextBlock", text: "Hello" }], + presentation: { + title: "Hello", + blocks: [{ type: "text", text: "Hello" }], }, } ``` -Примітка: без префікса `user:` імена типово трактуються як цілі групи/команди. Завжди використовуйте `user:`, коли адресуєте людей за display name. +Примітка: без префікса `user:` імена типово трактуються як цілі групи/команди. Завжди використовуйте `user:`, коли націлюєтеся на людей за display name. ## Проактивні повідомлення - Проактивні повідомлення можливі лише **після** взаємодії користувача, оскільки саме тоді ми зберігаємо посилання на розмову. -- Див. `/gateway/configuration` щодо `dmPolicy` і обмеження через allowlist. +- Див. `/gateway/configuration` для `dmPolicy` і керування через allowlist. -## ID команди та каналу (поширена пастка) +## ID команд і каналів (поширена пастка) -Параметр запиту `groupId` в URL Teams — це **НЕ** team ID, який використовується для конфігурації. Натомість витягайте ID зі шляху URL: +Параметр запиту `groupId` в URL Teams — **НЕ** той ID команди, який використовується для конфігурації. Натомість витягуйте ID зі шляху URL: **URL команди:** ``` https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=... └────────────────────────────┘ - Team ID (виконайте URL-декодування) + ID команди (декодуйте URL) ``` **URL каналу:** @@ -896,26 +894,26 @@ https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?gro ``` https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=... └─────────────────────────┘ - Channel ID (виконайте URL-декодування) + ID каналу (декодуйте URL) ``` **Для конфігурації:** -- Team ID = сегмент шляху після `/team/` (URL-декодований, наприклад `19:Bk4j...@thread.tacv2`) -- Channel ID = сегмент шляху після `/channel/` (URL-декодований) +- ID команди = сегмент шляху після `/team/` (після URL-декодування, наприклад `19:Bk4j...@thread.tacv2`) +- ID каналу = сегмент шляху після `/channel/` (після URL-декодування) - Параметр запиту `groupId` **ігноруйте** ## Приватні канали Боти мають обмежену підтримку в приватних каналах: -| Функція | Стандартні канали | Приватні канали | -| ---------------------------- | ----------------- | -------------------- | -| Встановлення бота | Так | Обмежено | -| Повідомлення в реальному часі (webhook) | Так | Може не працювати | -| Дозволи RSC | Так | Можуть поводитися інакше | -| @mentions | Так | Якщо бот доступний | -| Історія через Graph API | Так | Так (із дозволами) | +| Функція | Стандартні канали | Приватні канали | +| --------------------------- | ----------------- | --------------------- | +| Встановлення бота | Так | Обмежено | +| Повідомлення в реальному часі (webhook) | Так | Може не працювати | +| Дозволи RSC | Так | Можуть поводитися інакше | +| @mentions | Так | Якщо бот доступний | +| Історія через Graph API | Так | Так (з дозволами) | **Обхідні варіанти, якщо приватні канали не працюють:** @@ -927,29 +925,29 @@ https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?gr ### Поширені проблеми -- **У каналах не відображаються зображення:** бракує дозволів Graph або admin consent. Повторно встановіть застосунок Teams і повністю закрийте/знову відкрийте Teams. -- **Немає відповідей у каналі:** типово потрібні згадки; установіть `channels.msteams.requireMention=false` або налаштуйте це для конкретної команди/каналу. -- **Невідповідність версій (Teams все ще показує старий маніфест):** видаліть і знову додайте застосунок та повністю перезапустіть Teams для оновлення. -- **401 Unauthorized від webhook:** очікувано під час ручного тестування без Azure JWT — це означає, що endpoint доступний, але автентифікація не пройдена. Для коректної перевірки використовуйте Azure Web Chat. +- **Зображення не відображаються в каналах:** відсутні дозволи Graph або admin consent. Перевстановіть застосунок Teams і повністю закрийте/заново відкрийте Teams. +- **Немає відповідей у каналі:** типово потрібні згадки; установіть `channels.msteams.requireMention=false` або налаштуйте це для окремої команди/каналу. +- **Невідповідність версій (Teams усе ще показує старий маніфест):** видаліть і повторно додайте застосунок та повністю закрийте Teams, щоб оновити стан. +- **401 Unauthorized від webhook:** це очікувано під час ручного тестування без Azure JWT — означає, що endpoint досяжний, але автентифікація не пройшла. Для коректної перевірки використовуйте Azure Web Chat. ### Помилки завантаження маніфесту -- **"Icon file cannot be empty":** маніфест посилається на файли іконок розміром 0 байт. Створіть коректні PNG-іконки (`outline.png` 32x32, `color.png` 192x192). +- **"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. +- **"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. Перевірте, чи адміністратор вашої організації не заблокував дозволи RSC -4. Підтвердьте, що ви використовуєте правильну область: `ChannelMessage.Read.Group` для команд, `ChatMessage.Read.Chat` для групових чатів +3. Перевірте, чи адміністратор вашої org не заблокував дозволи RSC +4. Підтвердьте, що використовуєте правильний scope: `ChannelMessage.Read.Group` для команд, `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) @@ -958,8 +956,8 @@ https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?gr ## Пов’язане -- [Огляд каналів](/uk/channels) — усі підтримувані канали +- [Channels Overview](/uk/channels) — усі підтримувані канали - [Pairing](/uk/channels/pairing) — автентифікація DM і потік pairing -- [Групи](/uk/channels/groups) — поведінка групового чату та обмеження за згадками -- [Маршрутизація каналів](/uk/channels/channel-routing) — маршрутизація сесій для повідомлень -- [Безпека](/uk/gateway/security) — модель доступу та посилення захисту +- [Groups](/uk/channels/groups) — поведінка групового чату й керування через згадки +- [Channel Routing](/uk/channels/channel-routing) — маршрутизація сесій для повідомлень +- [Security](/uk/gateway/security) — модель доступу та посилення захисту diff --git a/docs/uk/channels/qqbot.md b/docs/uk/channels/qqbot.md index 03d4b8697..bf4814da4 100644 --- a/docs/uk/channels/qqbot.md +++ b/docs/uk/channels/qqbot.md @@ -2,35 +2,41 @@ read_when: - Ви хочете підключити OpenClaw до QQ - Вам потрібно налаштувати облікові дані QQ Bot - - Ви хочете підтримку групових чатів або приватних чатів QQ Bot + - Ви хочете підтримку групового або приватного чату QQ Bot summary: Налаштування, конфігурація та використання QQ Bot title: QQ Bot x-i18n: - generated_at: "2026-04-05T17:58:40Z" + generated_at: "2026-04-21T20:37:37Z" model: gpt-5.4 provider: openai - source_hash: 0e58fb7b07c59ecbf80a1276368c4a007b45d84e296ed40cffe9845e0953696c + source_hash: 49a5ae5615935a435a69748a3c4465ae8c33d3ab84db5e37fd8beec70506ce36 source_path: channels/qqbot.md workflow: 15 --- # QQ Bot -QQ Bot підключається до OpenClaw через офіційний API QQ Bot (WebSocket gateway). Плагін підтримує приватні чати C2C, групові @повідомлення та повідомлення в каналах guild із розширеними медіа (зображення, голос, відео, файли). +QQ Bot підключається до OpenClaw через офіційний QQ Bot API (шлюз WebSocket). Цей +Plugin підтримує приватний чат C2C, групові @повідомлення та повідомлення в каналах guild із +розширеними медіа (зображення, голос, відео, файли). -Статус: вбудований плагін. Підтримуються прямі повідомлення, групові чати, канали guild і медіа. Реакції та потоки не підтримуються. +Статус: вбудований plugin. Підтримуються прямі повідомлення, групові чати, канали +guild і медіа. Реакції та треди не підтримуються. -## Вбудований плагін +## Вбудований plugin -Поточні випуски OpenClaw містять QQ Bot у комплекті, тому звичайні зібрані збірки не потребують окремого кроку `openclaw plugins install`. +Поточні випуски OpenClaw містять QQ Bot у комплекті, тому звичайним пакетним збіркам не потрібен +окремий крок `openclaw plugins install`. ## Налаштування -1. Перейдіть на [QQ Open Platform](https://q.qq.com/) і відскануйте QR-код за допомогою QQ на телефоні, щоб зареєструватися / увійти. -2. Натисніть **Create Bot**, щоб створити нового QQ-бота. +1. Перейдіть на [QQ Open Platform](https://q.qq.com/) і відскануйте QR-код своїм + QQ на телефоні, щоб зареєструватися / увійти. +2. Натисніть **Create Bot**, щоб створити нового бота QQ. 3. Знайдіть **AppID** і **AppSecret** на сторінці налаштувань бота та скопіюйте їх. -> AppSecret не зберігається у відкритому вигляді — якщо ви залишите сторінку, не зберігши його, вам доведеться згенерувати новий. +> AppSecret не зберігається у відкритому вигляді — якщо ви залишите сторінку, не зберігши його, +> вам доведеться згенерувати новий. 4. Додайте канал: @@ -40,7 +46,7 @@ openclaw channels add --channel qqbot --token "AppID:AppSecret" 5. Перезапустіть Gateway. -Інтерактивні шляхи налаштування: +Шляхи інтерактивного налаштування: ```bash openclaw channels add @@ -84,13 +90,14 @@ AppSecret із файла: Примітки: -- Резервний варіант через змінні середовища застосовується лише до облікового запису QQ Bot за замовчуванням. -- `openclaw channels add --channel qqbot --token-file ...` надає лише AppSecret; AppID уже має бути задано в конфігурації або в `QQBOT_APP_ID`. -- `clientSecret` також приймає вхід SecretRef, а не лише відкритий рядок. +- Резервне використання змінних середовища застосовується лише до облікового запису QQ Bot за замовчуванням. +- `openclaw channels add --channel qqbot --token-file ...` надає лише + AppSecret; AppID уже має бути заданий у конфігурації або в `QQBOT_APP_ID`. +- `clientSecret` також приймає введення SecretRef, а не лише рядок у відкритому вигляді. ### Налаштування кількох облікових записів -Запускайте кілька QQ-ботів в одному екземплярі OpenClaw: +Запускайте кілька ботів QQ в одному екземплярі OpenClaw: ```json5 { @@ -111,7 +118,8 @@ AppSecret із файла: } ``` -Кожен обліковий запис запускає власне WebSocket-з’єднання та підтримує незалежний кеш токенів (ізольований за `appId`). +Кожен обліковий запис запускає власне WebSocket-з'єднання та підтримує незалежний +кеш токенів (ізоляція за `appId`). Додайте другого бота через CLI: @@ -121,12 +129,12 @@ openclaw channels add --channel qqbot --account bot2 --token "222222222:secret-o ### Голос (STT / TTS) -Підтримка STT і TTS має дворівневу конфігурацію з пріоритетним резервним вибором: +Підтримка STT і TTS має дворівневу конфігурацію з резервним пріоритетом: -| Налаштування | Специфічне для плагіна | Резервний варіант фреймворку | -| ------------ | ---------------------- | ---------------------------- | -| STT | `channels.qqbot.stt` | `tools.media.audio.models[0]` | -| TTS | `channels.qqbot.tts` | `messages.tts` | +| Налаштування | Специфічне для plugin | Резервне значення framework | +| ------------ | --------------------- | ------------------------------ | +| STT | `channels.qqbot.stt` | `tools.media.audio.models[0]` | +| TTS | `channels.qqbot.tts` | `messages.tts` | ```json5 { @@ -146,9 +154,10 @@ openclaw channels add --channel qqbot --account bot2 --token "222222222:secret-o } ``` -Установіть `enabled: false` для будь-якого з них, щоб вимкнути. +Установіть `enabled: false` для будь-якого з них, щоб вимкнути його. -Поведінку завантаження/транскодування вихідного аудіо також можна налаштувати через `channels.qqbot.audioFormatPolicy`: +Поведінку вивантаження/транскодування вихідного аудіо також можна налаштувати через +`channels.qqbot.audioFormatPolicy`: - `sttDirectFormats` - `uploadDirectFormats` @@ -162,26 +171,50 @@ openclaw channels add --channel qqbot --account bot2 --token "222222222:secret-o | `qqbot:group:GROUP_OPENID` | Груповий чат | | `qqbot:channel:CHANNEL_ID` | Канал guild | -> Кожен бот має власний набір користувацьких OpenID. OpenID, отриманий ботом A, **не можна** використовувати для надсилання повідомлень через бота B. +> Кожен бот має власний набір OpenID користувачів. OpenID, отриманий ботом A, **не можна** +> використовувати для надсилання повідомлень через бота B. ## Slash-команди -Вбудовані команди, що перехоплюються до черги AI: +Вбудовані команди, які перехоплюються до черги AI: -| Команда | Опис | -| -------------- | -------------------------------------- | -| `/bot-ping` | Перевірка затримки | -| `/bot-version` | Показати версію фреймворку OpenClaw | -| `/bot-help` | Показати всі команди | -| `/bot-upgrade` | Показати посилання на посібник оновлення QQBot | -| `/bot-logs` | Експортувати останні журнали gateway у файл | +| Команда | Опис | +| -------------- | -------------------------------------------------------------------------------------------------------------- | +| `/bot-ping` | Тест затримки | +| `/bot-version` | Показати версію framework OpenClaw | +| `/bot-help` | Показати список усіх команд | +| `/bot-upgrade` | Показати посилання на посібник з оновлення QQBot | +| `/bot-logs` | Експортувати нещодавні журнали Gateway як файл | +| `/bot-approve` | Схвалити очікувану дію QQ Bot (наприклад, підтвердження вивантаження C2C або в групу) через нативний потік. | -Додавайте `?` до будь-якої команди, щоб отримати довідку з використання (наприклад, `/bot-upgrade ?`). +Додайте `?` до будь-якої команди, щоб отримати довідку щодо використання (наприклад, `/bot-upgrade ?`). + +## Архітектура рушія + +QQ Bot постачається як самодостатній рушій усередині plugin: + +- Кожен обліковий запис має ізольований стек ресурсів (WebSocket-з'єднання, API-клієнт, кеш токенів, кореневий каталог медіасховища), прив'язаний до `appId`. Облікові записи ніколи не ділять вхідний/вихідний стан. +- Багатообліковий логер позначає рядки журналу обліковим записом-власником, щоб діагностику можна було розділяти, коли ви запускаєте кількох ботів під одним gateway. +- Шляхи вхідних, вихідних повідомлень і bridge Gateway спільно використовують єдиний кореневий каталог медіаданих у `~/.openclaw/media`, тому вивантаження, завантаження та кеші транскодування потрапляють до одного захищеного каталогу замість дерева для кожної підсистеми. +- Облікові дані можна резервувати та відновлювати як частину стандартних знімків облікових даних OpenClaw; після відновлення рушій знову приєднує стек ресурсів кожного облікового запису без потреби в новому QR-сполученні. + +## Онбординг через QR-код + +Як альтернатива ручному вставленню `AppID:AppSecret`, рушій підтримує потік онбордингу через QR-код для прив'язування QQ Bot до OpenClaw: + +1. Запустіть шлях налаштування QQ Bot (наприклад, `openclaw channels add --channel qqbot`) і, коли буде запропоновано, виберіть потік через QR-код. +2. Відскануйте згенерований QR-код за допомогою застосунку на телефоні, прив'язаного до цільового QQ Bot. +3. Підтвердьте сполучення на телефоні. OpenClaw зберігає отримані облікові дані в `credentials/` у межах правильного облікового запису. + +Запити на підтвердження, згенеровані самим ботом (наприклад, потоки «дозволити цю дію?», які надає QQ Bot API), відображаються як нативні запити OpenClaw, які можна прийняти за допомогою `/bot-approve`, а не відповідати через сирий клієнт QQ. ## Усунення несправностей -- **Бот відповідає "gone to Mars":** облікові дані не налаштовані або Gateway не запущено. -- **Немає вхідних повідомлень:** перевірте, що `appId` і `clientSecret` правильні, а бот увімкнений на QQ Open Platform. -- **Після налаштування з `--token-file` усе ще показується як не налаштовано:** `--token-file` задає лише AppSecret. Вам усе ще потрібен `appId` у конфігурації або `QQBOT_APP_ID`. -- **Проактивні повідомлення не надходять:** QQ може перехоплювати повідомлення, ініційовані ботом, якщо користувач не взаємодіяв нещодавно. -- **Голос не транскрибується:** переконайтеся, що STT налаштовано, а провайдер доступний. +- **Бот відповідає "gone to Mars":** облікові дані не налаштовано або Gateway не запущено. +- **Немає вхідних повідомлень:** перевірте, що `appId` і `clientSecret` правильні, і + що бота увімкнено на QQ Open Platform. +- **Після налаштування з `--token-file` усе ще показується неналаштований стан:** `--token-file` задає лише + AppSecret. Вам усе ще потрібен `appId` у конфігурації або `QQBOT_APP_ID`. +- **Проактивні повідомлення не надходять:** QQ може перехоплювати повідомлення, ініційовані ботом, якщо + користувач не взаємодіяв із ним нещодавно. +- **Голос не транскрибується:** переконайтеся, що STT налаштовано і що provider доступний. diff --git a/docs/uk/channels/telegram.md b/docs/uk/channels/telegram.md index 9da32f5b4..ec639299f 100644 --- a/docs/uk/channels/telegram.md +++ b/docs/uk/channels/telegram.md @@ -4,27 +4,27 @@ read_when: summary: Статус підтримки бота Telegram, можливості та конфігурація title: Telegram x-i18n: - generated_at: "2026-04-21T16:52:57Z" + generated_at: "2026-04-21T20:37:36Z" model: gpt-5.4 provider: openai - source_hash: 816238b53942b319a300843db62ec1d4bf8d84bc11094010926ac9ad457c6d3d + source_hash: 1575c4e5e932a4a6330d57fa0d1639336aecdb8fa70d37d92dccd0d466d2fccb source_path: channels/telegram.md workflow: 15 --- # Telegram (Bot API) -Статус: готовий до продакшену для DM бота + груп через grammY. Long polling — режим за замовчуванням; режим Webhook — необов’язковий. +Статус: готовий до використання у продакшені для DM бота + груп через grammY. Long polling — режим за замовчуванням; режим Webhook-ів — необов’язковий. - Політика DM за замовчуванням для Telegram — підключення. + Типова політика DM для Telegram — підключення. - - Міжканальна діагностика та інструкції з відновлення. + + Міжканальні діагностичні та відновлювальні сценарії. - Повні шаблони конфігурації каналу та приклади. + Повні шаблони та приклади конфігурації каналу. @@ -32,9 +32,9 @@ x-i18n: - Відкрийте Telegram і почніть чат із **@BotFather** (переконайтеся, що хендл точно `@BotFather`). + Відкрийте Telegram і почніть чат з **@BotFather** (переконайтеся, що handle точно `@BotFather`). - Виконайте `/newbot`, дотримуйтесь підказок і збережіть токен. + Виконайте `/newbot`, дотримуйтеся підказок і збережіть токен. @@ -54,11 +54,11 @@ x-i18n: ``` Резервний варіант через env: `TELEGRAM_BOT_TOKEN=...` (лише для облікового запису за замовчуванням). - Telegram **не** використовує `openclaw channels login telegram`; налаштуйте токен у config/env, а потім запустіть gateway. + Telegram **не** використовує `openclaw channels login telegram`; налаштуйте токен у config/env, потім запустіть gateway. - + ```bash openclaw gateway @@ -66,31 +66,31 @@ openclaw pairing list telegram openclaw pairing approve telegram ``` - Коди підключення спливають через 1 годину. + Коди підключення дійсні протягом 1 години. - Додайте бота до своєї групи, а потім налаштуйте `channels.telegram.groups` і `groupPolicy` відповідно до вашої моделі доступу. + Додайте бота до своєї групи, потім налаштуйте `channels.telegram.groups` і `groupPolicy` відповідно до вашої моделі доступу. -Порядок визначення токена враховує обліковий запис. На практиці значення з config мають пріоритет над резервним env-значенням, а `TELEGRAM_BOT_TOKEN` застосовується лише до облікового запису за замовчуванням. +Порядок визначення токена залежить від облікового запису. На практиці значення з config мають пріоритет над резервним варіантом з env, а `TELEGRAM_BOT_TOKEN` застосовується лише до облікового запису за замовчуванням. -## Налаштування на стороні Telegram +## Налаштування з боку Telegram - - Для ботів Telegram за замовчуванням увімкнено **Privacy Mode**, який обмежує, які повідомлення в групах вони отримують. + + Для ботів Telegram за замовчуванням увімкнено **Privacy Mode**, який обмежує повідомлення групи, що вони отримують. - Якщо бот має бачити всі повідомлення в групі, зробіть одне з такого: + Якщо бот має бачити всі повідомлення групи, зробіть одне з такого: - - вимкніть режим приватності через `/setprivacy`, або + - вимкніть режим конфіденційності через `/setprivacy`, або - зробіть бота адміністратором групи. - Після перемикання режиму приватності видаліть і знову додайте бота в кожну групу, щоб Telegram застосував зміну. + Після перемикання режиму конфіденційності видаліть бота з кожної групи й додайте знову, щоб Telegram застосував зміну. @@ -103,34 +103,34 @@ openclaw pairing approve telegram - - `/setjoingroups` щоб дозволити/заборонити додавання до груп - - `/setprivacy` для поведінки видимості в групах + - `/setjoingroups`, щоб дозволити/заборонити додавання до груп + - `/setprivacy` для керування видимістю в групах -## Контроль доступу та активація +## Керування доступом і активація `channels.telegram.dmPolicy` керує доступом до прямих повідомлень: - `pairing` (за замовчуванням) - - `allowlist` (потрібен принаймні один ID відправника в `allowFrom`) - - `open` (потрібно, щоб `allowFrom` містив `"*"`) + - `allowlist` (потребує принаймні одного ID відправника в `allowFrom`) + - `open` (потребує, щоб `allowFrom` містив `"*"`) - `disabled` - `channels.telegram.allowFrom` приймає числові ID користувачів Telegram. Префікси `telegram:` / `tg:` приймаються та нормалізуються. - `dmPolicy: "allowlist"` з порожнім `allowFrom` блокує всі DM і відхиляється валідацією config. + `channels.telegram.allowFrom` приймає числові ID користувачів Telegram. Префікси `telegram:` / `tg:` приймаються й нормалізуються. + `dmPolicy: "allowlist"` з порожнім `allowFrom` блокує всі DM і відхиляється перевіркою config. Під час налаштування запитуються лише числові ID користувачів. - Якщо ви оновилися і ваша config містить записи allowlist у форматі `@username`, виконайте `openclaw doctor --fix`, щоб перетворити їх (best-effort; потрібен токен Telegram-бота). - Якщо ви раніше покладалися на файли allowlist зі сховища підключень, `openclaw doctor --fix` може відновити записи в `channels.telegram.allowFrom` для сценаріїв allowlist (наприклад, коли `dmPolicy: "allowlist"` ще не має явних ID). + Якщо ви оновилися і ваш config містить записи allowlist у форматі `@username`, виконайте `openclaw doctor --fix`, щоб їх виправити (у режимі best-effort; потрібен токен бота Telegram). + Якщо ви раніше покладалися на файли allowlist зі сховища pairing-store, `openclaw doctor --fix` може відновити записи до `channels.telegram.allowFrom` у сценаріях allowlist (наприклад, коли `dmPolicy: "allowlist"` ще не має явних ID). - Для ботів з одним власником рекомендується `dmPolicy: "allowlist"` з явними числовими ID у `allowFrom`, щоб політика доступу стабільно зберігалася в config (замість залежності від попередніх підтверджень підключення). + Для ботів з одним власником віддавайте перевагу `dmPolicy: "allowlist"` із явними числовими ID у `allowFrom`, щоб політика доступу надійно зберігалася в config (замість залежності від попередніх схвалень підключення). - Поширена плутанина: підтвердження підключення для DM не означає, що «цей відправник авторизований усюди». - Підключення надає доступ лише до DM. Авторизація відправників у групах, як і раніше, визначається явними allowlist у config. - Якщо ви хочете модель «я один раз авторизований, і працюють і DM, і команди в групах», додайте свій числовий ID користувача Telegram до `channels.telegram.allowFrom`. + Типова плутанина: схвалення підключення для DM не означає, що «цей відправник авторизований всюди». + Підключення надає доступ лише до DM. Авторизація відправника в групах, як і раніше, визначається явними allowlist у config. + Якщо ви хочете, щоб «я авторизувався один раз, і працювали і DM, і команди в групі», додайте свій числовий ID користувача Telegram до `channels.telegram.allowFrom`. ### Як знайти свій ID користувача Telegram @@ -140,7 +140,7 @@ openclaw pairing approve telegram 2. Виконайте `openclaw logs --follow`. 3. Прочитайте `from.id`. - Офіційний спосіб через Bot API: + Офіційний метод через Bot API: ```bash curl "https://api.telegram.org/bot/getUpdates" @@ -151,12 +151,12 @@ curl "https://api.telegram.org/bot/getUpdates" - Разом застосовуються два механізми контролю: + Разом застосовуються два механізми: 1. **Які групи дозволені** (`channels.telegram.groups`) - немає config `groups`: - - з `groupPolicy: "open"`: будь-яка група може пройти перевірки ID групи - - з `groupPolicy: "allowlist"` (за замовчуванням): групи блокуються, доки ви не додасте записи в `groups` (або `"*"`) + - з `groupPolicy: "open"`: будь-яка група може пройти перевірку ID групи + - з `groupPolicy: "allowlist"` (за замовчуванням): групи блокуються, доки ви не додасте записи до `groups` (або `"*"`) - `groups` налаштовано: працює як allowlist (явні ID або `"*"`) 2. **Які відправники дозволені в групах** (`channels.telegram.groupPolicy`) @@ -164,17 +164,17 @@ curl "https://api.telegram.org/bot/getUpdates" - `allowlist` (за замовчуванням) - `disabled` - `groupAllowFrom` використовується для фільтрації відправників у групах. Якщо його не задано, Telegram використовує `allowFrom` як резервне значення. + `groupAllowFrom` використовується для фільтрації відправників у групах. Якщо його не задано, Telegram використовує `allowFrom`. Записи `groupAllowFrom` мають бути числовими ID користувачів Telegram (`telegram:` / `tg:` префікси нормалізуються). - Не вказуйте ID Telegram-груп або супергруп у `groupAllowFrom`. Від’ємні ID чатів мають бути в `channels.telegram.groups`. - Нечислові записи ігноруються під час авторизації відправників. - Межа безпеки (`2026.2.25+`): авторизація відправників у групах **не** успадковує підтвердження зі сховища підключень для DM. - Підключення залишається лише для DM. Для груп задайте `groupAllowFrom` або `allowFrom` на рівні групи/теми. - Якщо `groupAllowFrom` не задано, Telegram використовує config `allowFrom`, а не сховище підключень. - Практичний шаблон для ботів з одним власником: задайте свій ID користувача в `channels.telegram.allowFrom`, не задавайте `groupAllowFrom` і дозвольте цільові групи в `channels.telegram.groups`. - Примітка щодо runtime: якщо `channels.telegram` повністю відсутній, runtime за замовчуванням працює у fail-closed режимі з `groupPolicy="allowlist"`, якщо лише не задано явно `channels.defaults.groupPolicy`. + Не вказуйте ID чатів груп або супергруп Telegram у `groupAllowFrom`. Від’ємні ID чатів слід вказувати в `channels.telegram.groups`. + Нечислові записи ігноруються під час авторизації відправника. + Межа безпеки (`2026.2.25+`): авторизація відправника в групі **не** успадковує схвалення зі сховища pairing-store для DM. + Підключення залишається лише для DM. Для груп налаштуйте `groupAllowFrom` або `allowFrom` для конкретної групи/теми. + Якщо `groupAllowFrom` не задано, Telegram використовує config `allowFrom`, а не pairing store. + Практичний шаблон для ботів з одним власником: вкажіть свій ID користувача в `channels.telegram.allowFrom`, не задавайте `groupAllowFrom`, і дозвольте цільові групи в `channels.telegram.groups`. + Примітка щодо runtime: якщо `channels.telegram` повністю відсутній, runtime за замовчуванням використовує fail-closed `groupPolicy="allowlist"`, якщо тільки `channels.defaults.groupPolicy` не задано явно. - Приклад: дозволити будь-якого учасника в одній конкретній групі: + Приклад: дозволити будь-якому учаснику в одній конкретній групі: ```json5 { @@ -191,7 +191,7 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - Приклад: дозволити лише конкретних користувачів в одній конкретній групі: + Приклад: дозволити лише конкретним користувачам в одній конкретній групі: ```json5 { @@ -209,16 +209,16 @@ curl "https://api.telegram.org/bot/getUpdates" ``` - Поширена помилка: `groupAllowFrom` — це не allowlist груп Telegram. + Типова помилка: `groupAllowFrom` — це не allowlist груп Telegram. - - Додавайте від’ємні ID Telegram-груп або супергруп, наприклад `-1001234567890`, у `channels.telegram.groups`. - - Додавайте ID користувачів Telegram, наприклад `8734062810`, у `groupAllowFrom`, коли хочете обмежити, які люди всередині дозволеної групи можуть викликати бота. + - Вказуйте від’ємні ID груп або супергруп Telegram, як-от `-1001234567890`, у `channels.telegram.groups`. + - Вказуйте ID користувачів Telegram, як-от `8734062810`, у `groupAllowFrom`, коли хочете обмежити, які люди всередині дозволеної групи можуть звертатися до бота. - Використовуйте `groupAllowFrom: ["*"]` лише тоді, коли хочете, щоб будь-який учасник дозволеної групи міг спілкуватися з ботом. - + Відповіді в групах за замовчуванням потребують згадування. Згадування може надходити з: @@ -235,7 +235,7 @@ curl "https://api.telegram.org/bot/getUpdates" Вони оновлюють лише стан сесії. Для збереження використовуйте config. - Приклад постійної config: + Приклад постійної конфігурації: ```json5 { @@ -251,7 +251,7 @@ curl "https://api.telegram.org/bot/getUpdates" Як отримати ID групового чату: - - перешліть повідомлення з групи в `@userinfobot` / `@getidsbot` + - перешліть повідомлення з групи до `@userinfobot` / `@getidsbot` - або прочитайте `chat.id` з `openclaw logs --follow` - або перевірте Bot API `getUpdates` @@ -261,40 +261,40 @@ curl "https://api.telegram.org/bot/getUpdates" ## Поведінка runtime - Telegram належить процесу gateway. -- Маршрутизація детермінована: вхідні відповіді Telegram повертаються в Telegram (модель не вибирає канали). -- Вхідні повідомлення нормалізуються у спільний конверт каналу з метаданими відповіді та заповнювачами для медіа. +- Маршрутизація детермінована: вхідні відповіді з Telegram повертаються в Telegram (модель не вибирає канали). +- Вхідні повідомлення нормалізуються до спільного канального envelope з метаданими відповіді та заповнювачами медіа. - Групові сесії ізольовані за ID групи. Теми форуму додають `:topic:`, щоб теми залишалися ізольованими. -- DM-повідомлення можуть містити `message_thread_id`; OpenClaw маршрутизує їх за thread-aware ключами сесії та зберігає ID треду для відповідей. -- Long polling використовує runner grammY із послідовністю на рівні чату/треду. Загальна конкурентність sink runner-а використовує `agents.defaults.maxConcurrent`. -- Перезапуски watchdog для long polling спрацьовують після 120 секунд без завершеної перевірки живості `getUpdates` за замовчуванням. Збільшуйте `channels.telegram.pollingStallThresholdMs` лише якщо у вашому розгортанні все ще трапляються хибні перезапуски через зависання polling під час довготривалої роботи. Значення задається в мілісекундах і може бути від `30000` до `600000`; підтримуються перевизначення для окремих облікових записів. +- Повідомлення DM можуть містити `message_thread_id`; OpenClaw маршрутизує їх із thread-aware ключами сесії та зберігає ID потоку для відповідей. +- Long polling використовує grammY runner з послідовністю за chat/per-thread. Загальна sink-конкурентність runner використовує `agents.defaults.maxConcurrent`. +- Перезапуски watchdog для long polling спрацьовують за замовчуванням після 120 секунд без завершеної перевірки життєздатності `getUpdates`. Збільшуйте `channels.telegram.pollingStallThresholdMs` лише якщо у вашому розгортанні все ще трапляються хибні перезапуски через зависання polling під час довготривалої роботи. Значення задається в мілісекундах і дозволене в діапазоні від `30000` до `600000`; підтримуються перевизначення для окремих облікових записів. - Telegram Bot API не підтримує квитанції про прочитання (`sendReadReceipts` не застосовується). ## Довідник можливостей - OpenClaw може транслювати часткові відповіді в реальному часі: + OpenClaw може передавати часткові відповіді в реальному часі: - - прямі чати: повідомлення попереднього перегляду + `editMessageText` - - групи/теми: повідомлення попереднього перегляду + `editMessageText` + - прямі чати: попереднє повідомлення + `editMessageText` + - групи/теми: попереднє повідомлення + `editMessageText` Вимога: - - `channels.telegram.streaming` має бути `off | partial | block | progress` (за замовчуванням: `partial`) - - `progress` у Telegram відображається як `partial` (сумісність із міжканальним найменуванням) - - `streaming.preview.toolProgress` керує тим, чи оновлення інструментів/прогресу повторно використовують те саме відредаговане повідомлення попереднього перегляду (за замовчуванням: `true`). Установіть `false`, щоб зберігати окремі повідомлення інструментів/прогресу. - - застарілі `channels.telegram.streamMode` і булеві значення `streaming` автоматично відображаються + - `channels.telegram.streaming` має значення `off | partial | block | progress` (за замовчуванням: `partial`) + - `progress` у Telegram відповідає `partial` (сумісність із міжканальним найменуванням) + - `streaming.preview.toolProgress` керує тим, чи оновлення інструментів/прогресу повторно використовують те саме відредаговане попереднє повідомлення (за замовчуванням: `true`). Встановіть `false`, щоб зберегти окремі повідомлення інструментів/прогресу. + - застарілі `channels.telegram.streamMode` і булеві значення `streaming` автоматично мапуються Для відповідей лише з текстом: - - DM: OpenClaw зберігає те саме повідомлення попереднього перегляду і виконує фінальне редагування на місці (без другого повідомлення) - - група/тема: OpenClaw зберігає те саме повідомлення попереднього перегляду і виконує фінальне редагування на місці (без другого повідомлення) + - DM: OpenClaw зберігає те саме попереднє повідомлення і виконує фінальне редагування на місці (без другого повідомлення) + - група/тема: OpenClaw зберігає те саме попереднє повідомлення і виконує фінальне редагування на місці (без другого повідомлення) - Для складних відповідей (наприклад, медіа-повідомлень) OpenClaw повертається до звичайної фінальної доставки, а потім очищає повідомлення попереднього перегляду. + Для складних відповідей (наприклад, медіа-навантажень) OpenClaw повертається до звичайної фінальної доставки, а потім очищує попереднє повідомлення. - Потокова передача попереднього перегляду відокремлена від block streaming. Коли block streaming для Telegram явно увімкнено, OpenClaw пропускає preview stream, щоб уникнути подвійної потокової передачі. + Потоковий попередній перегляд відокремлений від block streaming. Якщо для Telegram явно увімкнено block streaming, OpenClaw пропускає preview stream, щоб уникнути подвійного стримінгу. - Якщо нативний транспорт чернеток недоступний або відхилений, OpenClaw автоматично повертається до `sendMessage` + `editMessageText`. + Якщо нативний transport для чернеток недоступний або відхилений, OpenClaw автоматично повертається до `sendMessage` + `editMessageText`. Потік reasoning лише для Telegram: @@ -303,21 +303,21 @@ curl "https://api.telegram.org/bot/getUpdates" - - Для вихідного тексту використовується Telegram `parse_mode: "HTML"`. + + Вихідний текст використовує Telegram `parse_mode: "HTML"`. - Текст у стилі Markdown рендериться в безпечний для Telegram HTML. - - Сирий HTML моделі екранується, щоб зменшити кількість збоїв розбору в Telegram. + - Сирий HTML моделі екранується, щоб зменшити кількість збоїв парсингу Telegram. - Якщо Telegram відхиляє розібраний HTML, OpenClaw повторює спробу як звичайний текст. - Попередній перегляд посилань увімкнено за замовчуванням і його можна вимкнути за допомогою `channels.telegram.linkPreview: false`. + Попередній перегляд посилань увімкнено за замовчуванням і його можна вимкнути через `channels.telegram.linkPreview: false`. - + Реєстрація меню команд Telegram виконується під час запуску через `setMyCommands`. - Нативні команди за замовчуванням: + Налаштування нативних команд за замовчуванням: - `commands.native: "auto"` вмикає нативні команди для Telegram @@ -328,7 +328,7 @@ curl "https://api.telegram.org/bot/getUpdates" channels: { telegram: { customCommands: [ - { command: "backup", description: "Git backup" }, + { command: "backup", description: "Резервне копіювання Git" }, { command: "generate", description: "Створити зображення" }, ], }, @@ -338,38 +338,38 @@ curl "https://api.telegram.org/bot/getUpdates" Правила: - - назви нормалізуються (прибирається початковий `/`, переводяться в нижній регістр) + - імена нормалізуються (видаляється початковий `/`, нижній регістр) - допустимий шаблон: `a-z`, `0-9`, `_`, довжина `1..32` - - користувацькі команди не можуть перевизначати нативні команди - - конфлікти/дублікати пропускаються та журналюються + - власні команди не можуть перевизначати нативні команди + - конфлікти/дублікати пропускаються та логуються Примітки: - - користувацькі команди — це лише записи меню; вони не реалізують поведінку автоматично - - команди Plugin/Skills можуть і далі працювати при ручному введенні, навіть якщо вони не показані в меню Telegram + - власні команди — це лише записи меню; вони не реалізують поведінку автоматично + - команди plugin/Skills однаково можуть працювати при введенні вручну, навіть якщо вони не показані в меню Telegram - Якщо нативні команди вимкнено, вбудовані команди видаляються. Користувацькі команди/команди Plugin все ще можуть реєструватися, якщо це налаштовано. + Якщо нативні команди вимкнено, вбудовані команди видаляються. Власні команди/команди plugin усе ще можуть реєструватися, якщо це налаштовано. - Поширені збої налаштування: + Типові збої під час налаштування: - - `setMyCommands failed` з `BOT_COMMANDS_TOO_MUCH` означає, що меню Telegram усе ще переповнене навіть після скорочення; зменште кількість користувацьких команд/команд Plugin/Skills або вимкніть `channels.telegram.commands.native`. - - `setMyCommands failed` з помилками network/fetch зазвичай означає, що вихідний DNS/HTTPS до `api.telegram.org` заблокований. + - `setMyCommands failed` з `BOT_COMMANDS_TOO_MUCH` означає, що меню Telegram усе ще переповнене після скорочення; зменште кількість власних команд/команд plugin/Skills або вимкніть `channels.telegram.commands.native`. + - `setMyCommands failed` з помилками network/fetch зазвичай означає, що вихідні DNS/HTTPS-з’єднання до `api.telegram.org` заблоковано. - ### Команди підключення пристроїв (`device-pair` Plugin) + ### Команди підключення пристрою (`device-pair` Plugin) Коли встановлено Plugin `device-pair`: 1. `/pair` генерує код налаштування 2. вставте код у застосунок iOS - 3. `/pair pending` показує список запитів, що очікують на розгляд (включно з role/scopes) - 4. підтвердьте запит: - - `/pair approve ` для явного підтвердження + 3. `/pair pending` показує список запитів, що очікують на розгляд (включно з роллю/областями доступу) + 4. схваліть запит: + - `/pair approve ` для явного схвалення - `/pair approve`, коли є лише один запит, що очікує на розгляд - `/pair approve latest` для найновішого - Код налаштування містить короткоживучий bootstrap token. Вбудований bootstrap handoff зберігає токен primary node на `scopes: []`; будь-який переданий operator token залишається обмеженим `operator.approvals`, `operator.read`, `operator.talk.secrets` і `operator.write`. Перевірки bootstrap scope мають префікс role, тому цей operator allowlist задовольняє лише operator-запити; для не-operator ролей усе ще потрібні scopes під власним префіксом ролі. + Код налаштування містить короткоживучий bootstrap-токен. Вбудована bootstrap-передача зберігає токен первинного Node на рівні `scopes: []`; будь-який переданий токен оператора залишається обмеженим до `operator.approvals`, `operator.read`, `operator.talk.secrets` і `operator.write`. Перевірки bootstrap-областей доступу мають префікс ролі, тому цей allowlist оператора задовольняє лише запити оператора; ролі, що не є оператором, усе ще потребують областей доступу під префіксом власної ролі. - Якщо пристрій повторює спробу зі зміненими даними auth (наприклад, role/scopes/public key), попередній запит, що очікує на розгляд, заміщується, а новий запит використовує інший `requestId`. Перед підтвердженням знову виконайте `/pair pending`. + Якщо пристрій повторює спробу зі зміненими даними автентифікації (наприклад, роль/області доступу/публічний ключ), попередній запит, що очікує на розгляд, заміщується, а новий запит використовує інший `requestId`. Перед схваленням знову виконайте `/pair pending`. Докладніше: [Підключення](/uk/channels/pairing#pair-via-telegram-recommended-for-ios). @@ -416,7 +416,7 @@ curl "https://api.telegram.org/bot/getUpdates" - `all` - `allowlist` (за замовчуванням) - Застаріле `capabilities: ["inlineButtons"]` відображається як `inlineButtons: "all"`. + Застаріле `capabilities: ["inlineButtons"]` мапується на `inlineButtons: "all"`. Приклад дії повідомлення: @@ -441,33 +441,33 @@ curl "https://api.telegram.org/bot/getUpdates" - + Дії інструментів Telegram включають: - - `sendMessage` (`to`, `content`, необов’язкові `mediaUrl`, `replyToMessageId`, `messageThreadId`) + - `sendMessage` (`to`, `content`, необов’язково `mediaUrl`, `replyToMessageId`, `messageThreadId`) - `react` (`chatId`, `messageId`, `emoji`) - `deleteMessage` (`chatId`, `messageId`) - `editMessage` (`chatId`, `messageId`, `content`) - - `createForumTopic` (`chatId`, `name`, необов’язкові `iconColor`, `iconCustomEmojiId`) + - `createForumTopic` (`chatId`, `name`, необов’язково `iconColor`, `iconCustomEmojiId`) - Дії повідомлень каналу надають зручні псевдоніми (`send`, `react`, `delete`, `edit`, `sticker`, `sticker-search`, `topic-create`). + Дії повідомлень каналу надають зручні аліаси (`send`, `react`, `delete`, `edit`, `sticker`, `sticker-search`, `topic-create`). - Керування доступом: + Керування через gating: - `channels.telegram.actions.sendMessage` - `channels.telegram.actions.deleteMessage` - `channels.telegram.actions.reactions` - `channels.telegram.actions.sticker` (за замовчуванням: вимкнено) - Примітка: `edit` і `topic-create` зараз увімкнені за замовчуванням і не мають окремих перемикачів `channels.telegram.actions.*`. - Надсилання в runtime використовує активний snapshot config/secrets (startup/reload), тому шляхи дій не виконують ad-hoc повторне визначення `SecretRef` для кожного надсилання. + Примітка: `edit` і `topic-create` наразі увімкнені за замовчуванням і не мають окремих перемикачів `channels.telegram.actions.*`. + Надсилання під час runtime використовує активний знімок config/secrets (startup/reload), тому шляхи дій не виконують ad-hoc повторне визначення `SecretRef` для кожного надсилання. Семантика видалення реакцій: [/tools/reactions](/uk/tools/reactions) - - Telegram підтримує явні теги тредів відповідей у згенерованому виводі: + + Telegram підтримує явні теги потоків відповідей у згенерованому виводі: - `[[reply_to_current]]` відповідає на повідомлення, яке ініціювало дію - `[[reply_to:]]` відповідає на конкретний ID повідомлення Telegram @@ -478,27 +478,27 @@ curl "https://api.telegram.org/bot/getUpdates" - `first` - `all` - Примітка: `off` вимикає неявний трединг відповідей. Явні теги `[[reply_to_*]]` усе одно враховуються. + Примітка: `off` вимикає неявне формування потоку відповідей. Явні теги `[[reply_to_*]]` усе одно враховуються. - + Супергрупи форуму: - ключі сесій тем додають `:topic:` - - відповіді й набір тексту націлюються на тред теми + - відповіді та індикатор набору тексту спрямовуються в потік теми - шлях config теми: `channels.telegram.groups..topics.` - Особливий випадок для загальної теми (`threadId=1`): + Спеціальний випадок загальної теми (`threadId=1`): - - під час надсилання повідомлень `message_thread_id` пропускається (Telegram відхиляє `sendMessage(...thread_id=1)`) - - дії набору тексту все ще включають `message_thread_id` + - надсилання повідомлень пропускає `message_thread_id` (Telegram відхиляє `sendMessage(...thread_id=1)`) + - дії набору тексту все одно включають `message_thread_id` - Успадкування тем: записи тем успадковують налаштування групи, якщо не перевизначені (`requireMention`, `allowFrom`, `skills`, `systemPrompt`, `enabled`, `groupPolicy`). - `agentId` належить лише темі й не успадковується з налаштувань групи за замовчуванням. + Успадкування тем: записи тем успадковують налаштування групи, якщо їх не перевизначено (`requireMention`, `allowFrom`, `skills`, `systemPrompt`, `enabled`, `groupPolicy`). + `agentId` є параметром лише теми й не успадковується з типових налаштувань групи. - **Маршрутизація агентів для окремих тем**: Кожна тема може маршрутизуватися до іншого агента через `agentId` у config теми. Це дає кожній темі власний ізольований workspace, пам’ять і сесію. Приклад: + **Маршрутизація агента для окремої теми**: кожна тема може маршрутизуватися до іншого агента, якщо задати `agentId` у config теми. Це дає кожній темі власний ізольований робочий простір, пам’ять і сесію. Приклад: ```json5 { @@ -509,7 +509,7 @@ curl "https://api.telegram.org/bot/getUpdates" topics: { "1": { agentId: "main" }, // Загальна тема → агент main "3": { agentId: "zu" }, // Тема розробки → агент zu - "5": { agentId: "coder" } // Рев’ю коду → агент coder + "5": { agentId: "coder" } // Code review → агент coder } } } @@ -520,7 +520,7 @@ curl "https://api.telegram.org/bot/getUpdates" Тоді кожна тема має власний ключ сесії: `agent:zu:telegram:group:-1001234567890:topic:3` - **Постійна прив’язка тем ACP**: Теми форуму можуть закріплювати сесії harness ACP через типізовані ACP-прив’язки верхнього рівня: + **Постійна прив’язка тем ACP**: теми форуму можуть закріплювати сесії harness ACP через typed ACP bindings верхнього рівня: - `bindings[]` з `type: "acp"` і `match.channel: "telegram"` @@ -571,23 +571,23 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - Наразі це обмежено темами форуму в групах і супергрупах. + Наразі це обмежено темами форумів у групах і супергрупах. - **Запуск ACP, прив’язаний до треду, з чату**: + **Запуск ACP, прив’язаний до потоку, з чату**: - - `/acp spawn --thread here|auto` може прив’язати поточну тему Telegram до нової ACP-сесії. - - Наступні повідомлення в темі маршрутизуються безпосередньо до прив’язаної ACP-сесії (без потреби в `/acp steer`). - - Після успішної прив’язки OpenClaw закріплює повідомлення-підтвердження запуску в темі. - - Потрібно `channels.telegram.threadBindings.spawnAcpSessions=true`. + - `/acp spawn --thread here|auto` може прив’язати поточну тему Telegram до нової сесії ACP. + - Наступні повідомлення в темі маршрутизуються безпосередньо до прив’язаної сесії ACP (без потреби в `/acp steer`). + - Після успішної прив’язки OpenClaw закріплює повідомлення з підтвердженням запуску в цій темі. + - Потребує `channels.telegram.threadBindings.spawnAcpSessions=true`. Контекст шаблону включає: - `MessageThreadId` - `IsForum` - Поведінка DM-тредів: + Поведінка потоку DM: - - приватні чати з `message_thread_id` зберігають DM-маршрутизацію, але використовують thread-aware ключі сесій/цілі відповідей. + - приватні чати з `message_thread_id` зберігають маршрутизацію DM, але використовують thread-aware ключі сесії/цілі відповідей. @@ -613,7 +613,7 @@ curl "https://api.telegram.org/bot/getUpdates" ### Відеоповідомлення - Telegram розрізняє відеофайли та video note. + Telegram розрізняє відеофайли та video notes. Приклад дії повідомлення: @@ -627,13 +627,13 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - Video note не підтримують підписи; наданий текст повідомлення надсилається окремо. + Video notes не підтримують підписи; наданий текст повідомлення надсилається окремо. ### Стікери Обробка вхідних стікерів: - - статичний WEBP: завантажується та обробляється (заповнювач ``) + - статичний WEBP: завантажується й обробляється (заповнювач ``) - анімований TGS: пропускається - відео WEBM: пропускається @@ -676,7 +676,7 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - Пошук кешованих стікерів: + Пошук у кешованих стікерах: ```json5 { @@ -690,9 +690,9 @@ curl "https://api.telegram.org/bot/getUpdates" - Реакції Telegram надходять як оновлення `message_reaction` (окремо від payload повідомлень). + Реакції Telegram надходять як оновлення `message_reaction` (окремо від корисних навантажень повідомлень). - Коли цю можливість увімкнено, OpenClaw ставить у чергу системні події на кшталт: + Коли цю функцію ввімкнено, OpenClaw ставить у чергу системні події на кшталт: - `Telegram reaction added: 👍 by Alice (@alice) on msg 42` @@ -704,16 +704,16 @@ curl "https://api.telegram.org/bot/getUpdates" Примітки: - `own` означає лише реакції користувачів на повідомлення, надіслані ботом (best-effort через кеш надісланих повідомлень). - - Події реакцій усе одно дотримуються контролю доступу Telegram (`dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`); неавторизовані відправники відкидаються. - - Telegram не надає ID тредів в оновленнях реакцій. - - нефорумні групи маршрутизуються до сесії групового чату - - форумні групи маршрутизуються до сесії загальної теми групи (`:topic:1`), а не до точної початкової теми + - Події реакцій усе одно поважають механізми контролю доступу Telegram (`dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`); від неавторизованих відправників вони відкидаються. + - Telegram не надає ID потоку в оновленнях реакцій. + - групи без форуму маршрутизуються до сесії групового чату + - групи форуму маршрутизуються до сесії загальної теми групи (`:topic:1`), а не до точної початкової теми - `allowed_updates` для polling/webhook автоматично включають `message_reaction`. + `allowed_updates` для polling/Webhook-ів автоматично включають `message_reaction`. - + `ackReaction` надсилає emoji-підтвердження, поки OpenClaw обробляє вхідне повідомлення. Порядок визначення: @@ -721,22 +721,22 @@ curl "https://api.telegram.org/bot/getUpdates" - `channels.telegram.accounts..ackReaction` - `channels.telegram.ackReaction` - `messages.ackReaction` - - резервне emoji з identity агента (`agents.list[].identity.emoji`, інакше "👀") + - резервний emoji з ідентичності агента (`agents.list[].identity.emoji`, інакше "👀") Примітки: - - Telegram очікує emoji Unicode (наприклад, "👀"). + - Telegram очікує unicode emoji (наприклад, "👀"). - Використовуйте `""`, щоб вимкнути реакцію для каналу або облікового запису. - Записи config каналу увімкнені за замовчуванням (`configWrites !== false`). + Записи в config каналу увімкнені за замовчуванням (`configWrites !== false`). Записи, ініційовані Telegram, включають: - події міграції груп (`migrate_to_chat_id`) для оновлення `channels.telegram.groups` - - `/config set` і `/config unset` (потрібне ввімкнення команд) + - `/config set` і `/config unset` (потребує ввімкнення команд) Вимкнення: @@ -752,39 +752,39 @@ curl "https://api.telegram.org/bot/getUpdates" - + За замовчуванням: long polling. - Режим Webhook: + Режим Webhook-ів: - задайте `channels.telegram.webhookUrl` - - задайте `channels.telegram.webhookSecret` (обов’язково, коли задано URL webhook) + - задайте `channels.telegram.webhookSecret` (обов’язково, якщо задано URL Webhook-а) - необов’язково `channels.telegram.webhookPath` (за замовчуванням `/telegram-webhook`) - необов’язково `channels.telegram.webhookHost` (за замовчуванням `127.0.0.1`) - необов’язково `channels.telegram.webhookPort` (за замовчуванням `8787`) - Локальний listener за замовчуванням для режиму webhook прив’язується до `127.0.0.1:8787`. + Типовий локальний listener для режиму Webhook-ів прив’язується до `127.0.0.1:8787`. - Якщо ваша публічна кінцева точка відрізняється, розмістіть перед нею reverse proxy і вкажіть `webhookUrl` на публічний URL. - Установіть `webhookHost` (наприклад, `0.0.0.0`), коли вам свідомо потрібен зовнішній вхідний доступ. + Якщо ваша публічна кінцева точка відрізняється, розмістіть попереду reverse proxy і вкажіть публічний URL у `webhookUrl`. + Установіть `webhookHost` (наприклад, `0.0.0.0`), якщо вам навмисно потрібен зовнішній вхідний доступ. - `channels.telegram.textChunkLimit` за замовчуванням має значення 4000. - - `channels.telegram.chunkMode="newline"` надає перевагу межам абзаців (порожнім рядкам) перед поділом за довжиною. - - `channels.telegram.mediaMaxMb` (за замовчуванням 100) обмежує розмір вхідних і вихідних медіафайлів Telegram. + - `channels.telegram.chunkMode="newline"` віддає перевагу межам абзаців (порожнім рядкам) перед розбиттям за довжиною. + - `channels.telegram.mediaMaxMb` (за замовчуванням 100) обмежує розмір вхідних і вихідних медіа Telegram. - `channels.telegram.timeoutSeconds` перевизначає тайм-аут клієнта Telegram API (якщо не задано, застосовується значення grammY за замовчуванням). - - `channels.telegram.pollingStallThresholdMs` за замовчуванням дорівнює `120000`; налаштовуйте в межах `30000`–`600000` лише для хибнопозитивних перезапусків через зависання polling. - - історія контексту групи використовує `channels.telegram.historyLimit` або `messages.groupChat.historyLimit` (за замовчуванням 50); `0` вимикає її. - - додатковий контекст reply/quote/forward наразі передається як отримано. - - allowlist Telegram насамперед обмежують, хто може викликати агента, а не є повноцінною межею редагування додаткового контексту. - - елементи керування історією DM: + - `channels.telegram.pollingStallThresholdMs` за замовчуванням дорівнює `120000`; налаштовуйте в межах від `30000` до `600000` лише для хибнопозитивних перезапусків через зависання polling. + - історія контексту групи використовує `channels.telegram.historyLimit` або `messages.groupChat.historyLimit` (за замовчуванням 50); `0` вимикає. + - додатковий контекст reply/quote/forward наразі передається в отриманому вигляді. + - allowlist-списки Telegram насамперед керують тим, хто може активувати агента, а не є повною межею редагування додаткового контексту. + - керування історією DM: - `channels.telegram.dmHistoryLimit` - `channels.telegram.dms[""].historyLimit` - config `channels.telegram.retry` застосовується до допоміжних функцій надсилання Telegram (CLI/tools/actions) для відновлюваних вихідних помилок API. - Ціллю надсилання в CLI може бути числовий ID чату або ім’я користувача: + Ціль CLI для надсилання може бути числовим ID чату або username: ```bash openclaw message send --channel telegram --target 123456789 --message "hi" @@ -808,72 +808,73 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ - `--poll-public` - `--thread-id` для тем форуму (або використовуйте ціль `:topic:`) - Надсилання в Telegram також підтримує: + Надсилання Telegram також підтримує: - - `--buttons` для вбудованих клавіатур, коли це дозволяє `channels.telegram.capabilities.inlineButtons` - - `--force-document`, щоб надсилати вихідні зображення та GIF як документи, а не як стиснені фото чи анімовані медіазавантаження + - `--presentation` з блоками `buttons` для вбудованих клавіатур, коли це дозволяє `channels.telegram.capabilities.inlineButtons` + - `--pin` або `--delivery '{"pin":true}'`, щоб запитати закріплену доставку, коли бот може закріплювати в цьому чаті + - `--force-document`, щоб надсилати вихідні зображення та GIF як документи замість стиснених фото або завантажень анімованих медіа - Керування доступом до дій: + Керування діями: - `channels.telegram.actions.sendMessage=false` вимикає вихідні повідомлення Telegram, включно з опитуваннями - `channels.telegram.actions.poll=false` вимикає створення опитувань Telegram, залишаючи звичайне надсилання увімкненим - - Telegram підтримує підтвердження exec у DM затверджувачів і за потреби може надсилати запити на підтвердження в початковий чат або тему. + + Telegram підтримує схвалення exec у DM схвалювачів і за потреби може публікувати запити на схвалення у вихідному чаті або темі. Шлях config: - `channels.telegram.execApprovals.enabled` - - `channels.telegram.execApprovals.approvers` (необов’язково; інакше використовуються числові ID власників, виведені з `allowFrom` і прямого `defaultTo`, де це можливо) + - `channels.telegram.execApprovals.approvers` (необов’язково; за відсутності використовується резервне визначення з числових ID власника, виведених із `allowFrom` і прямого `defaultTo`, коли це можливо) - `channels.telegram.execApprovals.target` (`dm` | `channel` | `both`, за замовчуванням: `dm`) - `agentFilter`, `sessionFilter` - Затверджувачі мають бути числовими ID користувачів Telegram. Telegram автоматично вмикає нативні підтвердження exec, коли `enabled` не задано або має значення `"auto"` і можна визначити принаймні одного затверджувача — або з `execApprovals.approvers`, або з числової config власника облікового запису (`allowFrom` і `defaultTo` для прямих повідомлень). Установіть `enabled: false`, щоб явно вимкнути Telegram як нативний клієнт підтвердження. Інакше запити на підтвердження повертаються до інших налаштованих маршрутів підтвердження або до резервної політики підтвердження exec. + Схвалювачі мають бути числовими ID користувачів Telegram. Telegram автоматично вмикає нативні схвалення exec, коли `enabled` не задано або дорівнює `"auto"` і можна визначити принаймні одного схвалювача — або з `execApprovals.approvers`, або з числового config власника облікового запису (`allowFrom` і `defaultTo` для прямих повідомлень). Установіть `enabled: false`, щоб явно вимкнути Telegram як нативний клієнт схвалення. В інших випадках запити на схвалення повертаються до інших налаштованих маршрутів схвалення або до fallback-політики схвалення exec. - Telegram також відображає спільні кнопки підтвердження, які використовують інші чат-канали. Нативний адаптер Telegram переважно додає маршрутизацію DM затверджувачів, fanout у канали/теми та підказки набору тексту перед доставкою. - Коли ці кнопки присутні, вони є основним UX підтвердження; OpenClaw - має включати ручну команду `/approve` лише тоді, коли результат інструмента вказує, - що підтвердження в чаті недоступні або ручне підтвердження — єдиний шлях. + Telegram також рендерить спільні кнопки схвалення, які використовують інші чат-канали. Нативний адаптер Telegram переважно додає маршрутизацію DM схвалювачів, fanout у канали/теми та підказки набору тексту перед доставкою. + Коли ці кнопки присутні, вони є основним UX для схвалення; OpenClaw + має включати ручну команду `/approve` лише тоді, коли результат інструмента каже, + що схвалення в чаті недоступні або ручне схвалення — єдиний шлях. Правила доставки: - - `target: "dm"` надсилає запити на підтвердження лише в DM визначених затверджувачів - - `target: "channel"` надсилає запит назад у початковий чат/тему Telegram - - `target: "both"` надсилає і в DM затверджувачів, і в початковий чат/тему + - `target: "dm"` надсилає запити на схвалення лише в DM визначених схвалювачів + - `target: "channel"` надсилає запит назад у вихідний чат/тему Telegram + - `target: "both"` надсилає і в DM схвалювачів, і у вихідний чат/тему - Лише визначені затверджувачі можуть підтверджувати або відхиляти. Не-затверджувачі не можуть використовувати `/approve` і не можуть використовувати кнопки підтвердження Telegram. + Лише визначені схвалювачі можуть схвалювати або відхиляти. Користувачі, які не є схвалювачами, не можуть використовувати `/approve` і не можуть користуватися кнопками схвалення Telegram. - Поведінка визначення підтвердження: + Поведінка визначення схвалення: - - ID з префіксом `plugin:` завжди визначаються через підтвердження plugin. + - ID з префіксом `plugin:` завжди визначаються через схвалення plugin. - Інші ID спочатку пробують `exec.approval.resolve`. - - Якщо Telegram також авторизований для підтверджень plugin і gateway повідомляє, - що підтвердження exec невідоме або сплило, Telegram один раз повторює спробу через + - Якщо Telegram також авторизований для схвалень plugin і gateway каже, + що схвалення exec невідоме/прострочене, Telegram один раз повторює спробу через `plugin.approval.resolve`. - - Реальні відмови/помилки підтвердження exec не переходять мовчки до визначення - підтвердження plugin. + - Реальні відмови/помилки схвалення exec не переходять мовчки до + визначення схвалення plugin. - Доставка в канал показує текст команди в чаті, тому вмикайте `channel` або `both` лише в довірених групах/темах. Коли запит потрапляє в тему форуму, OpenClaw зберігає тему і для запиту на підтвердження, і для подальшого повідомлення після підтвердження. За замовчуванням підтвердження exec спливають через 30 хвилин. + Доставка в канал показує текст команди в чаті, тому вмикайте `channel` або `both` лише в довірених групах/темах. Коли запит потрапляє в тему форуму, OpenClaw зберігає тему як для запиту на схвалення, так і для подальших дій після схвалення. За замовчуванням схвалення exec спливають через 30 хвилин. - Вбудовані кнопки підтвердження також залежать від того, чи `channels.telegram.capabilities.inlineButtons` дозволяє цільову поверхню (`dm`, `group` або `all`). + Вбудовані кнопки схвалення також залежать від того, чи дозволяє `channels.telegram.capabilities.inlineButtons` цільову поверхню (`dm`, `group` або `all`). - Пов’язана документація: [Підтвердження exec](/uk/tools/exec-approvals) + Пов’язана документація: [Схвалення exec](/uk/tools/exec-approvals) -## Параметри відповіді на помилки +## Керування відповідями про помилки -Коли агент стикається з помилкою доставки або провайдера, Telegram може або відповісти текстом помилки, або приховати його. Цю поведінку контролюють два ключі config: +Коли агент стикається з помилкою доставки або провайдера, Telegram може або відповісти текстом помилки, або приховати її. Цю поведінку контролюють два ключі config: | Key | Values | Default | Description | | ----------------------------------- | ----------------- | ------- | ----------------------------------------------------------------------------------------------- | -| `channels.telegram.errorPolicy` | `reply`, `silent` | `reply` | `reply` надсилає дружнє повідомлення про помилку в чат. `silent` повністю пригнічує відповіді про помилки. | -| `channels.telegram.errorCooldownMs` | number (ms) | `60000` | Мінімальний час між відповідями про помилки в той самий чат. Запобігає спаму помилками під час збоїв. | +| `channels.telegram.errorPolicy` | `reply`, `silent` | `reply` | `reply` надсилає до чату дружнє повідомлення про помилку. `silent` повністю пригнічує відповіді про помилки. | +| `channels.telegram.errorCooldownMs` | number (ms) | `60000` | Мінімальний час між відповідями про помилки в тому самому чаті. Запобігає спаму помилками під час збоїв. | -Підтримуються перевизначення для окремих облікових записів, груп і тем (та сама схема успадкування, що й для інших ключів config Telegram). +Підтримуються перевизначення для окремого облікового запису, групи й теми (те саме успадкування, що й для інших ключів config Telegram). ```json5 { @@ -883,7 +884,7 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ errorCooldownMs: 120000, groups: { "-1001234567890": { - errorPolicy: "silent", // пригнічувати помилки в цій групі + errorPolicy: "silent", // приглушити помилки в цій групі }, }, }, @@ -894,42 +895,42 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ ## Усунення несправностей - + - - Якщо `requireMention=false`, режим приватності Telegram має дозволяти повну видимість. + - Якщо `requireMention=false`, режим конфіденційності Telegram має дозволяти повну видимість. - BotFather: `/setprivacy` -> Disable - - потім видаліть і знову додайте бота в групу + - потім видаліть бота з групи й додайте знову - `openclaw channels status` попереджає, коли config очікує повідомлення групи без згадування. - - `openclaw channels status --probe` може перевіряти явні числові ID груп; wildcard `"*"` не можна перевірити на членство. + - `openclaw channels status --probe` може перевіряти явні числові ID груп; для wildcard `"*"` перевірка членства недоступна. - швидкий тест сесії: `/activation always`. - + - - коли існує `channels.telegram.groups`, група має бути вказана (або має бути `"*"`) + - коли існує `channels.telegram.groups`, група має бути вказана в списку (або має бути `"*"`) - перевірте членство бота в групі - - перегляньте журнали: `openclaw logs --follow` для причин пропуску + - перегляньте логи: `openclaw logs --follow`, щоб побачити причини пропуску - + - авторизуйте свою ідентичність відправника (підключення та/або числовий `allowFrom`) - авторизація команд усе одно застосовується, навіть коли політика групи `open` - - `setMyCommands failed` з `BOT_COMMANDS_TOO_MUCH` означає, що нативне меню має забагато записів; зменште кількість користувацьких команд/команд Plugin/Skills або вимкніть нативні меню - - `setMyCommands failed` з помилками network/fetch зазвичай вказує на проблеми доступності DNS/HTTPS до `api.telegram.org` + - `setMyCommands failed` з `BOT_COMMANDS_TOO_MUCH` означає, що нативне меню має забагато записів; зменште кількість власних команд/команд plugin/Skills або вимкніть нативні меню + - `setMyCommands failed` з помилками network/fetch зазвичай указує на проблеми досяжності DNS/HTTPS до `api.telegram.org` - Node 22+ + власний fetch/proxy можуть спричиняти негайне переривання, якщо типи AbortSignal не збігаються. - - Деякі хости спочатку визначають `api.telegram.org` в IPv6; несправний вихідний IPv6 може спричиняти переривчасті збої Telegram API. - - Якщо журнали містять `TypeError: fetch failed` або `Network request for 'getUpdates' failed!`, OpenClaw тепер повторює їх як відновлювані помилки мережі. - - Якщо журнали містять `Polling stall detected`, OpenClaw перезапускає polling і перебудовує транспорт Telegram після 120 секунд без завершеної перевірки живості long-poll за замовчуванням. - - Збільшуйте `channels.telegram.pollingStallThresholdMs` лише тоді, коли довготривалі виклики `getUpdates` є здоровими, але ваш хост усе одно повідомляє про хибнопозитивні перезапуски через зависання polling. Стійкі зависання зазвичай вказують на проблеми з proxy, DNS, IPv6 або TLS egress між хостом і `api.telegram.org`. - - На VPS-хостах із нестабільним прямим egress/TLS маршрутизуйте виклики Telegram API через `channels.telegram.proxy`: + - Деякі хости спочатку резолвлять `api.telegram.org` в IPv6; несправний вихідний IPv6 може спричиняти періодичні збої Telegram API. + - Якщо логи містять `TypeError: fetch failed` або `Network request for 'getUpdates' failed!`, OpenClaw тепер повторює їх як відновлювані мережеві помилки. + - Якщо логи містять `Polling stall detected`, OpenClaw перезапускає polling і перебудовує транспорт Telegram після 120 секунд без завершеної перевірки життєздатності long poll за замовчуванням. + - Збільшуйте `channels.telegram.pollingStallThresholdMs` лише тоді, коли довготривалі виклики `getUpdates` працюють нормально, але ваш хост усе ще повідомляє про хибнопозитивні перезапуски через зависання polling. Стійкі зависання зазвичай вказують на проблеми proxy, DNS, IPv6 або TLS-виходу між хостом і `api.telegram.org`. + - На VPS-хостах із нестабільним прямим вихідним трафіком/TLS спрямовуйте виклики Telegram API через `channels.telegram.proxy`: ```yaml channels: @@ -937,8 +938,8 @@ channels: proxy: socks5://:@proxy-host:1080 ``` - - Node 22+ за замовчуванням використовує `autoSelectFamily=true` (крім WSL2) і `dnsResultOrder=ipv4first`. - - Якщо ваш хост — WSL2 або явно краще працює лише з IPv4, примусово задайте вибір family: + - У Node 22+ за замовчуванням використовується `autoSelectFamily=true` (крім WSL2) і `dnsResultOrder=ipv4first`. + - Якщо ваш хост — WSL2 або явно краще працює лише з IPv4, примусово задайте вибір сімейства: ```yaml channels: @@ -947,11 +948,11 @@ channels: autoSelectFamily: false ``` - - Відповіді в діапазоні benchmark RFC 2544 (`198.18.0.0/15`) уже дозволені + - Відповіді діапазону benchmark RFC 2544 (`198.18.0.0/15`) уже дозволені за замовчуванням для завантаження медіа Telegram. Якщо довірений fake-IP або transparent proxy переписує `api.telegram.org` на якусь іншу - приватну/внутрішню/special-use адресу під час завантаження медіа, ви можете - явно ввімкнути обхід лише для Telegram: + приватну/внутрішню/спеціальну адресу під час завантаження медіа, ви можете + увімкнути обхід лише для Telegram: ```yaml channels: @@ -960,21 +961,25 @@ channels: dangerouslyAllowPrivateNetwork: true ``` - - Такий самий явний параметр доступний для окремого облікового запису в + - Те саме явне ввімкнення доступне для окремого облікового запису в `channels.telegram.accounts..network.dangerouslyAllowPrivateNetwork`. - - Якщо ваш proxy визначає медіахости Telegram у `198.18.x.x`, спочатку залиште - небезпечний прапорець вимкненим. Медіа Telegram уже дозволяє діапазон - benchmark RFC 2544 за замовчуванням. + - Якщо ваш proxy резолвить медіахости Telegram в `198.18.x.x`, спочатку залиште + небезпечний прапорець вимкненим. Медіа Telegram уже дозволяє діапазон benchmark RFC 2544 + за замовчуванням. - `channels.telegram.network.dangerouslyAllowPrivateNetwork` послаблює захист від SSRF для медіа Telegram. Використовуйте його лише в довірених керованих оператором середовищах proxy, таких як fake-IP routing у Clash, Mihomo або Surge, коли вони синтезують приватні або special-use відповіді поза межами benchmark-діапазону RFC 2544. Для звичайного публічного доступу до Telegram через інтернет залишайте його вимкненим. + `channels.telegram.network.dangerouslyAllowPrivateNetwork` послаблює захист Telegram + media SSRF. Використовуйте це лише в довірених середовищах proxy, якими керує оператор, + таких як Clash, Mihomo або маршрутизація fake-IP у Surge, коли вони синтезують приватні + або спеціальні відповіді поза межами діапазону benchmark RFC 2544. Для звичайного + публічного доступу Telegram через інтернет залишайте це вимкненим. - - Перевизначення через env (тимчасово): + - Перевизначення через середовище (тимчасово): - `OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1` - `OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1` - `OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first` - - Перевірка DNS-відповідей: + - Перевірте відповіді DNS: ```bash dig +short api.telegram.org A @@ -984,7 +989,7 @@ dig +short api.telegram.org AAAA -Додаткова допомога: [Усунення несправностей каналу](/uk/channels/troubleshooting). +Більше довідки: [Усунення проблем каналу](/uk/channels/troubleshooting). ## Вказівники на довідник config Telegram @@ -994,78 +999,78 @@ dig +short api.telegram.org AAAA - `channels.telegram.botToken`: токен бота (BotFather). - `channels.telegram.tokenFile`: читати токен зі шляху до звичайного файлу. Символічні посилання відхиляються. - `channels.telegram.dmPolicy`: `pairing | allowlist | open | disabled` (за замовчуванням: pairing). -- `channels.telegram.allowFrom`: allowlist DM (числові ID користувачів Telegram). `allowlist` вимагає щонайменше один ID відправника. `open` вимагає `"*"`. `openclaw doctor --fix` може перетворювати застарілі записи `@username` на ID і може відновлювати записи allowlist з файлів pairing-store у сценаріях міграції allowlist. -- `channels.telegram.actions.poll`: увімкнути або вимкнути створення опитувань Telegram (за замовчуванням: увімкнено; усе ще потребує `sendMessage`). -- `channels.telegram.defaultTo`: ціль Telegram за замовчуванням, яку використовує CLI `--deliver`, коли явний `--reply-to` не вказано. +- `channels.telegram.allowFrom`: allowlist для DM (числові ID користувачів Telegram). `allowlist` потребує принаймні одного ID відправника. `open` потребує `"*"`. `openclaw doctor --fix` може перетворити застарілі записи `@username` на ID і відновити записи allowlist із файлів pairing-store у сценаріях міграції allowlist. +- `channels.telegram.actions.poll`: увімкнути або вимкнути створення опитувань Telegram (за замовчуванням: увімкнено; усе одно потребує `sendMessage`). +- `channels.telegram.defaultTo`: ціль Telegram за замовчуванням, яку використовує CLI `--deliver`, коли явний `--reply-to` не задано. - `channels.telegram.groupPolicy`: `open | allowlist | disabled` (за замовчуванням: allowlist). -- `channels.telegram.groupAllowFrom`: allowlist відправників у групах (числові ID користувачів Telegram). `openclaw doctor --fix` може перетворювати застарілі записи `@username` на ID. Нечислові записи ігноруються під час auth. Авторизація груп не використовує резервний варіант через DM pairing-store (`2026.2.25+`). -- Пріоритет для кількох облікових записів: - - Коли налаштовано два або більше ID облікових записів, задайте `channels.telegram.defaultAccount` (або включіть `channels.telegram.accounts.default`), щоб явно визначити маршрутизацію за замовчуванням. - - Якщо не задано жодного з них, OpenClaw використовує перший нормалізований ID облікового запису, а `openclaw doctor` показує попередження. +- `channels.telegram.groupAllowFrom`: allowlist відправників у групах (числові ID користувачів Telegram). `openclaw doctor --fix` може перетворити застарілі записи `@username` на ID. Нечислові записи ігноруються під час автентифікації. Автентифікація груп не використовує fallback на pairing-store для DM (`2026.2.25+`). +- Пріоритетність для кількох облікових записів: + - Коли налаштовано два або більше ID облікових записів, задайте `channels.telegram.defaultAccount` (або включіть `channels.telegram.accounts.default`), щоб явно визначити маршрут за замовчуванням. + - Якщо не задано жодного з них, OpenClaw використовує перший нормалізований ID облікового запису, а `openclaw doctor` виводить попередження. - `channels.telegram.accounts.default.allowFrom` і `channels.telegram.accounts.default.groupAllowFrom` застосовуються лише до облікового запису `default`. - - Іменовані облікові записи успадковують `channels.telegram.allowFrom` і `channels.telegram.groupAllowFrom`, коли значення на рівні облікового запису не задані. + - Іменовані облікові записи успадковують `channels.telegram.allowFrom` і `channels.telegram.groupAllowFrom`, якщо значення на рівні облікового запису не задано. - Іменовані облікові записи не успадковують `channels.telegram.accounts.default.allowFrom` / `groupAllowFrom`. -- `channels.telegram.groups`: значення за замовчуванням для окремих груп + allowlist (використовуйте `"*"` для глобальних значень за замовчуванням). - - `channels.telegram.groups..groupPolicy`: перевизначення groupPolicy для окремої групи (`open | allowlist | disabled`). - - `channels.telegram.groups..requireMention`: значення за замовчуванням для обмеження через згадування. +- `channels.telegram.groups`: типові значення для груп + allowlist (використовуйте `"*"` для глобальних типових значень). + - `channels.telegram.groups..groupPolicy`: перевизначення groupPolicy для конкретної групи (`open | allowlist | disabled`). + - `channels.telegram.groups..requireMention`: типовий gating згадувань. - `channels.telegram.groups..skills`: фільтр Skills (пропущено = усі Skills, порожньо = жодного). - - `channels.telegram.groups..allowFrom`: перевизначення allowlist відправників для окремої групи. - - `channels.telegram.groups..systemPrompt`: додатковий системний запит для групи. - - `channels.telegram.groups..enabled`: вимкнути групу, коли `false`. - - `channels.telegram.groups..topics..*`: перевизначення для окремої теми (поля групи + `agentId`, доступний лише для теми). + - `channels.telegram.groups..allowFrom`: перевизначення allowlist відправників для конкретної групи. + - `channels.telegram.groups..systemPrompt`: додатковий system prompt для групи. + - `channels.telegram.groups..enabled`: вимикає групу, якщо `false`. + - `channels.telegram.groups..topics..*`: перевизначення для конкретної теми (поля групи + `agentId`, доступний лише для теми). - `channels.telegram.groups..topics..agentId`: маршрутизувати цю тему до конкретного агента (перевизначає маршрутизацію на рівні групи та bindings). -- `channels.telegram.groups..topics..groupPolicy`: перевизначення groupPolicy для окремої теми (`open | allowlist | disabled`). -- `channels.telegram.groups..topics..requireMention`: перевизначення обмеження через згадування для окремої теми. -- верхньорівневий `bindings[]` з `type: "acp"` і канонічним ID теми `chatId:topic:topicId` у `match.peer.id`: поля постійної ACP-прив’язки теми (див. [ACP Agents](/uk/tools/acp-agents#channel-specific-settings)). +- `channels.telegram.groups..topics..groupPolicy`: перевизначення groupPolicy для конкретної теми (`open | allowlist | disabled`). +- `channels.telegram.groups..topics..requireMention`: перевизначення gating згадувань для конкретної теми. +- верхньорівневий `bindings[]` з `type: "acp"` і канонічним ID теми `chatId:topic:topicId` у `match.peer.id`: поля постійної прив’язки ACP теми (див. [ACP Agents](/uk/tools/acp-agents#channel-specific-settings)). - `channels.telegram.direct..topics..agentId`: маршрутизувати теми DM до конкретного агента (та сама поведінка, що й для тем форуму). -- `channels.telegram.execApprovals.enabled`: увімкнути Telegram як чат-клієнт підтверджень exec для цього облікового запису. -- `channels.telegram.execApprovals.approvers`: ID користувачів Telegram, яким дозволено підтверджувати або відхиляти запити exec. Необов’язково, коли `channels.telegram.allowFrom` або прямий `channels.telegram.defaultTo` уже визначає власника. +- `channels.telegram.execApprovals.enabled`: увімкнути Telegram як чат-клієнт для схвалення exec для цього облікового запису. +- `channels.telegram.execApprovals.approvers`: ID користувачів Telegram, яким дозволено схвалювати або відхиляти запити exec. Необов’язково, якщо `channels.telegram.allowFrom` або прямий `channels.telegram.defaultTo` уже визначає власника. - `channels.telegram.execApprovals.target`: `dm | channel | both` (за замовчуванням: `dm`). `channel` і `both` зберігають початкову тему Telegram, якщо вона є. -- `channels.telegram.execApprovals.agentFilter`: необов’язковий фільтр ID агента для пересланих запитів на підтвердження. -- `channels.telegram.execApprovals.sessionFilter`: необов’язковий фільтр ключа сесії (підрядок або regex) для пересланих запитів на підтвердження. -- `channels.telegram.accounts..execApprovals`: перевизначення маршрутизації підтверджень exec у Telegram і авторизації затверджувачів для окремого облікового запису. +- `channels.telegram.execApprovals.agentFilter`: необов’язковий фільтр ID агента для пересланих запитів на схвалення. +- `channels.telegram.execApprovals.sessionFilter`: необов’язковий фільтр ключа сесії (підрядок або regex) для пересланих запитів на схвалення. +- `channels.telegram.accounts..execApprovals`: перевизначення маршрутизації схвалення exec і авторизації схвалювача для конкретного облікового запису Telegram. - `channels.telegram.capabilities.inlineButtons`: `off | dm | group | all | allowlist` (за замовчуванням: allowlist). -- `channels.telegram.accounts..capabilities.inlineButtons`: перевизначення для окремого облікового запису. +- `channels.telegram.accounts..capabilities.inlineButtons`: перевизначення для конкретного облікового запису. - `channels.telegram.commands.nativeSkills`: увімкнути/вимкнути нативні команди Skills у Telegram. - `channels.telegram.replyToMode`: `off | first | all` (за замовчуванням: `off`). -- `channels.telegram.textChunkLimit`: розмір вихідного фрагмента (символи). -- `channels.telegram.chunkMode`: `length` (за замовчуванням) або `newline` для поділу за порожніми рядками (межами абзаців) перед поділом за довжиною. +- `channels.telegram.textChunkLimit`: розмір вихідного фрагмента (символів). +- `channels.telegram.chunkMode`: `length` (за замовчуванням) або `newline`, щоб розбивати за порожніми рядками (межами абзаців) перед розбиттям за довжиною. - `channels.telegram.linkPreview`: перемикач попереднього перегляду посилань для вихідних повідомлень (за замовчуванням: true). -- `channels.telegram.streaming`: `off | partial | block | progress` (попередній перегляд live stream; за замовчуванням: `partial`; `progress` відображається як `partial`; `block` — сумісність із застарілим режимом preview). Потоковий preview у Telegram використовує одне повідомлення попереднього перегляду, яке редагується на місці. -- `channels.telegram.streaming.preview.toolProgress`: повторно використовувати повідомлення live preview для оновлень інструментів/прогресу, коли preview streaming активний (за замовчуванням: `true`). Установіть `false`, щоб зберігати окремі повідомлення інструментів/прогресу. -- `channels.telegram.mediaMaxMb`: обмеження медіа Telegram для вхідних/вихідних даних (МБ, за замовчуванням: 100). -- `channels.telegram.retry`: політика повторних спроб для допоміжних функцій надсилання Telegram (CLI/tools/actions) при відновлюваних вихідних помилках API (attempts, minDelayMs, maxDelayMs, jitter). -- `channels.telegram.network.autoSelectFamily`: перевизначити Node autoSelectFamily (true=увімкнути, false=вимкнути). За замовчуванням увімкнено в Node 22+, а для WSL2 за замовчуванням вимкнено. -- `channels.telegram.network.dnsResultOrder`: перевизначити порядок DNS-результатів (`ipv4first` або `verbatim`). За замовчуванням: `ipv4first` у Node 22+. -- `channels.telegram.network.dangerouslyAllowPrivateNetwork`: небезпечний явний параметр для довірених середовищ fake-IP або transparent-proxy, де завантаження медіа Telegram визначають `api.telegram.org` у приватні/внутрішні/special-use адреси поза стандартним дозволеним benchmark-діапазоном RFC 2544. +- `channels.telegram.streaming`: `off | partial | block | progress` (попередній перегляд live stream; за замовчуванням: `partial`; `progress` мапується на `partial`; `block` — сумісність із застарілим режимом preview). Потоковий попередній перегляд Telegram використовує одне preview-повідомлення, яке редагується на місці. +- `channels.telegram.streaming.preview.toolProgress`: повторно використовувати live preview-повідомлення для оновлень tools/progress, коли активний preview streaming (за замовчуванням: `true`). Установіть `false`, щоб зберегти окремі повідомлення tools/progress. +- `channels.telegram.mediaMaxMb`: обмеження розміру вхідних/вихідних медіа Telegram (МБ, за замовчуванням: 100). +- `channels.telegram.retry`: політика повторних спроб для допоміжних функцій надсилання Telegram (CLI/tools/actions) у разі відновлюваних вихідних помилок API (спроби, minDelayMs, maxDelayMs, jitter). +- `channels.telegram.network.autoSelectFamily`: перевизначити Node autoSelectFamily (true=увімкнути, false=вимкнути). За замовчуванням увімкнено в Node 22+, а у WSL2 за замовчуванням вимкнено. +- `channels.telegram.network.dnsResultOrder`: перевизначити порядок результатів DNS (`ipv4first` або `verbatim`). За замовчуванням у Node 22+ використовується `ipv4first`. +- `channels.telegram.network.dangerouslyAllowPrivateNetwork`: небезпечне явне ввімкнення для довірених середовищ із fake-IP або transparent proxy, де завантаження медіа Telegram резолвить `api.telegram.org` у приватні/внутрішні/спеціальні адреси поза типовим дозволеним діапазоном benchmark RFC 2544. - `channels.telegram.proxy`: URL proxy для викликів Bot API (SOCKS/HTTP). -- `channels.telegram.webhookUrl`: увімкнути режим Webhook (потрібен `channels.telegram.webhookSecret`). -- `channels.telegram.webhookSecret`: секрет webhook (обов’язковий, коли задано webhookUrl). -- `channels.telegram.webhookPath`: локальний шлях webhook (за замовчуванням `/telegram-webhook`). -- `channels.telegram.webhookHost`: локальний хост прив’язки webhook (за замовчуванням `127.0.0.1`). -- `channels.telegram.webhookPort`: локальний порт прив’язки webhook (за замовчуванням `8787`). -- `channels.telegram.actions.reactions`: керування доступом до реакцій інструментів Telegram. -- `channels.telegram.actions.sendMessage`: керування доступом до надсилання повідомлень інструментами Telegram. -- `channels.telegram.actions.deleteMessage`: керування доступом до видалення повідомлень інструментами Telegram. -- `channels.telegram.actions.sticker`: керування доступом до дій зі стікерами Telegram — надсилання та пошук (за замовчуванням: false). -- `channels.telegram.reactionNotifications`: `off | own | all` — керує тим, які реакції викликають системні події (за замовчуванням: `own`, якщо не задано). -- `channels.telegram.reactionLevel`: `off | ack | minimal | extensive` — керує можливістю агента працювати з реакціями (за замовчуванням: `minimal`, якщо не задано). -- `channels.telegram.errorPolicy`: `reply | silent` — керує поведінкою відповіді на помилки (за замовчуванням: `reply`). Підтримуються перевизначення для окремих облікових записів/груп/тем. -- `channels.telegram.errorCooldownMs`: мінімальна кількість мс між відповідями про помилки в той самий чат (за замовчуванням: `60000`). Запобігає спаму помилками під час збоїв. +- `channels.telegram.webhookUrl`: увімкнути режим Webhook-ів (потребує `channels.telegram.webhookSecret`). +- `channels.telegram.webhookSecret`: секрет Webhook-а (обов’язковий, коли задано webhookUrl). +- `channels.telegram.webhookPath`: локальний шлях Webhook-а (за замовчуванням `/telegram-webhook`). +- `channels.telegram.webhookHost`: локальний host прив’язки Webhook-а (за замовчуванням `127.0.0.1`). +- `channels.telegram.webhookPort`: локальний port прив’язки Webhook-а (за замовчуванням `8787`). +- `channels.telegram.actions.reactions`: керування реакціями інструментів Telegram. +- `channels.telegram.actions.sendMessage`: керування надсиланням повідомлень інструментами Telegram. +- `channels.telegram.actions.deleteMessage`: керування видаленням повідомлень інструментами Telegram. +- `channels.telegram.actions.sticker`: керування діями зі стікерами Telegram — надсилання та пошук (за замовчуванням: false). +- `channels.telegram.reactionNotifications`: `off | own | all` — керує тим, які реакції запускають системні події (за замовчуванням: `own`, якщо не задано). +- `channels.telegram.reactionLevel`: `off | ack | minimal | extensive` — керує можливістю реакцій агента (за замовчуванням: `minimal`, якщо не задано). +- `channels.telegram.errorPolicy`: `reply | silent` — керує поведінкою відповіді на помилки (за замовчуванням: `reply`). Підтримуються перевизначення для окремого облікового запису/групи/теми. +- `channels.telegram.errorCooldownMs`: мінімальна кількість мс між відповідями на помилки в тому самому чаті (за замовчуванням: `60000`). Запобігає спаму помилками під час збоїв. -- [Довідник конфігурації — Telegram](/uk/gateway/configuration-reference#telegram) +- [Довідник конфігурації - Telegram](/uk/gateway/configuration-reference#telegram) -Специфічні для Telegram високосигнальні поля: +Специфічні для Telegram поля з високою цінністю сигналу: -- startup/auth: `enabled`, `botToken`, `tokenFile`, `accounts.*` (`tokenFile` має вказувати на звичайний файл; символічні посилання відхиляються) +- запуск/автентифікація: `enabled`, `botToken`, `tokenFile`, `accounts.*` (`tokenFile` має вказувати на звичайний файл; символічні посилання відхиляються) - контроль доступу: `dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`, `groups`, `groups.*.topics.*`, верхньорівневий `bindings[]` (`type: "acp"`) -- підтвердження exec: `execApprovals`, `accounts.*.execApprovals` -- команда/меню: `commands.native`, `commands.nativeSkills`, `customCommands` -- треди/відповіді: `replyToMode` +- схвалення exec: `execApprovals`, `accounts.*.execApprovals` +- команди/меню: `commands.native`, `commands.nativeSkills`, `customCommands` +- потоки/відповіді: `replyToMode` - streaming: `streaming` (preview), `streaming.preview.toolProgress`, `blockStreaming` - форматування/доставка: `textChunkLimit`, `chunkMode`, `linkPreview`, `responsePrefix` - медіа/мережа: `mediaMaxMb`, `timeoutSeconds`, `pollingStallThresholdMs`, `retry`, `network.autoSelectFamily`, `network.dangerouslyAllowPrivateNetwork`, `proxy` -- webhook: `webhookUrl`, `webhookSecret`, `webhookPath`, `webhookHost` +- Webhook: `webhookUrl`, `webhookSecret`, `webhookPath`, `webhookHost` - дії/можливості: `capabilities.inlineButtons`, `actions.sendMessage|editMessage|deleteMessage|reactions|sticker` - реакції: `reactionNotifications`, `reactionLevel` - помилки: `errorPolicy`, `errorCooldownMs` diff --git a/docs/uk/plan/ui-channels.md b/docs/uk/plan/ui-channels.md new file mode 100644 index 000000000..1bf59f8b0 --- /dev/null +++ b/docs/uk/plan/ui-channels.md @@ -0,0 +1,261 @@ +--- +read_when: + - Рефакторинг UI повідомлень каналу, інтерактивних корисних навантажень або нативних засобів візуалізації каналу + - Зміна можливостей інструментів повідомлень, підказок доставки або міжконтекстних маркерів + - Налагодження fanout імпорту Discord Carbon або лінивості середовища виконання plugin каналу +summary: Відокремте семантичне представлення повідомлень від нативних засобів візуалізації UI каналу. +title: План рефакторингу представлення каналу +x-i18n: + generated_at: "2026-04-21T20:37:39Z" + model: gpt-5.4 + provider: openai + source_hash: ed3c49f3cc55151992315599a05451fe499f2983d53d69dc58784e846f9f32ad + source_path: plan/ui-channels.md + workflow: 15 +--- + +# План рефакторингу представлення каналу + +## Статус + +Реалізовано для спільного агента, CLI, можливостей plugin і поверхонь вихідної доставки: + +- `ReplyPayload.presentation` містить семантичний UI повідомлення. +- `ReplyPayload.delivery.pin` містить запити на закріплення надісланих повідомлень. +- Спільні дії повідомлень надають `presentation`, `delivery` і `pin` замість нативних для провайдера `components`, `blocks`, `buttons` або `card`. +- Ядро рендерить або автоматично деградує presentation через оголошені plugin можливості вихідної доставки. +- Рендерери Discord, Slack, Telegram, Mattermost, MS Teams і Feishu споживають узагальнений контракт. +- Код control plane каналу Discord більше не імпортує UI-контейнери на основі Carbon. + +Канонічна документація тепер розміщена в [Представлення повідомлень](/uk/plugins/message-presentation). +Зберігайте цей план як історичний контекст реалізації; оновлюйте канонічний посібник +для змін у контракті, рендерері або поведінці fallback. + +## Проблема + +UI каналу зараз розділений між кількома несумісними поверхнями: + +- Ядро володіє хук-рендерером міжконтекстного представлення у формі Discord через `buildCrossContextComponents`. +- `channel.ts` Discord може імпортувати нативний Carbon UI через `DiscordUiContainer`, що підтягує залежності UI середовища виконання в control plane plugin каналу. +- Агент і CLI надають escape hatch для нативних payload, як-от Discord `components`, Slack `blocks`, Telegram або Mattermost `buttons`, а також Teams або Feishu `card`. +- `ReplyPayload.channelData` містить як підказки транспорту, так і нативні UI-конверти. +- Загальна модель `interactive` існує, але вона вужча, ніж багатші макети, які вже використовуються в Discord, Slack, Teams, Feishu, LINE, Telegram і Mattermost. + +Через це ядро знає про форми нативного UI, послаблюється лінивість середовища виконання plugin, а агенти отримують забагато специфічних для провайдера способів вираження одного й того самого наміру повідомлення. + +## Цілі + +- Ядро визначає найкраще семантичне представлення повідомлення на основі оголошених можливостей. +- Extensions оголошують можливості та рендерять семантичне представлення в нативні transport payload. +- Web Control UI залишається окремим від нативного UI чату. +- Нативні channel payload не доступні через спільну поверхню повідомлень агента або CLI. +- Непідтримувані можливості представлення автоматично деградують до найкращого текстового представлення. +- Поведінка доставки, така як закріплення надісланого повідомлення, є узагальненими метаданими доставки, а не представленням. + +## Нецілі + +- Жодного shim зворотної сумісності для `buildCrossContextComponents`. +- Жодних публічних нативних escape hatch для `components`, `blocks`, `buttons` або `card`. +- Жодних імпортів у ядрі бібліотек UI, нативних для каналу. +- Жодних специфічних для провайдера SDK seam для вбудованих каналів. + +## Цільова модель + +Додати до `ReplyPayload` поле `presentation`, яким володіє ядро. + +```ts +type MessagePresentationTone = "neutral" | "info" | "success" | "warning" | "danger"; + +type MessagePresentation = { + tone?: MessagePresentationTone; + title?: string; + blocks: MessagePresentationBlock[]; +}; + +type MessagePresentationBlock = + | { type: "text"; text: string } + | { type: "context"; text: string } + | { type: "divider" } + | { type: "buttons"; buttons: MessagePresentationButton[] } + | { type: "select"; placeholder?: string; options: MessagePresentationOption[] }; + +type MessagePresentationButton = { + label: string; + value?: string; + url?: string; + style?: "primary" | "secondary" | "success" | "danger"; +}; + +type MessagePresentationOption = { + label: string; + value: string; +}; +``` + +`interactive` під час міграції стає підмножиною `presentation`: + +- Блок тексту `interactive` відображається в `presentation.blocks[].type = "text"`. +- Блок кнопок `interactive` відображається в `presentation.blocks[].type = "buttons"`. +- Блок вибору `interactive` відображається в `presentation.blocks[].type = "select"`. + +Зовнішні схеми агента і CLI тепер використовують `presentation`; `interactive` залишається внутрішнім legacy helper для парсингу/рендерингу для наявних продуцентів відповідей. + +## Метадані доставки + +Додати поле `delivery`, яким володіє ядро, для поведінки надсилання, що не є UI. + +```ts +type ReplyPayloadDelivery = { + pin?: + | boolean + | { + enabled: boolean; + notify?: boolean; + required?: boolean; + }; +}; +``` + +Семантика: + +- `delivery.pin = true` означає закріпити перше успішно доставлене повідомлення. +- `notify` типово дорівнює `false`. +- `required` типово дорівнює `false`; непідтримувані канали або помилки під час закріплення автоматично деградують шляхом продовження доставки. +- Ручні дії повідомлень `pin`, `unpin` і `list-pins` залишаються для наявних повідомлень. + +Поточну прив’язку теми Telegram ACP слід перенести з `channelData.telegram.pin = true` до `delivery.pin = true`. + +## Контракт можливостей середовища виконання + +Додати presentation і delivery hooks рендерингу до runtime outbound adapter, а не до plugin каналу control plane. + +```ts +type ChannelPresentationCapabilities = { + supported: boolean; + buttons?: boolean; + selects?: boolean; + context?: boolean; + divider?: boolean; + tones?: MessagePresentationTone[]; +}; + +type ChannelDeliveryCapabilities = { + pinSentMessage?: boolean; +}; + +type ChannelOutboundAdapter = { + presentationCapabilities?: ChannelPresentationCapabilities; + + renderPresentation?: (params: { + payload: ReplyPayload; + presentation: MessagePresentation; + ctx: ChannelOutboundSendContext; + }) => ReplyPayload | null; + + deliveryCapabilities?: ChannelDeliveryCapabilities; + + pinDeliveredMessage?: (params: { + cfg: OpenClawConfig; + accountId?: string | null; + to: string; + threadId?: string | number | null; + messageId: string; + notify: boolean; + }) => Promise; +}; +``` + +Поведінка ядра: + +- Визначити цільовий канал і runtime adapter. +- Запитати можливості presentation. +- Деградувати непідтримувані блоки перед рендерингом. +- Викликати `renderPresentation`. +- Якщо рендерер відсутній, перетворити presentation на текстовий fallback. +- Після успішного надсилання викликати `pinDeliveredMessage`, коли запитано `delivery.pin` і це підтримується. + +## Відображення каналів + +Discord: + +- Рендерити `presentation` у components v2 і Carbon-контейнери в модулях лише для runtime. +- Зберегти helper для accent color у легких модулях. +- Прибрати імпорти `DiscordUiContainer` з коду control plane plugin каналу. + +Slack: + +- Рендерити `presentation` у Block Kit. +- Прибрати вхідний параметр `blocks` з агента і CLI. + +Telegram: + +- Рендерити text, context і divider як текст. +- Рендерити actions і select як inline keyboard, коли це налаштовано і дозволено для цільової поверхні. +- Використовувати текстовий fallback, коли inline button вимкнено. +- Перенести закріплення теми ACP до `delivery.pin`. + +Mattermost: + +- Рендерити actions як інтерактивні кнопки, коли це налаштовано. +- Рендерити інші блоки як текстовий fallback. + +MS Teams: + +- Рендерити `presentation` у Adaptive Cards. +- Зберегти ручні дії pin/unpin/list-pins. +- За потреби реалізувати `pinDeliveredMessage`, якщо підтримка Graph надійна для цільової розмови. + +Feishu: + +- Рендерити `presentation` в interactive cards. +- Зберегти ручні дії pin/unpin/list-pins. +- За потреби реалізувати `pinDeliveredMessage` для закріплення надісланого повідомлення, якщо поведінка API надійна. + +LINE: + +- Рендерити `presentation` у Flex або template messages, де це можливо. +- Для непідтримуваних блоків використовувати fallback до тексту. +- Прибрати LINE UI payload з `channelData`. + +Звичайні або обмежені канали: + +- Перетворювати presentation на текст із консервативним форматуванням. + +## Кроки рефакторингу + +1. Повторно застосувати виправлення релізу Discord, яке відокремлює `ui-colors.ts` від Carbon-backed UI і прибирає `DiscordUiContainer` з `extensions/discord/src/channel.ts`. +2. Додати `presentation` і `delivery` до `ReplyPayload`, нормалізації outbound payload, зведень доставки та hook payload. +3. Додати схему `MessagePresentation` і helper для парсингу у вузький підшлях SDK/runtime. +4. Замінити можливості повідомлень `buttons`, `cards`, `components` і `blocks` на семантичні можливості presentation. +5. Додати hooks runtime outbound adapter для рендерингу presentation і закріплення доставки. +6. Замінити побудову міжконтекстних компонентів на `buildCrossContextPresentation`. +7. Видалити `src/infra/outbound/channel-adapters.ts` і прибрати `buildCrossContextComponents` з типів plugin каналу. +8. Змінити `maybeApplyCrossContextMarker`, щоб він приєднував `presentation` замість нативних params. +9. Оновити шляхи надсилання plugin-dispatch, щоб вони споживали лише семантичне presentation і метадані delivery. +10. Видалити нативні параметри payload агента і CLI: `components`, `blocks`, `buttons` і `card`. +11. Видалити helper SDK, які створюють схеми native message-tool, замінивши їх helper схем presentation. +12. Прибрати UI/native envelopes з `channelData`; залишити лише метадані транспорту, доки не буде переглянуто кожне поле, що залишилося. +13. Мігрувати рендерери Discord, Slack, Telegram, Mattermost, MS Teams, Feishu і LINE. +14. Оновити документацію для CLI повідомлень, сторінок каналів, SDK plugin і cookbook можливостей. +15. Запустити профілювання fanout імпорту для Discord і пов’язаних entrypoint каналів. + +Кроки 1-11 і 13-14 реалізовано в цьому рефакторингу для спільного агента, CLI, можливостей plugin і контрактів outbound adapter. Крок 12 залишається глибшим внутрішнім етапом очищення для приватних transport envelope провайдера в `channelData`. Крок 15 залишається подальшою перевіркою, якщо нам потрібні кількісні показники fanout імпорту понад межі перевірки типів/тестів. + +## Тести + +Додати або оновити: + +- Тести нормалізації presentation. +- Тести автоматичної деградації presentation для непідтримуваних блоків. +- Тести міжконтекстних маркерів для шляхів plugin dispatch і доставки ядра. +- Тести матриці рендерингу каналів для Discord, Slack, Telegram, Mattermost, MS Teams, Feishu, LINE і текстового fallback. +- Тести схем message tool, які доводять, що нативні поля прибрано. +- Тести CLI, які доводять, що нативні прапорці прибрано. +- Регресійний тест лінивості імпорту entrypoint Discord, що покриває Carbon. +- Тести delivery pin, що покривають Telegram і загальний fallback. + +## Відкриті питання + +- Чи слід реалізувати `delivery.pin` для Discord, Slack, MS Teams і Feishu у першому проході, чи спочатку лише для Telegram? +- Чи має `delivery` зрештою поглинути наявні поля, як-от `replyToId`, `replyToCurrent`, `silent` і `audioAsVoice`, чи залишатися зосередженим на поведінках після надсилання? +- Чи має presentation безпосередньо підтримувати зображення або посилання на файли, чи поки що медіа мають залишатися окремо від UI-компонування? diff --git a/docs/uk/plugins/architecture.md b/docs/uk/plugins/architecture.md index f643b45c1..47c76474c 100644 --- a/docs/uk/plugins/architecture.md +++ b/docs/uk/plugins/architecture.md @@ -1,17 +1,17 @@ --- read_when: - - Створення або налагодження нативних Plugin OpenClaw - - Розуміння моделі можливостей Plugin або меж володіння - - Робота над конвеєром завантаження Plugin або реєстром + - Створення або налагодження нативних плагінів OpenClaw + - Розуміння моделі можливостей плагіна або меж володіння + - Робота над конвеєром завантаження плагінів або реєстром - Реалізація хуків середовища виконання провайдера або плагінів каналів sidebarTitle: Internals summary: 'Внутрішні компоненти Plugin: модель можливостей, володіння, контракти, конвеєр завантаження та допоміжні засоби середовища виконання' title: Внутрішні компоненти Plugin x-i18n: - generated_at: "2026-04-21T08:24:23Z" + generated_at: "2026-04-21T20:37:40Z" model: gpt-5.4 provider: openai - source_hash: 4b1fb42e659d4419033b317e88563a59b3ddbfad0523f32225c868c8e828fd16 + source_hash: 69080a1d0e496b321a6fd5a3e925108c3a03c41710073f8f23af13933a091e28 source_path: plugins/architecture.md workflow: 15 --- @@ -19,179 +19,177 @@ x-i18n: # Внутрішні компоненти Plugin - Це **довідник із глибокої архітектури**. Практичні посібники див. тут: + Це **поглиблена довідка з архітектури**. Практичні посібники дивіться тут: - [Встановлення та використання плагінів](/uk/tools/plugin) — посібник для користувача - - [Початок роботи](/uk/plugins/building-plugins) — перший навчальний посібник зі створення Plugin + - [Початок роботи](/uk/plugins/building-plugins) — перший посібник зі створення плагіна - [Плагіни каналів](/uk/plugins/sdk-channel-plugins) — створення каналу обміну повідомленнями - [Плагіни провайдерів](/uk/plugins/sdk-provider-plugins) — створення провайдера моделей - [Огляд SDK](/uk/plugins/sdk-overview) — карта імпорту та API реєстрації -Ця сторінка описує внутрішню архітектуру системи Plugin в OpenClaw. +Ця сторінка описує внутрішню архітектуру системи плагінів OpenClaw. ## Публічна модель можливостей -Можливості — це публічна модель **нативних Plugin** усередині OpenClaw. Кожен -нативний Plugin OpenClaw реєструється для одного або кількох типів можливостей: +Можливості — це публічна модель **нативних плагінів** усередині OpenClaw. Кожен +нативний плагін OpenClaw реєструється для одного або кількох типів можливостей: -| Можливість | Метод реєстрації | Приклади Plugin | -| --------------------- | ---------------------------------------------- | ----------------------------------- | -| Текстовий висновок | `api.registerProvider(...)` | `openai`, `anthropic` | -| Backend висновку CLI | `api.registerCliBackend(...)` | `openai`, `anthropic` | -| Мовлення | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` | -| Транскрипція в реальному часі | `api.registerRealtimeTranscriptionProvider(...)` | `openai` | -| Голос у реальному часі | `api.registerRealtimeVoiceProvider(...)` | `openai` | -| Розуміння медіа | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` | -| Генерація зображень | `api.registerImageGenerationProvider(...)` | `openai`, `google`, `fal`, `minimax` | -| Генерація музики | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` | -| Генерація відео | `api.registerVideoGenerationProvider(...)` | `qwen` | -| Отримання вебданих | `api.registerWebFetchProvider(...)` | `firecrawl` | -| Вебпошук | `api.registerWebSearchProvider(...)` | `google` | -| Канал / обмін повідомленнями | `api.registerChannel(...)` | `msteams`, `matrix` | +| Можливість | Метод реєстрації | Приклади плагінів | +| --------------------- | ----------------------------------------------- | ------------------------------------ | +| Текстовий інференс | `api.registerProvider(...)` | `openai`, `anthropic` | +| CLI-бекенд інференсу | `api.registerCliBackend(...)` | `openai`, `anthropic` | +| Мовлення | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` | +| Транскрипція в реальному часі | `api.registerRealtimeTranscriptionProvider(...)` | `openai` | +| Голос у реальному часі | `api.registerRealtimeVoiceProvider(...)` | `openai` | +| Розуміння медіа | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` | +| Генерація зображень | `api.registerImageGenerationProvider(...)` | `openai`, `google`, `fal`, `minimax` | +| Генерація музики | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` | +| Генерація відео | `api.registerVideoGenerationProvider(...)` | `qwen` | +| Отримання вебданих | `api.registerWebFetchProvider(...)` | `firecrawl` | +| Вебпошук | `api.registerWebSearchProvider(...)` | `google` | +| Канал / повідомлення | `api.registerChannel(...)` | `msteams`, `matrix` | -Plugin, який реєструє нуль можливостей, але надає хуки, інструменти або -сервіси, є **застарілим Plugin лише з хуками**. Цей шаблон і далі повністю -підтримується. +Плагін, який реєструє нуль можливостей, але надає хуки, інструменти або +сервіси, є **застарілим плагіном лише з хуками**. Цей шаблон досі повністю підтримується. ### Позиція щодо зовнішньої сумісності -Модель можливостей уже впроваджена в core і сьогодні використовується -вбудованими/нативними Plugin, але сумісність із зовнішніми Plugin усе ще -потребує вищої планки, ніж «це експортується, отже це заморожено». +Модель можливостей уже реалізована в core і сьогодні використовується +вбудованими/нативними плагінами, але сумісність зовнішніх плагінів усе ще +потребує чіткішого критерію, ніж «це експортовано, отже це незмінно». Поточні рекомендації: -- **наявні зовнішні Plugin:** зберігайте працездатність інтеграцій на основі хуків; вважайте +- **наявні зовнішні плагіни:** зберігайте працездатність інтеграцій на основі хуків; вважайте це базовим рівнем сумісності -- **нові вбудовані/нативні Plugin:** надавайте перевагу явній реєстрації можливостей - замість vendor-specific доступу до внутрішніх частин або нових конструкцій лише з хуками -- **зовнішні Plugin, які переходять на реєстрацію можливостей:** це дозволено, але - вважайте допоміжні поверхні для конкретних можливостей такими, що розвиваються, - якщо документація явно не позначає контракт як стабільний +- **нові вбудовані/нативні плагіни:** надавайте перевагу явній реєстрації можливостей, а не + vendor-specific проникненням усередину чи новим дизайнам лише з хуками +- **зовнішні плагіни, що переходять на реєстрацію можливостей:** це дозволено, але + вважайте допоміжні поверхні, специфічні для можливостей, такими, що розвиваються, якщо документація + явно не позначає контракт як стабільний Практичне правило: - API реєстрації можливостей — це бажаний напрям -- застарілі хуки залишаються найбезпечнішим шляхом без порушень сумісності для зовнішніх Plugin під час +- застарілі хуки залишаються найбезпечнішим шляхом без зламів для зовнішніх плагінів під час переходу -- не всі експортовані допоміжні підшляхи однаково важливі; надавайте перевагу вузькому - задокументованому контракту, а не випадковим допоміжним експортам +- не всі експортовані допоміжні підшляхи однакові; надавайте перевагу вузькому документованому + контракту, а не випадковим допоміжним експортам -### Форми Plugin +### Форми плагінів -OpenClaw класифікує кожен завантажений Plugin за формою на основі його фактичної -поведінки під час реєстрації, а не лише статичних метаданих: +OpenClaw класифікує кожен завантажений плагін за формою на основі його фактичної +поведінки реєстрації, а не лише статичних метаданих: -- **plain-capability** — реєструє рівно один тип можливостей (наприклад - Plugin лише провайдера, як-от `mistral`) -- **hybrid-capability** — реєструє кілька типів можливостей (наприклад - `openai` володіє текстовим висновком, мовленням, розумінням медіа та - генерацією зображень) -- **hook-only** — реєструє лише хуки (типізовані або користувацькі), без можливостей, +- **plain-capability** -- реєструє рівно один тип можливостей (наприклад, + плагін лише провайдера, як-от `mistral`) +- **hybrid-capability** -- реєструє кілька типів можливостей (наприклад, + `openai` відповідає за текстовий інференс, мовлення, розуміння медіа та + генерацію зображень) +- **hook-only** -- реєструє лише хуки (типізовані або користувацькі), без можливостей, інструментів, команд чи сервісів -- **non-capability** — реєструє інструменти, команди, сервіси або маршрути, але без - можливостей +- **non-capability** -- реєструє інструменти, команди, сервіси або маршрути, але не + можливості -Використовуйте `openclaw plugins inspect `, щоб побачити форму Plugin та -розподіл можливостей. Докладніше див. у [довіднику CLI](/cli/plugins#inspect). +Використовуйте `openclaw plugins inspect `, щоб побачити форму плагіна та +розподіл можливостей. Докладніше див. у [довідці CLI](/cli/plugins#inspect). ### Застарілі хуки Хук `before_agent_start` залишається підтримуваним як шлях сумісності для -Plugin лише з хуками. Реальні застарілі Plugin усе ще залежать від нього. +плагінів лише з хуками. Застарілі реальні плагіни все ще від нього залежать. Напрям: -- зберігати його працездатність +- зберігати його працездатним - документувати його як застарілий -- для перевизначення моделі/провайдера надавати перевагу `before_model_resolve` -- для змін prompt надавати перевагу `before_prompt_build` -- видаляти лише після падіння реального використання та коли покриття фікстурами підтвердить безпечність міграції +- для роботи з перевизначенням моделі/провайдера надавати перевагу `before_model_resolve` +- для змінювання prompt надавати перевагу `before_prompt_build` +- вилучати лише після зменшення реального використання та підтвердження безпечності міграції покриттям фікстур ### Сигнали сумісності -Коли ви запускаєте `openclaw doctor` або `openclaw plugins inspect `, ви можете -побачити одну з таких позначок: +Під час запуску `openclaw doctor` або `openclaw plugins inspect ` ви можете побачити +одну з таких позначок: -| Сигнал | Значення | -| -------------------------- | ---------------------------------------------------------- | -| **config valid** | Config успішно розбирається, а Plugin коректно визначаються | -| **compatibility advisory** | Plugin використовує підтримуваний, але старіший шаблон (наприклад, `hook-only`) | -| **legacy warning** | Plugin використовує `before_agent_start`, який є застарілим | -| **hard error** | Config недійсний або Plugin не вдалося завантажити | +| Сигнал | Значення | +| -------------------------- | ------------------------------------------------------------ | +| **config valid** | Конфігурація коректно розбирається, а плагіни успішно визначаються | +| **compatibility advisory** | Плагін використовує підтримуваний, але старіший шаблон (наприклад, `hook-only`) | +| **legacy warning** | Плагін використовує `before_agent_start`, який є застарілим | +| **hard error** | Конфігурація некоректна або плагін не вдалося завантажити | -Ані `hook-only`, ані `before_agent_start` сьогодні не зламають ваш Plugin — -`hook-only` є рекомендаційним сигналом, а `before_agent_start` лише викликає -попередження. Ці сигнали також з’являються в `openclaw status --all` і -`openclaw plugins doctor`. +Ні `hook-only`, ні `before_agent_start` сьогодні не зламають ваш плагін -- +`hook-only` є рекомендаційним попередженням, а `before_agent_start` лише викликає попередження. Ці +сигнали також відображаються в `openclaw status --all` і `openclaw plugins doctor`. ## Огляд архітектури -Система Plugin OpenClaw має чотири шари: +Система плагінів OpenClaw має чотири рівні: 1. **Маніфест + виявлення** - OpenClaw знаходить кандидатів у Plugin із налаштованих шляхів, коренів робочих просторів, - глобальних коренів розширень і вбудованих розширень. Під час виявлення спочатку читаються - нативні маніфести `openclaw.plugin.json`, а також підтримувані маніфести пакетів. + OpenClaw знаходить кандидатів у плагіни зі сконфігурованих шляхів, коренів + робочих просторів, глобальних коренів розширень і вбудованих розширень. Під час виявлення спочатку читаються + нативні маніфести `openclaw.plugin.json` і підтримувані маніфести пакетів. 2. **Увімкнення + валідація** - Core визначає, чи знайдений Plugin увімкнено, вимкнено, заблоковано або - вибрано для ексклюзивного слота, такого як пам’ять. + Core визначає, чи виявлений плагін увімкнений, вимкнений, заблокований або + вибраний для ексклюзивного слота, такого як пам’ять. 3. **Завантаження середовища виконання** - Нативні Plugin OpenClaw завантажуються в межах процесу через jiti і реєструють - можливості в центральному реєстрі. Сумісні пакети нормалізуються в записи + Нативні плагіни OpenClaw завантажуються в процес через jiti і реєструють + можливості в центральному реєстрі. Сумісні пакети нормалізуються до записів реєстру без імпорту коду середовища виконання. -4. **Споживання поверхонь** +4. **Використання поверхонь** Решта OpenClaw читає реєстр, щоб надавати інструменти, канали, налаштування - провайдерів, хуки, HTTP-маршрути, команди CLI та сервіси. + провайдерів, хуки, HTTP-маршрути, CLI-команди та сервіси. -Зокрема для CLI Plugin, виявлення кореневих команд розділено на дві фази: +Для CLI плагінів зокрема виявлення кореневих команд поділене на дві фази: -- метадані під час розбору надходять із `registerCli(..., { descriptors: [...] })` -- реальний модуль CLI Plugin може залишатися відкладеним і реєструватися під час першого виклику +- метадані часу розбору надходять із `registerCli(..., { descriptors: [...] })` +- реальний модуль CLI плагіна може залишатися лінивим і реєструватися під час першого виклику -Це дає змогу зберігати код CLI, що належить Plugin, усередині самого Plugin, водночас дозволяючи OpenClaw -резервувати імена кореневих команд до початку розбору. +Це дозволяє зберігати код CLI, що належить плагіну, усередині плагіна, водночас +даючи OpenClaw змогу резервувати імена кореневих команд до розбору. -Важлива межа проєктування: +Важлива межа дизайну: -- виявлення + валідація config мають працювати з **метаданих маніфесту/схеми** - без виконання коду Plugin -- нативна поведінка середовища виконання походить із шляху `register(api)` модуля Plugin +- виявлення та валідація конфігурації мають працювати на основі **метаданих маніфесту/схеми** + без виконання коду плагіна +- нативна поведінка середовища виконання надходить зі шляху модуля плагіна `register(api)` -Це розділення дає OpenClaw змогу перевіряти config, пояснювати відсутні/вимкнені Plugin і -будувати підказки для UI/схеми до того, як повне середовище виконання стане активним. +Це розділення дає OpenClaw змогу перевіряти конфігурацію, пояснювати +відсутні/вимкнені плагіни та будувати підказки для UI/схеми до повної активації середовища виконання. ### Плагіни каналів і спільний інструмент повідомлень -Плагінам каналів не потрібно реєструвати окремий інструмент надсилання/редагування/реакції для -звичайних дій чату. OpenClaw зберігає один спільний інструмент `message` у core, а -плагіни каналів володіють специфічними для каналу виявленням і виконанням за ним. +Плагінам каналів не потрібно реєструвати окремий інструмент send/edit/react для +звичайних дій чату. OpenClaw зберігає один спільний інструмент `message` у core, +а плагіни каналів відповідають за виявлення та виконання, специфічні для каналу, за ним. Поточна межа така: -- core володіє хостом спільного інструмента `message`, прив’язкою prompt, веденням - обліку сеансів/потоків і диспетчеризацією виконання -- плагіни каналів володіють виявленням дій у межах області, виявленням можливостей і будь-якими - фрагментами схеми, специфічними для каналу -- плагіни каналів володіють граматикою розмов сеансів, специфічною для провайдера, наприклад - тим, як ідентифікатори розмов кодують ідентифікатори потоків або успадковують їх від батьківських розмов +- core відповідає за хост спільного інструмента `message`, підключення prompt, + облік сесій/гілок і диспетчеризацію виконання +- плагіни каналів відповідають за виявлення дій у межах області, виявлення + можливостей і будь-які фрагменти схеми, специфічні для каналу +- плагіни каналів відповідають за граматику розмов сесій, специфічну для провайдера, наприклад, + як ідентифікатори розмов кодують ідентифікатори гілок або успадковуються від батьківських розмов - плагіни каналів виконують фінальну дію через свій адаптер дій Для плагінів каналів поверхнею SDK є `ChannelMessageActionAdapter.describeMessageTool(...)`. Цей уніфікований виклик -виявлення дає змогу Plugin повертати видимі дії, можливості та внески у схему -разом, щоб ці частини не розходилися між собою. +виявлення дає плагіну змогу повертати видимі дії, можливості та внески у схему +разом, щоб ці частини не розходилися. -Коли параметр інструмента повідомлень, специфічний для каналу, містить джерело медіа, -наприклад локальний шлях або URL віддаленого медіа, Plugin також має повертати +Коли параметр інструмента повідомлення, специфічний для каналу, містить джерело медіа, +наприклад локальний шлях або віддалений URL медіа, плагін також має повертати `mediaSourceParams` із `describeMessageTool(...)`. Core використовує цей явний -список для застосування нормалізації шляхів у sandbox і підказок щодо вихідного доступу до медіа -без жорстко закодованих імен параметрів, що належать Plugin. -Тут слід надавати перевагу картам у межах дій, а не одному плоскому списку на весь канал, -щоб параметр медіа лише для профілю не нормалізувався для не пов’язаних дій, як-от +список для застосування нормалізації шляхів sandbox і підказок щодо вихідного доступу до медіа +без жорсткого кодування назв параметрів, що належать плагіну. +Там слід надавати перевагу картам у межах дій, а не одному пласкому списку для всього каналу, +щоб параметр медіа лише для профілю не нормалізувався для не пов’язаних дій, таких як `send`. -Core передає область середовища виконання в цей етап виявлення. Важливі поля включають: +Core передає область середовища виконання в цей крок виявлення. Важливі поля включають: - `accountId` - `currentChannelId` @@ -202,126 +200,126 @@ Core передає область середовища виконання в ц - `agentId` - довірений вхідний `requesterSenderId` -Це важливо для context-sensitive Plugin. Канал може приховувати або показувати -дії з повідомленнями залежно від активного облікового запису, поточної кімнати/потоку/повідомлення або -довіреної ідентичності відправника запиту, без жорстко закодованих специфічних для каналу гілок -у core-інструменті `message`. +Це важливо для контекстно-чутливих плагінів. Канал може приховувати або +показувати дії повідомлень залежно від активного облікового запису, поточної кімнати/гілки/повідомлення або +довіреної ідентичності запитувача без жорстко закодованих гілок, специфічних для каналу, у +core-інструменті `message`. -Саме тому зміни маршрутизації embedded-runner усе ще є роботою Plugin: runner -відповідає за пересилання поточної ідентичності чату/сеансу в межу виявлення Plugin, щоб -спільний інструмент `message` відкривав правильну поверхню, що належить каналу, для -поточного кроку. +Саме тому зміни маршрутизації embedded-runner усе ще належать до роботи плагіна: runner +відповідає за переспрямування поточної ідентичності чату/сесії до межі +виявлення плагіна, щоб спільний інструмент `message` показував правильну поверхню, +що належить каналу, для поточного кроку. -Для допоміжних засобів виконання, що належать каналу, вбудовані Plugin мають зберігати середовище -виконання всередині власних модулів розширення. Core більше не володіє -середовищами виконання дій із повідомленнями Discord, Slack, Telegram або WhatsApp -у `src/agents/tools`. -Ми не публікуємо окремі підшляхи `plugin-sdk/*-action-runtime`, і вбудовані -Plugin мають імпортувати власний локальний код середовища виконання безпосередньо зі своїх -модулів, що належать розширенню. +Для допоміжних засобів виконання, що належать каналу, вбудовані плагіни мають зберігати середовище +виконання у власних модулях розширень. Core більше не відповідає за +середовища виконання дій повідомлень Discord, Slack, Telegram або WhatsApp у `src/agents/tools`. +Ми не публікуємо окремі підшляхи `plugin-sdk/*-action-runtime`, а вбудовані +плагіни мають імпортувати свій локальний код середовища виконання безпосередньо з +модулів, що належать їхнім розширенням. -Та сама межа застосовується і до SDK-швів із назвами провайдерів загалом: core не повинен -імпортувати зручні панелі, специфічні для каналів, для Slack, Discord, Signal, +Та сама межа застосовується і до поверхонь SDK, названих на честь провайдера, загалом: core не +повинен імпортувати допоміжні barrel-модулі, специфічні для каналів, для Slack, Discord, Signal, WhatsApp або подібних розширень. Якщо core потрібна певна поведінка, слід або -використати власну панель `api.ts` / `runtime-api.ts` вбудованого Plugin, або підняти потребу -до вузької узагальненої можливості у спільному SDK. +використовувати власний barrel `api.ts` / `runtime-api.ts` вбудованого плагіна, або +підняти цю потребу до вузької загальної можливості у спільному SDK. Зокрема для опитувань існує два шляхи виконання: -- `outbound.sendPoll` — це спільна базова лінія для каналів, які відповідають загальній +- `outbound.sendPoll` — це спільна базова лінія для каналів, що відповідають загальній моделі опитувань -- `actions.handleAction("poll")` — це бажаний шлях для специфічної для каналу семантики - опитувань або додаткових параметрів опитувань +- `actions.handleAction("poll")` — це бажаний шлях для семантики опитувань, специфічної для каналу, або + додаткових параметрів опитувань -Тепер Core відкладає спільний розбір опитувань до моменту, коли диспетчеризація опитувань Plugin -відхилить дію, тож обробники опитувань, що належать Plugin, можуть приймати специфічні для каналу -поля опитувань, не будучи заблокованими спочатку загальним парсером опитувань. +Тепер core відкладає спільний розбір опитувань до моменту, коли диспетчеризація опитування плагіна +відхилить дію, щоб обробники опитувань, що належать плагіну, могли приймати поля опитувань, +специфічні для каналу, і не блокувалися спочатку загальним парсером опитувань. -Повну послідовність запуску див. у [Конвеєрі завантаження](#load-pipeline). +Повну послідовність запуску див. у [Конвеєр завантаження](#load-pipeline). ## Модель володіння можливостями -OpenClaw розглядає нативний Plugin як межу володіння для **компанії** або -**функції**, а не як набір не пов’язаних між собою інтеграцій. +OpenClaw розглядає нативний плагін як межу володіння для **компанії** або +**функції**, а не як набір непов’язаних інтеграцій. Це означає таке: -- Plugin компанії зазвичай має володіти всіма поверхнями OpenClaw, що стосуються цієї компанії -- Plugin функції зазвичай має володіти повною поверхнею функції, яку він додає -- канали мають використовувати спільні можливості core замість того, щоб щоразу - заново реалізовувати поведінку провайдера +- плагін компанії зазвичай має володіти всіма поверхнями OpenClaw, що стосуються цієї компанії +- плагін функції зазвичай має володіти повною поверхнею функції, яку він додає +- канали мають використовувати спільні можливості core замість спеціального + повторного впровадження поведінки провайдера Приклади: -- вбудований Plugin `openai` володіє поведінкою провайдера моделей OpenAI та поведінкою OpenAI для +- вбудований плагін `openai` відповідає за поведінку провайдера моделей OpenAI і поведінку OpenAI для мовлення + голосу в реальному часі + розуміння медіа + генерації зображень -- вбудований Plugin `elevenlabs` володіє поведінкою мовлення ElevenLabs -- вбудований Plugin `microsoft` володіє поведінкою мовлення Microsoft -- вбудований Plugin `google` володіє поведінкою провайдера моделей Google, а також поведінкою Google для +- вбудований плагін `elevenlabs` відповідає за поведінку мовлення ElevenLabs +- вбудований плагін `microsoft` відповідає за поведінку мовлення Microsoft +- вбудований плагін `google` відповідає за поведінку провайдера моделей Google, а також за поведінку Google для розуміння медіа + генерації зображень + вебпошуку -- вбудований Plugin `firecrawl` володіє поведінкою Firecrawl для отримання вебданих -- вбудовані Plugin `minimax`, `mistral`, `moonshot` і `zai` володіють своїми - backend для розуміння медіа -- вбудований Plugin `qwen` володіє поведінкою текстового провайдера Qwen, а також - поведінкою розуміння медіа і генерації відео -- Plugin `voice-call` є Plugin функції: він володіє транспортом викликів, інструментами, - CLI, маршрутами та мостом медіапотоків Twilio, але використовує спільні можливості мовлення, - а також транскрипції в реальному часі й голосу в реальному часі, замість - прямого імпорту vendor Plugin +- вбудований плагін `firecrawl` відповідає за поведінку Firecrawl для + отримання вебданих +- вбудовані плагіни `minimax`, `mistral`, `moonshot` і `zai` відповідають за свої + бекенди розуміння медіа +- вбудований плагін `qwen` відповідає за поведінку текстового провайдера Qwen, а також за + розуміння медіа і генерацію відео +- плагін `voice-call` є плагіном функції: він відповідає за транспорт викликів, інструменти, + CLI, маршрути та місток медіапотоку Twilio, але використовує спільні можливості мовлення, + а також транскрипції в реальному часі й голосу в реальному часі замість + прямого імпорту плагінів постачальників -Бажаний кінцевий стан такий: +Бажаний кінцевий стан: -- OpenAI живе в одному Plugin, навіть якщо він охоплює текстові моделі, мовлення, зображення та +- OpenAI живе в одному плагіні, навіть якщо він охоплює текстові моделі, мовлення, зображення та майбутнє відео -- інший вендор може робити те саме для власної області поверхонь -- канали не зважають на те, який vendor Plugin володіє провайдером; вони використовують +- інший постачальник може робити те саме для власної поверхні +- канали не повинні зважати, який плагін постачальника володіє провайдером; вони використовують спільний контракт можливостей, який надає core Ось ключова відмінність: - **plugin** = межа володіння -- **capability** = контракт core, який можуть реалізовувати або використовувати кілька Plugin +- **capability** = контракт core, який можуть реалізовувати або використовувати кілька плагінів -Тож якщо OpenClaw додає нову сферу, як-от відео, перше запитання не таке: -«який провайдер має жорстко закодувати обробку відео?» Перше запитання таке: «який саме -контракт можливостей відео в core?» Щойно такий контракт з’являється, vendor Plugin +Тож якщо OpenClaw додає нову доменну область, наприклад відео, перше питання не +«який провайдер має жорстко закодувати обробку відео?» Перше питання — «яким є +контракт core для можливості відео?» Щойно цей контракт з’являється, плагіни постачальників можуть реєструватися для нього, а плагіни каналів/функцій можуть його використовувати. -Якщо можливість ще не існує, правильний крок зазвичай такий: +Якщо можливість ще не існує, зазвичай правильний крок такий: 1. визначити відсутню можливість у core -2. надати її через API/середовище виконання Plugin у типізований спосіб +2. відкрити її через API/середовище виконання плагіна у типізований спосіб 3. під’єднати канали/функції до цієї можливості -4. дозволити vendor Plugin реєструвати реалізації +4. дозволити плагінам постачальників реєструвати реалізації -Це зберігає явне володіння, водночас уникаючи поведінки core, яка залежить від -одного вендора або одноразового специфічного для Plugin шляху коду. +Це зберігає явність володіння та водночас уникає поведінки core, яка залежить від +одного постачальника або одноразового шляху коду, специфічного для плагіна. ### Шарування можливостей -Використовуйте цю ментальну модель, коли вирішуєте, де має бути код: +Використовуйте цю ментальну модель, коли вирішуєте, де має розміщуватися код: -- **шар можливостей core**: спільна оркестрація, політики, резервна поведінка, правила - злиття config, семантика доставки та типізовані контракти -- **шар vendor Plugin**: vendor-specific API, автентифікація, каталоги моделей, синтез мовлення, - генерація зображень, майбутні backend відео, кінцеві точки використання -- **шар плагінів каналів/функцій**: інтеграція Slack/Discord/voice-call/тощо, - яка використовує можливості core і показує їх на певній поверхні +- **рівень можливостей core**: спільна оркестрація, політика, резервна логіка, правила + злиття конфігурації, семантика доставки та типізовані контракти +- **рівень плагіна постачальника**: API постачальника, автентифікація, каталоги моделей, мовленнєвий + синтез, генерація зображень, майбутні відеобекенди, кінцеві точки використання +- **рівень плагіна каналу/функції**: інтеграція Slack/Discord/voice-call/тощо, + яка використовує можливості core і надає їх на своїй поверхні Наприклад, TTS має таку форму: -- core володіє політикою TTS під час відповіді, порядком резервного використання, prefs і доставкою в канали -- `openai`, `elevenlabs` і `microsoft` володіють реалізаціями синтезу +- core відповідає за політику TTS під час відповіді, порядок резервного вибору, налаштування та доставку каналом +- `openai`, `elevenlabs` і `microsoft` відповідають за реалізації синтезу - `voice-call` використовує допоміжний засіб середовища виконання TTS для телефонії -Той самий шаблон слід надавати перевагу і для майбутніх можливостей. +Такий самий шаблон слід віддавати перевагу і для майбутніх можливостей. -### Приклад Plugin компанії з кількома можливостями +### Приклад плагіна компанії з кількома можливостями -Plugin компанії має виглядати цілісно ззовні. Якщо OpenClaw має спільні +Плагін компанії має сприйматися цілісно ззовні. Якщо OpenClaw має спільні контракти для моделей, мовлення, транскрипції в реальному часі, голосу в реальному часі, розуміння медіа, генерації зображень, генерації відео, отримання вебданих і вебпошуку, -вендор може володіти всіма своїми поверхнями в одному місці: +постачальник може володіти всіма своїми поверхнями в одному місці: ```ts import type { OpenClawPluginDefinition } from "openclaw/plugin-sdk/plugin-entry"; @@ -336,12 +334,12 @@ const plugin: OpenClawPluginDefinition = { register(api) { api.registerProvider({ id: "exampleai", - // хуки auth/каталогу моделей/середовища виконання + // auth/model catalog/runtime hooks }); api.registerSpeechProvider({ id: "exampleai", - // config мовлення вендора — реалізуйте інтерфейс SpeechProviderPlugin безпосередньо + // vendor speech config — implement the SpeechProviderPlugin interface directly }); api.registerMediaUnderstandingProvider({ @@ -366,7 +364,7 @@ const plugin: OpenClawPluginDefinition = { api.registerWebSearchProvider( createPluginBackedWebSearchProvider({ id: "exampleai-search", - // логіка облікових даних + отримання + // credential + fetch logic }), ); }, @@ -377,11 +375,11 @@ export default plugin; Важливі не точні назви допоміжних засобів. Важлива форма: -- один Plugin володіє поверхнею вендора -- core, як і раніше, володіє контрактами можливостей -- канали та плагіни функцій використовують допоміжні засоби `api.runtime.*`, а не код вендора -- контрактні тести можуть перевіряти, що Plugin зареєстрував ті можливості, - якими, за його твердженням, він володіє +- один плагін володіє поверхнею постачальника +- core усе ще володіє контрактами можливостей +- канали та плагіни функцій використовують допоміжні засоби `api.runtime.*`, а не код постачальника +- тести контрактів можуть перевіряти, що плагін зареєстрував можливості, якими + він стверджує, що володіє ### Приклад можливості: розуміння відео @@ -389,230 +387,226 @@ OpenClaw уже розглядає розуміння зображень/ауд можливість. Тут застосовується та сама модель володіння: 1. core визначає контракт розуміння медіа -2. vendor Plugin реєструють `describeImage`, `transcribeAudio` і - `describeVideo`, де це доречно +2. плагіни постачальників реєструють `describeImage`, `transcribeAudio` і + `describeVideo`, де це застосовно 3. канали та плагіни функцій використовують спільну поведінку core замість - прямого підключення до коду вендора + прямого підключення до коду постачальника -Це не дає вбудувати припущення одного провайдера про відео в core. Plugin володіє -поверхнею вендора; core володіє контрактом можливості та резервною поведінкою. +Це запобігає вбудовуванню в core припущень щодо відео одного постачальника. Плагін володіє +поверхнею постачальника; core володіє контрактом можливості та резервною поведінкою. Генерація відео вже використовує ту саму послідовність: core володіє типізованим -контрактом можливості та допоміжним засобом середовища виконання, а vendor Plugin реєструють -реалізації `api.registerVideoGenerationProvider(...)` для цього контракту. +контрактом можливості та допоміжним засобом середовища виконання, а плагіни постачальників реєструють +реалізації `api.registerVideoGenerationProvider(...)` для нього. Потрібен конкретний контрольний список для впровадження? Див. -[Практичний посібник із можливостей](/uk/plugins/architecture). +[Збірник рецептів можливостей](/uk/plugins/architecture). ## Контракти та забезпечення виконання -Поверхня API Plugin навмисно типізована й централізована в +Поверхня API плагіна навмисно типізована та централізована в `OpenClawPluginApi`. Цей контракт визначає підтримувані точки реєстрації та -допоміжні засоби середовища виконання, на які може покладатися Plugin. +допоміжні засоби середовища виконання, на які може спиратися плагін. Чому це важливо: -- автори Plugin отримують єдиний стабільний внутрішній стандарт -- core може відхиляти дубльоване володіння, наприклад коли два Plugin реєструють той самий - id провайдера -- під час запуску можна показувати практичні діагностичні повідомлення для некоректної реєстрації -- контрактні тести можуть забезпечувати володіння вбудованих Plugin і запобігати тихому дрейфу +- автори плагінів отримують один стабільний внутрішній стандарт +- core може відхиляти дубльоване володіння, наприклад коли два плагіни реєструють один і той самий + ідентифікатор провайдера +- під час запуску можна показувати зрозумілі діагностичні повідомлення для некоректної реєстрації +- тести контрактів можуть забезпечувати володіння вбудованих плагінів і запобігати непомітному дрейфу -Є два шари забезпечення виконання: +Існує два рівні забезпечення виконання: -1. **забезпечення виконання реєстрації під час роботи** - Реєстр Plugin перевіряє реєстрації під час завантаження Plugin. Приклади: - дубльовані id провайдерів, дубльовані id провайдерів мовлення та некоректні - реєстрації створюють діагностику Plugin замість невизначеної поведінки. -2. **контрактні тести** - Вбудовані Plugin фіксуються в реєстрах контрактів під час запуску тестів, щоб - OpenClaw міг явно перевіряти володіння. Сьогодні це використовується для - провайдерів моделей, провайдерів мовлення, провайдерів вебпошуку та володіння - реєстрацією вбудованих Plugin. +1. **забезпечення виконання реєстрації під час виконання** + Реєстр плагінів перевіряє реєстрації під час завантаження плагінів. Приклади: + дубльовані ідентифікатори провайдерів, дубльовані ідентифікатори мовленнєвих провайдерів і некоректні + реєстрації породжують діагностику плагіна замість невизначеної поведінки. +2. **тести контрактів** + Вбудовані плагіни фіксуються в реєстрах контрактів під час запуску тестів, щоб + OpenClaw міг явно перевіряти володіння. Сьогодні це використовується для моделей + провайдерів, мовленнєвих провайдерів, провайдерів вебпошуку та володіння реєстрацією вбудованих плагінів. -Практичний ефект полягає в тому, що OpenClaw заздалегідь знає, який Plugin якою -поверхнею володіє. Це дає змогу core і каналам безшовно компонуватися, оскільки володіння -задеклароване, типізоване й придатне до тестування, а не неявне. +Практичний ефект полягає в тому, що OpenClaw заздалегідь знає, який плагін якою +поверхнею володіє. Це дозволяє core і каналам компонуватися безшовно, оскільки володіння +оголошене, типізоване й перевірюване, а не неявне. ### Що має входити до контракту -Хороші контракти Plugin: +Хороші контракти плагінів: - типізовані -- невеликі -- специфічні для можливостей +- малі +- специфічні для можливості - належать core -- придатні для повторного використання кількома Plugin -- можуть використовуватися каналами/функціями без знання про вендора +- придатні для повторного використання кількома плагінами +- можуть використовуватися каналами/функціями без знання про постачальника -Погані контракти Plugin: +Погані контракти плагінів: -- vendor-specific політика, прихована в core -- одноразові лазівки для Plugin, які обходять реєстр -- код каналу, який напряму звертається до реалізації вендора -- ad hoc об’єкти середовища виконання, які не є частиною `OpenClawPluginApi` або +- політика, специфічна для постачальника, прихована в core +- одноразові аварійні механізми плагіна, які обходять реєстр +- код каналу, що напряму звертається до реалізації постачальника +- спеціальні об’єкти середовища виконання, які не є частиною `OpenClawPluginApi` або `api.runtime` -Якщо є сумнів, підніміть рівень абстракції: спочатку визначте можливість, а вже потім -дозвольте Plugin підключатися до неї. +Якщо є сумніви, підніміть рівень абстракції: спочатку визначте можливість, а вже потім +дозвольте плагінам підключатися до неї. ## Модель виконання -Нативні Plugin OpenClaw виконуються **в межах процесу** разом із Gateway. Вони не -ізольовані в sandbox. Завантажений нативний Plugin має ту саму межу довіри на рівні процесу, що й +Нативні плагіни OpenClaw виконуються **у процесі** разом із Gateway. Вони не +ізольовані. Завантажений нативний плагін має ту саму межу довіри на рівні процесу, що й код core. Наслідки: -- нативний Plugin може реєструвати інструменти, мережеві обробники, хуки та сервіси -- помилка нативного Plugin може спричинити збій або дестабілізувати gateway -- зловмисний нативний Plugin еквівалентний довільному виконанню коду всередині +- нативний плагін може реєструвати інструменти, мережеві обробники, хуки та сервіси +- помилка в нативному плагіні може аварійно завершити роботу gateway або дестабілізувати його +- зловмисний нативний плагін еквівалентний довільному виконанню коду всередині процесу OpenClaw -Сумісні пакети безпечніші за замовчуванням, тому що OpenClaw наразі розглядає їх -як пакети метаданих/контенту. У поточних релізах це здебільшого означає вбудовані +Сумісні пакети безпечніші за замовчуванням, оскільки OpenClaw наразі розглядає їх +як пакети метаданих/контенту. У поточних випусках це здебільшого означає вбудовані Skills. -Використовуйте allowlist і явні шляхи встановлення/завантаження для невбудованих Plugin. Розглядайте -Plugin робочого простору як код етапу розробки, а не як виробничі значення за замовчуванням. +Для невбудованих плагінів використовуйте allowlist і явні шляхи встановлення/завантаження. Розглядайте +плагіни робочого простору як код часу розробки, а не стандартні параметри production. -Для імен пакетів вбудованого робочого простору зберігайте id Plugin прив’язаним до npm-імені: -`@openclaw/` за замовчуванням або до схваленого типізованого суфікса, як-от -`-provider`, `-plugin`, `-speech`, `-sandbox` або `-media-understanding`, коли -пакет навмисно надає вужчу роль Plugin. +Для імен пакетів вбудованого робочого простору зберігайте ідентифікатор плагіна прив’язаним до імені npm: +`@openclaw/` за замовчуванням або затверджений типізований суфікс, як-от +`-provider`, `-plugin`, `-speech`, `-sandbox` чи `-media-understanding`, коли +пакет навмисно надає вужчу роль плагіна. Важлива примітка щодо довіри: -- `plugins.allow` довіряє **id Plugin**, а не походженню джерела. -- Plugin робочого простору з тим самим id, що й у вбудованого Plugin, навмисно затіняє - вбудовану копію, коли цей Plugin робочого простору увімкнено/додано до allowlist. -- Це нормально й корисно для локальної розробки, тестування патчів і hotfix. +- `plugins.allow` довіряє **ідентифікаторам плагінів**, а не походженню джерела. +- Плагін робочого простору з тим самим ідентифікатором, що й у вбудованого плагіна, навмисно затіняє + вбудовану копію, коли цей плагін робочого простору увімкнено/додано до allowlist. +- Це нормально й корисно для локальної розробки, тестування виправлень і hotfix. ## Межа експорту -OpenClaw експортує можливості, а не зручні засоби реалізації. +OpenClaw експортує можливості, а не зручні реалізації. -Зберігайте публічність реєстрації можливостей. Скорочуйте експорт допоміжних засобів, які не є частиною контракту: +Зберігайте реєстрацію можливостей публічною. Скорочуйте експорти допоміжних засобів, які не є контрактами: -- підшляхи, специфічні для вбудованих Plugin -- підшляхи внутрішньої логіки середовища виконання, які не призначені як публічний API -- vendor-specific допоміжні засоби +- підшляхи допоміжних засобів, специфічні для вбудованих плагінів +- підшляхи внутрішньої логіки середовища виконання, не призначені як публічний API +- зручні допоміжні засоби, специфічні для постачальників - допоміжні засоби налаштування/onboarding, які є деталями реалізації -Деякі підшляхи допоміжних засобів вбудованих Plugin усе ще залишаються в згенерованій -карті експортів SDK для сумісності та підтримки вбудованих Plugin. Поточні приклади включають +Деякі підшляхи допоміжних засобів вбудованих плагінів усе ще залишаються в згенерованій +карті експорту SDK задля сумісності та підтримки вбудованих плагінів. Поточні приклади включають `plugin-sdk/feishu`, `plugin-sdk/feishu-setup`, `plugin-sdk/zalo`, -`plugin-sdk/zalo-setup` і кілька швів `plugin-sdk/matrix*`. Розглядайте їх як -зарезервовані експорти деталей реалізації, а не як рекомендований шаблон SDK для -нових сторонніх Plugin. +`plugin-sdk/zalo-setup` і кілька поверхонь `plugin-sdk/matrix*`. Вважайте їх +зарезервованими експортами деталей реалізації, а не рекомендованим шаблоном SDK для +нових сторонніх плагінів. ## Конвеєр завантаження Під час запуску OpenClaw приблизно виконує таке: -1. виявляє корені потенційних Plugin -2. читає нативні маніфести або маніфести сумісних пакетів і метадані пакетів -3. відхиляє небезпечні кандидати -4. нормалізує config Plugin (`plugins.enabled`, `allow`, `deny`, `entries`, +1. виявляє корені кандидатів у плагіни +2. читає нативні або сумісні маніфести пакетів і метадані пакетів +3. відхиляє небезпечних кандидатів +4. нормалізує конфігурацію плагінів (`plugins.enabled`, `allow`, `deny`, `entries`, `slots`, `load.paths`) -5. вирішує, чи вмикати кожного кандидата +5. визначає, чи ввімкнений кожен кандидат 6. завантажує ввімкнені нативні модулі через jiti -7. викликає нативні хуки `register(api)` (або `activate(api)` — застарілий псевдонім) і збирає реєстрації в реєстр Plugin +7. викликає нативні хуки `register(api)` (або `activate(api)` — застарілий псевдонім) і збирає реєстрації до реєстру плагінів 8. відкриває реєстр для поверхонь команд/середовища виконання -`activate` — це застарілий псевдонім для `register`: завантажувач визначає, що саме присутнє (`def.register ?? def.activate`), і викликає це в тій самій точці. Усі вбудовані Plugin використовують `register`; для нових Plugin надавайте перевагу `register`. +`activate` — це застарілий псевдонім для `register` — завантажувач визначає, що саме присутнє (`def.register ?? def.activate`), і викликає це в тій самій точці. Усі вбудовані плагіни використовують `register`; для нових плагінів надавайте перевагу `register`. -Запобіжні перевірки виконуються **до** виконання коду середовища виконання. Кандидати блокуються, -коли точка входу виходить за межі кореня Plugin, шлях має дозвіл на запис для всіх, або -володіння шляхом виглядає підозріло для невбудованих Plugin. +Перевірки безпеки відбуваються **до** виконання коду середовища виконання. Кандидати блокуються, +коли точка входу виходить за межі кореня плагіна, шлях доступний для запису всім, або +володіння шляхом виглядає підозріло для невбудованих плагінів. -### Поведінка на основі маніфесту +### Поведінка manifest-first -Маніфест — це джерело істини для control plane. OpenClaw використовує його, щоб: +Маніфест є джерелом істини для control plane. OpenClaw використовує його, щоб: -- ідентифікувати Plugin -- виявляти оголошені канали/Skills/схему config або можливості пакетів +- ідентифікувати плагін +- виявляти оголошені канали/Skills/схему конфігурації або можливості пакетів - перевіряти `plugins.entries..config` -- доповнювати мітки/placeholder у Control UI +- доповнювати мітки/placeholder-и Control UI - показувати метадані встановлення/каталогу -- зберігати дешеві дескриптори активації та налаштування без завантаження середовища виконання Plugin +- зберігати дешеві дескриптори активації та налаштування без завантаження середовища виконання плагіна -Для нативних Plugin модуль середовища виконання є частиною data plane. Він реєструє -фактичну поведінку, як-от хуки, інструменти, команди або потоки провайдера. +Для нативних плагінів модуль середовища виконання є частиною data plane. Він реєструє +фактичну поведінку, таку як хуки, інструменти, команди або потоки провайдера. Необов’язкові блоки маніфесту `activation` і `setup` залишаються в control plane. -Це дескриптори лише з метаданими для планування активації та виявлення налаштування; +Це лише дескриптори метаданих для планування активації та виявлення налаштування; вони не замінюють реєстрацію середовища виконання, `register(...)` або `setupEntry`. -Перші споживачі живої активації тепер використовують підказки маніфесту щодо команд, каналів і провайдерів, -щоб звузити завантаження Plugin до ширшої матеріалізації реєстру: +Перші живі споживачі активації тепер використовують підказки маніфесту для команд, каналів і провайдерів, +щоб звузити завантаження плагінів до ширшої матеріалізації реєстру: -- завантаження CLI звужується до Plugin, які володіють запитаною основною командою -- налаштування каналу/визначення Plugin звужується до Plugin, які володіють запитаним - id каналу -- явне налаштування/визначення середовища виконання провайдера звужується до Plugin, які володіють - запитаним id провайдера +- завантаження CLI звужується до плагінів, які володіють запитаною основною командою +- налаштування каналу/визначення плагіна звужується до плагінів, які володіють запитаним + ідентифікатором каналу +- явне налаштування/визначення середовища виконання провайдера звужується до плагінів, які володіють + запитаним ідентифікатором провайдера -Виявлення налаштування тепер надає перевагу id, що належать дескрипторам, як-от `setup.providers` і -`setup.cliBackends`, щоб звузити коло потенційних Plugin до того, як воно повернеться до -`setup-api` для Plugin, яким усе ще потрібні хуки середовища виконання під час налаштування. Якщо більше -ніж один знайдений Plugin заявляє про той самий нормалізований id провайдера налаштування або backend CLI, -пошук налаштування відмовляється від неоднозначного власника замість того, щоб покладатися на порядок -виявлення. +Виявлення налаштування тепер віддає перевагу ідентифікаторам, що належать дескрипторам, таким як `setup.providers` і +`setup.cliBackends`, щоб звузити коло кандидатів у плагіни, перш ніж воно повернеться до +`setup-api` для плагінів, яким усе ще потрібні хуки середовища виконання на етапі налаштування. Якщо більше +ніж один виявлений плагін заявляє той самий нормалізований ідентифікатор провайдера налаштування або CLI-бекенда, +пошук налаштування відхиляє неоднозначного власника замість того, щоб покладатися на порядок виявлення. ### Що кешує завантажувач -OpenClaw зберігає короткоживучі кеші в межах процесу для: +OpenClaw зберігає короткочасні внутрішньопроцесні кеші для: - результатів виявлення - даних реєстру маніфестів -- реєстрів завантажених Plugin +- реєстрів завантажених плагінів -Ці кеші зменшують пікові витрати під час запуску та повторних викликів команд. Їх безпечно -сприймати як короткоживучі кеші продуктивності, а не як постійне зберігання. +Ці кеші зменшують пікове навантаження під час запуску та накладні витрати від повторних команд. Їх безпечно +сприймати як короткоживучі кеші продуктивності, а не як збереження стану. Примітка щодо продуктивності: -- Установіть `OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1` або +- Встановіть `OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1` або `OPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1`, щоб вимкнути ці кеші. -- Налаштовуйте вікна кешу через `OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS` і +- Налаштуйте вікна кешу за допомогою `OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS` і `OPENCLAW_PLUGIN_MANIFEST_CACHE_MS`. ## Модель реєстру -Завантажені Plugin не змінюють напряму довільні глобальні змінні core. Вони реєструються в -центральному реєстрі Plugin. +Завантажені плагіни не змінюють напряму довільні глобальні об’єкти core. Вони реєструються в +центральному реєстрі плагінів. Реєстр відстежує: -- записи Plugin (ідентичність, джерело, походження, статус, діагностика) +- записи плагінів (ідентичність, джерело, походження, статус, діагностика) - інструменти - застарілі хуки та типізовані хуки - канали -- провайдери +- провайдерів - обробники Gateway RPC - HTTP-маршрути - реєстратори CLI - фонові сервіси -- команди, що належать Plugin +- команди, що належать плагінам -Потім можливості core читають із цього реєстру замість прямої взаємодії з модулями Plugin. -Це зберігає односпрямоване завантаження: +Потім можливості core читають із цього реєстру замість прямої взаємодії з модулями плагінів. +Це зберігає завантаження односпрямованим: -- модуль Plugin -> реєстрація в реєстрі -- середовище виконання core -> споживання реєстру +- модуль плагіна -> реєстрація в реєстрі +- середовище виконання core -> споживання з реєстру -Це розділення важливе для підтримуваності. Воно означає, що більшості поверхонь core -потрібна лише одна точка інтеграції: «читати реєстр», а не «робити спеціальний випадок для кожного -модуля Plugin». +Це розділення важливе для підтримуваності. Воно означає, що більшості поверхонь core потрібна +лише одна точка інтеграції: «читати реєстр», а не «окремо обробляти кожен модуль плагіна». -## Зворотні виклики прив’язки розмов +## Колбеки прив’язки розмови -Plugin, які прив’язують розмову, можуть реагувати, коли схвалення вирішено. +Плагіни, які прив’язують розмову, можуть реагувати, коли схвалення вирішено. -Використовуйте `api.onConversationBindingResolved(...)`, щоб отримати зворотний виклик після схвалення -або відхилення запиту на прив’язку: +Використовуйте `api.onConversationBindingResolved(...)`, щоб отримати колбек після того, як запит на прив’язку буде схвалено або відхилено: ```ts export default { @@ -620,39 +614,39 @@ export default { register(api) { api.onConversationBindingResolved(async (event) => { if (event.status === "approved") { - // Прив’язка тепер існує для цього plugin + conversation. + // A binding now exists for this plugin + conversation. console.log(event.binding?.conversationId); return; } - // Запит було відхилено; очистьте будь-який локальний стан очікування. + // The request was denied; clear any local pending state. console.log(event.request.conversation.conversationId); }); }, }; ``` -Поля корисного навантаження зворотного виклику: +Поля корисного навантаження колбека: - `status`: `"approved"` або `"denied"` - `decision`: `"allow-once"`, `"allow-always"` або `"deny"` -- `binding`: визначена прив’язка для схвалених запитів -- `request`: підсумок початкового запиту, підказка від’єднання, id відправника та +- `binding`: вирішена прив’язка для схвалених запитів +- `request`: оригінальне зведення запиту, підказка від’єднання, ідентифікатор відправника та метадані розмови -Цей зворотний виклик є лише сповіщенням. Він не змінює того, кому дозволено прив’язувати +Цей колбек призначений лише для сповіщення. Він не змінює того, кому дозволено прив’язувати розмову, і виконується після завершення обробки схвалення в core. ## Хуки середовища виконання провайдера -Плагіни провайдерів тепер мають два шари: +Плагіни провайдерів тепер мають два рівні: -- метадані маніфесту: `providerAuthEnvVars` для дешевого пошуку env-auth провайдера - до завантаження середовища виконання, `providerAuthAliases` для варіантів провайдерів, які спільно використовують - auth, `channelEnvVars` для дешевого пошуку env/налаштування каналу до завантаження середовища - виконання, а також `providerAuthChoices` для дешевих міток onboarding/вибору auth і +- метадані маніфесту: `providerAuthEnvVars` для дешевого пошуку env-автентифікації провайдера + до завантаження середовища виконання, `providerAuthAliases` для варіантів провайдера, які спільно використовують + автентифікацію, `channelEnvVars` для дешевого пошуку env/налаштування каналу до + завантаження середовища виконання, а також `providerAuthChoices` для дешевих міток onboarding/вибору автентифікації та метаданих прапорців CLI до завантаження середовища виконання -- хуки часу config: `catalog` / застарілий `discovery` плюс `applyConfigDefaults` +- хуки часу конфігурації: `catalog` / застарілий `discovery` плюс `applyConfigDefaults` - хуки середовища виконання: `normalizeModelId`, `normalizeTransport`, `normalizeConfig`, `applyNativeStreamingUsageCompat`, `resolveConfigApiKey`, @@ -673,89 +667,89 @@ export default { `buildReplayPolicy`, `sanitizeReplayHistory`, `validateReplayTurns`, `onModelSelected` -OpenClaw, як і раніше, володіє узагальненим циклом агента, перемиканням на резервний варіант, обробкою -транскриптів та політикою інструментів. Ці хуки — це поверхня розширення для специфічної для провайдера -поведінки без потреби в повністю власному транспорті висновку. +OpenClaw, як і раніше, володіє загальним циклом агента, failover, обробкою транскриптів та +політикою інструментів. Ці хуки є поверхнею розширення для поведінки, специфічної для провайдера, без +потреби в повністю власному транспорті інференсу. -Використовуйте маніфест `providerAuthEnvVars`, коли провайдер має облікові дані на основі env, -які узагальнені шляхи auth/status/model-picker повинні бачити без завантаження середовища виконання Plugin. -Використовуйте маніфест `providerAuthAliases`, коли один id провайдера має повторно використовувати -env vars, профілі auth, auth на основі config та варіант onboarding API key іншого id провайдера. -Використовуйте маніфест `providerAuthChoices`, коли поверхні CLI для onboarding/вибору auth -мають знати id вибору провайдера, мітки груп і просту схему auth з одним прапорцем -без завантаження середовища виконання провайдера. Зберігайте `envVars` середовища виконання провайдера для -операторських підказок, таких як мітки onboarding або -змінні налаштування OAuth client-id/client-secret. +Використовуйте `providerAuthEnvVars` у маніфесті, коли провайдер має облікові дані на основі env, +які загальні шляхи автентифікації/статусу/вибору моделі мають бачити без завантаження середовища виконання плагіна. +Використовуйте `providerAuthAliases` у маніфесті, коли один ідентифікатор провайдера має повторно використовувати +env-змінні, профілі автентифікації, автентифікацію на основі конфігурації та варіант onboarding API-ключа +іншого ідентифікатора провайдера. Використовуйте `providerAuthChoices` у маніфесті, коли поверхні CLI для onboarding/вибору автентифікації +мають знати ідентифікатор варіанта провайдера, мітки груп і просте +підключення автентифікації з одним прапорцем без завантаження середовища виконання провайдера. Зберігайте `envVars` у середовищі виконання провайдера +для підказок, орієнтованих на операторів, таких як мітки onboarding або змінні налаштування +client-id/client-secret OAuth. -Використовуйте маніфест `channelEnvVars`, коли канал має auth або налаштування на основі env, які -узагальнений резервний шлях shell-env, перевірки config/status або підказки налаштування повинні бачити +Використовуйте `channelEnvVars` у маніфесті, коли канал має автентифікацію або налаштування на основі env, +які загальний fallback shell-env, перевірки конфігурації/статусу або запити налаштування мають бачити без завантаження середовища виконання каналу. -### Порядок і використання хуків +### Порядок хуків і використання -Для Plugin моделей/провайдерів OpenClaw викликає хуки приблизно в такому порядку. -Стовпець «Коли використовувати» — це короткий посібник для прийняття рішень. +Для плагінів моделей/провайдерів OpenClaw викликає хуки приблизно в такому порядку. +Стовпець «Коли використовувати» — це короткий орієнтир для вибору. | # | Хук | Що він робить | Коли використовувати | | --- | --------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | `catalog` | Публікує config провайдера в `models.providers` під час генерації `models.json` | Провайдер володіє каталогом або значеннями `base URL` за замовчуванням | -| 2 | `applyConfigDefaults` | Застосовує глобальні значення config за замовчуванням, що належать провайдеру, під час матеріалізації config | Значення за замовчуванням залежать від режиму auth, env або семантики сімейства моделей провайдера | -| -- | _(built-in model lookup)_ | OpenClaw спочатку намагається використати звичайний шлях реєстру/каталогу | _(це не хук Plugin)_ | -| 3 | `normalizeModelId` | Нормалізує застарілі або preview-псевдоніми model-id перед пошуком | Провайдер володіє очищенням псевдонімів перед визначенням канонічної моделі | -| 4 | `normalizeTransport` | Нормалізує `api` / `baseUrl` сімейства провайдера перед загальним складанням моделі | Провайдер володіє очищенням транспорту для користувацьких id провайдера в тому самому сімействі транспорту | -| 5 | `normalizeConfig` | Нормалізує `models.providers.` перед визначенням середовища виконання/провайдера | Провайдеру потрібно очищення config, яке має жити разом із Plugin; вбудовані допоміжні засоби сімейства Google також страхують підтримувані записи Google config | -| 6 | `applyNativeStreamingUsageCompat` | Застосовує compat-переписування native streaming-usage до config провайдерів | Провайдеру потрібні виправлення метаданих native streaming usage, що залежать від кінцевої точки | -| 7 | `resolveConfigApiKey` | Визначає auth через env-marker для config провайдерів до завантаження auth середовища виконання | Провайдер має власне визначення API key через env-marker; `amazon-bedrock` тут також має вбудований AWS env-marker resolver | -| 8 | `resolveSyntheticAuth` | Показує локальний/self-hosted або auth на основі config без збереження відкритого тексту | Провайдер може працювати із синтетичним/локальним маркером облікових даних | -| 9 | `resolveExternalAuthProfiles` | Накладає зовнішні профілі auth, що належать провайдеру; типове значення `persistence` — `runtime-only` для облікових даних CLI/app | Провайдер повторно використовує зовнішні облікові дані auth без збереження скопійованих refresh token | -| 10 | `shouldDeferSyntheticProfileAuth` | Знижує пріоритет збережених синтетичних placeholder профілів порівняно з auth на основі env/config | Провайдер зберігає синтетичні placeholder-профілі, які не повинні мати вищий пріоритет | -| 11 | `resolveDynamicModel` | Синхронний резервний варіант для model id, що належать провайдеру, але ще не є в локальному реєстрі | Провайдер приймає довільні upstream model id | -| 12 | `prepareDynamicModel` | Асинхронний розігрів, після чого `resolveDynamicModel` запускається знову | Провайдеру потрібні мережеві метадані перед визначенням невідомих id | -| 13 | `normalizeResolvedModel` | Фінальне переписування перед тим, як embedded runner використовує визначену модель | Провайдеру потрібне переписування транспорту, але він усе ще використовує транспорт core | -| 14 | `contributeResolvedModelCompat` | Додає compat-прапорці для моделей вендора за іншим сумісним транспортом | Провайдер розпізнає власні моделі на проксі-транспорті, не перебираючи на себе володіння провайдером | -| 15 | `capabilities` | Метадані транскриптів/інструментів, що належать провайдеру та використовуються спільною логікою core | Провайдеру потрібні особливості транскриптів/сімейства провайдерів | -| 16 | `normalizeToolSchemas` | Нормалізує схеми інструментів до того, як їх побачить embedded runner | Провайдеру потрібне очищення схем для сімейства транспорту | -| 17 | `inspectToolSchemas` | Показує діагностику схем, що належить провайдеру, після нормалізації | Провайдер хоче попередження про ключові слова без додавання в core правил, специфічних для провайдера | -| 18 | `resolveReasoningOutputMode` | Вибирає нативний або тегований контракт reasoning-output | Провайдеру потрібен тегований reasoning/final output замість нативних полів | -| 19 | `prepareExtraParams` | Нормалізація параметрів запиту перед загальними обгортками параметрів потоку | Провайдеру потрібні параметри запиту за замовчуванням або очищення параметрів для конкретного провайдера | -| 20 | `createStreamFn` | Повністю замінює звичайний шлях потоку користувацьким транспортом | Провайдеру потрібен власний wire protocol, а не просто обгортка | -| 21 | `wrapStreamFn` | Обгортка потоку після застосування загальних обгорток | Провайдеру потрібні обгортки сумісності заголовків/тіла/model запиту без користувацького транспорту | -| 22 | `resolveTransportTurnState` | Прикріплює нативні заголовки або метадані транспорту для кожного кроку | Провайдер хоче, щоб загальні транспорти надсилали нативну ідентичність кроку провайдера | -| 23 | `resolveWebSocketSessionPolicy` | Прикріплює нативні заголовки WebSocket або політику охолодження сеансу | Провайдер хоче, щоб загальні WS-транспорти налаштовували заголовки сеансу або політику резервного варіанта | -| 24 | `formatApiKey` | Форматувач профілю auth: збережений профіль стає рядком `apiKey` середовища виконання | Провайдер зберігає додаткові метадані auth і потребує користувацької форми runtime token | -| 25 | `refreshOAuth` | Перевизначення оновлення OAuth для користувацьких endpoint оновлення або політики помилок оновлення | Провайдер не відповідає спільним механізмам оновлення `pi-ai` | -| 26 | `buildAuthDoctorHint` | Підказка з виправлення, яка додається, коли оновлення OAuth завершується помилкою | Провайдеру потрібні власні вказівки з відновлення auth після помилки оновлення | -| 27 | `matchesContextOverflowError` | Власний засіб зіставлення помилок переповнення контекстного вікна | Провайдер має сирі помилки переповнення, які пропустять загальні евристики | -| 28 | `classifyFailoverReason` | Власна класифікація причин переходу на резервний варіант | Провайдер може зіставляти сирі помилки API/транспорту з rate-limit/перевантаженням тощо | -| 29 | `isCacheTtlEligible` | Політика prompt-cache для проксі/магістральних провайдерів | Провайдеру потрібне керування TTL кешу, специфічне для проксі | -| 30 | `buildMissingAuthMessage` | Замінює загальне повідомлення відновлення для відсутнього auth | Провайдеру потрібна власна підказка з відновлення для випадку відсутнього auth | -| 31 | `suppressBuiltInModel` | Приховування застарілих upstream-моделей плюс необов’язкова користувацька підказка про помилку | Провайдеру потрібно приховати застарілі upstream-рядки або замінити їх підказкою від вендора | -| 32 | `augmentModelCatalog` | Синтетичні/фінальні рядки каталогу, додані після виявлення | Провайдеру потрібні синтетичні рядки прямої сумісності в `models list` і селекторах | -| 33 | `resolveThinkingProfile` | Рівень `/think`, мітки відображення та значення за замовчуванням для конкретної моделі | Провайдер надає власну шкалу thinking або двійкову мітку для вибраних моделей | -| 34 | `isBinaryThinking` | Хук сумісності для двійкового перемикача reasoning увімкнено/вимкнено | Провайдер надає лише двійковий режим thinking увімкнено/вимкнено | -| 35 | `supportsXHighThinking` | Хук сумісності для підтримки reasoning `xhigh` | Провайдер хоче `xhigh` лише для підмножини моделей | -| 36 | `resolveDefaultThinkingLevel` | Хук сумісності для рівня `/think` за замовчуванням | Провайдер володіє політикою `/think` за замовчуванням для сімейства моделей | -| 37 | `isModernModelRef` | Засіб зіставлення modern-model для фільтрів live profile і вибору smoke | Провайдер володіє зіставленням бажаних моделей для live/smoke | -| 38 | `prepareRuntimeAuth` | Обмінює налаштовані облікові дані на фактичний runtime token/key безпосередньо перед висновком | Провайдеру потрібен обмін token або короткоживучі облікові дані запиту | -| 39 | `resolveUsageAuth` | Визначає облікові дані використання/білінгу для `/usage` і пов’язаних поверхонь статусу | Провайдеру потрібен користувацький розбір token використання/квоти або інші облікові дані використання | -| 40 | `fetchUsageSnapshot` | Отримує й нормалізує специфічні для провайдера знімки використання/квоти після визначення auth | Провайдеру потрібна специфічна для провайдера endpoint використання або парсер корисного навантаження | -| 41 | `createEmbeddingProvider` | Створює адаптер embedding, що належить провайдеру, для пам’яті/пошуку | Поведінка embedding для пам’яті має належати Plugin провайдера | -| 42 | `buildReplayPolicy` | Повертає політику replay, яка керує обробкою транскриптів для провайдера | Провайдеру потрібна власна політика транскриптів, наприклад видалення блоків thinking | -| 43 | `sanitizeReplayHistory` | Переписує історію replay після загального очищення транскрипту | Провайдеру потрібні специфічні для провайдера переписування replay понад спільні допоміжні засоби Compaction | -| 44 | `validateReplayTurns` | Фінальна валідація або переформування кроків replay перед embedded runner | Транспорту провайдера потрібна суворіша валідація кроків після загальної санітизації | -| 45 | `onModelSelected` | Виконує побічні ефекти після вибору моделі, що належать провайдеру | Провайдеру потрібна телеметрія або стан, що належить провайдеру, коли модель стає активною | +| 1 | `catalog` | Публікує конфігурацію провайдера в `models.providers` під час генерації `models.json` | Провайдер володіє каталогом або базовими значеннями `base URL` | +| 2 | `applyConfigDefaults` | Застосовує глобальні значення конфігурації за замовчуванням, що належать провайдеру, під час матеріалізації конфігурації | Значення за замовчуванням залежать від режиму автентифікації, env або семантики сімейства моделей провайдера | +| -- | _(built-in model lookup)_ | OpenClaw спочатку намагається використати звичайний шлях реєстру/каталогу | _(не є хуком плагіна)_ | +| 3 | `normalizeModelId` | Нормалізує застарілі або preview-псевдоніми model-id перед пошуком | Провайдер володіє очищенням псевдонімів перед визначенням канонічної моделі | +| 4 | `normalizeTransport` | Нормалізує `api` / `baseUrl` сімейства провайдера перед загальним складанням моделі | Провайдер володіє очищенням транспорту для користувацьких ідентифікаторів провайдера в тому самому сімействі транспорту | +| 5 | `normalizeConfig` | Нормалізує `models.providers.` перед визначенням середовища виконання/провайдера | Провайдеру потрібне очищення конфігурації, яке має жити разом із плагіном; вбудовані допоміжні засоби сімейства Google також підстраховують підтримувані записи конфігурації Google | +| 6 | `applyNativeStreamingUsageCompat` | Застосовує переписування сумісності використання нативного потокового режиму до провайдерів конфігурації | Провайдеру потрібні виправлення метаданих використання нативного потокового режиму, керовані кінцевими точками | +| 7 | `resolveConfigApiKey` | Визначає env-marker автентифікацію для провайдерів конфігурації до завантаження автентифікації середовища виконання | Провайдер має визначення API-ключа env-marker, що належить провайдеру; `amazon-bedrock` також має тут вбудований AWS-резолвер env-marker | +| 8 | `resolveSyntheticAuth` | Показує локальну/self-hosted або засновану на конфігурації автентифікацію без збереження відкритого тексту | Провайдер може працювати із synthetic/local маркером облікових даних | +| 9 | `resolveExternalAuthProfiles` | Накладає зовнішні профілі автентифікації, що належать провайдеру; типове значення `persistence` — `runtime-only` для облікових даних CLI/застосунку | Провайдер повторно використовує зовнішні облікові дані автентифікації без збереження скопійованих refresh token | +| 10 | `shouldDeferSyntheticProfileAuth` | Знижує пріоритет збережених synthetic placeholder-профілів порівняно з автентифікацією на основі env/конфігурації | Провайдер зберігає synthetic placeholder-профілі, які не мають отримувати вищий пріоритет | +| 11 | `resolveDynamicModel` | Синхронний резервний механізм для model id, що належать провайдеру, яких ще немає в локальному реєстрі | Провайдер приймає довільні upstream model id | +| 12 | `prepareDynamicModel` | Асинхронний прогрів, після чого `resolveDynamicModel` запускається знову | Провайдеру потрібні мережеві метадані перед визначенням невідомих ідентифікаторів | +| 13 | `normalizeResolvedModel` | Остаточне переписування перед тим, як embedded runner використає визначену модель | Провайдеру потрібні переписування транспорту, але він усе ще використовує транспорт core | +| 14 | `contributeResolvedModelCompat` | Додає прапорці сумісності для моделей постачальника за іншим сумісним транспортом | Провайдер розпізнає власні моделі на proxy-транспортах, не перебираючи на себе провайдера | +| 15 | `capabilities` | Метадані транскрипту/інструментів, що належать провайдеру та використовуються спільною логікою core | Провайдеру потрібні особливості транскрипту/сімейства провайдерів | +| 16 | `normalizeToolSchemas` | Нормалізує схеми інструментів до того, як їх побачить embedded runner | Провайдеру потрібне очищення схем сімейства транспорту | +| 17 | `inspectToolSchemas` | Показує діагностику схем, що належить провайдеру, після нормалізації | Провайдер хоче попередження щодо ключових слів без навчання core правилам, специфічним для провайдера | +| 18 | `resolveReasoningOutputMode` | Вибирає нативний або позначений тегами контракт виводу міркувань | Провайдеру потрібен позначений тегами вивід міркувань/фінальний вивід замість нативних полів | +| 19 | `prepareExtraParams` | Нормалізація параметрів запиту перед загальними обгортками параметрів потоку | Провайдеру потрібні параметри запиту за замовчуванням або очищення параметрів для конкретного провайдера | +| 20 | `createStreamFn` | Повністю замінює звичайний шлях потоку користувацьким транспортом | Провайдеру потрібен користувацький протокол передавання даних, а не просто обгортка | +| 21 | `wrapStreamFn` | Обгортка потоку після застосування загальних обгорток | Провайдеру потрібні обгортки сумісності заголовків/тіла/моделі запиту без користувацького транспорту | +| 22 | `resolveTransportTurnState` | Додає нативні заголовки транспорту або метадані для кожного ходу | Провайдер хоче, щоб загальні транспорти надсилали нативну для провайдера ідентичність ходу | +| 23 | `resolveWebSocketSessionPolicy` | Додає нативні заголовки WebSocket або політику охолодження сесії | Провайдер хоче, щоб загальні WS-транспорти налаштовували заголовки сесії або політику резервного режиму | +| 24 | `formatApiKey` | Форматувач профілю автентифікації: збережений профіль стає рядком `apiKey` середовища виконання | Провайдер зберігає додаткові метадані автентифікації й потребує користувацької форми токена для середовища виконання | +| 25 | `refreshOAuth` | Перевизначення оновлення OAuth для користувацьких кінцевих точок оновлення або політики помилки оновлення | Провайдер не відповідає спільним механізмам оновлення `pi-ai` | +| 26 | `buildAuthDoctorHint` | Підказка виправлення, що додається, коли оновлення OAuth завершується помилкою | Провайдеру потрібні власні вказівки з відновлення автентифікації після помилки оновлення | +| 27 | `matchesContextOverflowError` | Засіб зіставлення переповнення контекстного вікна, що належить провайдеру | Провайдер має сирі помилки переповнення, які пропустять загальні евристики | +| 28 | `classifyFailoverReason` | Класифікація причин failover, що належить провайдеру | Провайдер може зіставляти сирі помилки API/транспорту з обмеженням швидкості/перевантаженням/тощо | +| 29 | `isCacheTtlEligible` | Політика prompt-cache для proxy/backhaul-провайдерів | Провайдеру потрібне специфічне для proxy керування TTL кешу | +| 30 | `buildMissingAuthMessage` | Замінник загального повідомлення відновлення при відсутній автентифікації | Провайдеру потрібна підказка відновлення при відсутній автентифікації, специфічна для провайдера | +| 31 | `suppressBuiltInModel` | Приховування застарілої upstream-моделі плюс необов’язкова підказка помилки для користувача | Провайдеру потрібно приховати застарілі upstream-рядки або замінити їх підказкою постачальника | +| 32 | `augmentModelCatalog` | Synthetic/фінальні рядки каталогу, що додаються після виявлення | Провайдеру потрібні synthetic рядки прямої сумісності в `models list` і засобах вибору | +| 33 | `resolveThinkingProfile` | Налаштування рівня `/think`, міток відображення та значення за замовчуванням для конкретної моделі | Провайдер надає користувацьку шкалу thinking або бінарну мітку для вибраних моделей | +| 34 | `isBinaryThinking` | Хук сумісності перемикача міркувань on/off | Провайдер надає лише бінарний режим thinking on/off | +| 35 | `supportsXHighThinking` | Хук сумісності підтримки міркувань `xhigh` | Провайдер хоче `xhigh` лише для підмножини моделей | +| 36 | `resolveDefaultThinkingLevel` | Хук сумісності рівня `/think` за замовчуванням | Провайдер володіє політикою `/think` за замовчуванням для сімейства моделей | +| 37 | `isModernModelRef` | Засіб зіставлення сучасних моделей для фільтрів live-профілів і вибору smoke | Провайдер володіє зіставленням бажаних моделей для live/smoke | +| 38 | `prepareRuntimeAuth` | Обмінює налаштовані облікові дані на фактичний токен/ключ середовища виконання безпосередньо перед інференсом | Провайдеру потрібен обмін токена або короткоживучі облікові дані запиту | +| 39 | `resolveUsageAuth` | Визначає облікові дані використання/білінгу для `/usage` і пов’язаних поверхонь статусу | Провайдеру потрібен користувацький розбір токена використання/квоти або інші облікові дані використання | +| 40 | `fetchUsageSnapshot` | Отримує та нормалізує знімки використання/квоти, специфічні для провайдера, після визначення автентифікації | Провайдеру потрібна кінцева точка використання або парсер корисного навантаження, специфічні для провайдера | +| 41 | `createEmbeddingProvider` | Створює адаптер ембедингів, що належить провайдеру, для пам’яті/пошуку | Поведінка ембедингів для пам’яті має належати плагіну провайдера | +| 42 | `buildReplayPolicy` | Повертає політику повторного відтворення, яка керує обробкою транскрипту для провайдера | Провайдеру потрібна користувацька політика транскрипту (наприклад, видалення блоків thinking) | +| 43 | `sanitizeReplayHistory` | Переписує історію повторного відтворення після загального очищення транскрипту | Провайдеру потрібні специфічні для провайдера переписування повторного відтворення понад спільні допоміжні засоби Compaction | +| 44 | `validateReplayTurns` | Фінальна валідація або зміна форми ходів повторного відтворення перед embedded runner | Транспорту провайдера потрібна суворіша валідація ходів після загального очищення | +| 45 | `onModelSelected` | Виконує побічні ефекти після вибору моделі, що належать провайдеру | Провайдеру потрібна телеметрія або стан, що належить провайдеру, коли модель стає активною | `normalizeModelId`, `normalizeTransport` і `normalizeConfig` спочатку перевіряють -зіставлений Plugin провайдера, а потім переходять до інших Plugin провайдерів, здатних працювати з хуками, -доки один із них фактично не змінить id моделі або transport/config. Це дає змогу -shim-рішенням для псевдонімів/compat провайдерів працювати без вимоги, щоб викликач знав, який -саме вбудований Plugin володіє цим переписуванням. Якщо жоден хук провайдера не перепише підтримуваний -запис config сімейства Google, вбудований нормалізатор Google config усе одно застосує +підібраний плагін провайдера, а потім переходять до інших плагінів провайдерів, здатних працювати з хуками, +доки один із них справді не змінить ідентифікатор моделі або транспорт/конфігурацію. Це зберігає +працездатність shim-шарів псевдонімів/сумісності провайдерів без необхідності для викликача знати, +який саме вбудований плагін володіє переписуванням. Якщо жоден хук провайдера не перепише підтримуваний +запис конфігурації сімейства Google, вбудований нормалізатор конфігурації Google все одно застосує це очищення сумісності. -Якщо провайдеру потрібен повністю власний wire protocol або власний виконавець запитів, +Якщо провайдеру потрібен повністю користувацький wire protocol або користувацький виконавець запитів, це вже інший клас розширення. Ці хуки призначені для поведінки провайдера, яка -все ще працює в межах звичайного циклу висновку OpenClaw. +все ще працює на звичайному циклі інференсу OpenClaw. ### Приклад провайдера @@ -817,115 +811,114 @@ api.registerProvider({ `resolveUsageAuth`, `fetchUsageSnapshot`, `isCacheTtlEligible`, `resolveThinkingProfile`, `applyConfigDefaults`, `isModernModelRef` і `wrapStreamFn`, тому що він володіє прямою сумісністю Claude 4.6, - підказками сімейства провайдерів, вказівками з відновлення auth, інтеграцією з endpoint використання, - допустимістю prompt-cache, значеннями config за замовчуванням з урахуванням auth, політикою - thinking за замовчуванням/адаптивного Claude та специфічним для Anthropic формуванням потоку для - beta headers, `/fast` / `serviceTier` і `context1m`. -- Допоміжні засоби потоку Anthropic, специфічні для Claude, поки що залишаються у власному - публічному шві `api.ts` / `contract-api.ts` вбудованого Plugin. Ця поверхня пакета + підказками для сімейства провайдера, вказівками щодо відновлення автентифікації, інтеграцією + кінцевої точки використання, допустимістю prompt-cache, значеннями конфігурації за замовчуванням, залежними від автентифікації, + політикою thinking Claude за замовчуванням/адаптивною політикою та формуванням потоку, специфічним для Anthropic, для + beta-заголовків, `/fast` / `serviceTier` і `context1m`. +- Допоміжні засоби потоку Anthropic, специфічні для Claude, поки що залишаються у власній + публічній поверхні `api.ts` / `contract-api.ts` вбудованого плагіна. Ця поверхня пакета експортує `wrapAnthropicProviderStream`, `resolveAnthropicBetas`, `resolveAnthropicFastMode`, `resolveAnthropicServiceTier` і нижчорівневі - засоби побудови обгорток Anthropic замість розширення узагальненого SDK навколо правил - beta headers одного провайдера. + конструктори обгорток Anthropic замість розширення загального SDK навколо + правил beta-заголовків одного провайдера. - OpenAI використовує `resolveDynamicModel`, `normalizeResolvedModel` і `capabilities`, а також `buildMissingAuthMessage`, `suppressBuiltInModel`, `augmentModelCatalog`, `resolveThinkingProfile` і `isModernModelRef`, тому що він володіє прямою сумісністю GPT-5.4, прямою нормалізацією OpenAI - `openai-completions` -> `openai-responses`, підказками auth з урахуванням Codex, - придушенням Spark, синтетичними рядками списку OpenAI та політикою thinking / - live-model для GPT-5; сімейство потоків `openai-responses-defaults` володіє - спільними нативними обгортками OpenAI Responses для attribution headers, - `/fast`/`serviceTier`, деталізації тексту, нативного вебпошуку Codex, - формування корисного навантаження reasoning-compat та керування контекстом Responses. + `openai-completions` -> `openai-responses`, підказками автентифікації з урахуванням Codex, + приховуванням Spark, synthetic-рядками списку OpenAI та політикою thinking / + live-моделей GPT-5; сімейство потоків `openai-responses-defaults` володіє + спільними нативними обгортками OpenAI Responses для заголовків атрибуції, + `/fast`/`serviceTier`, докладності тексту, нативного вебпошуку Codex, + формування корисного навантаження сумісності reasoning та керування контекстом Responses. - OpenRouter використовує `catalog`, а також `resolveDynamicModel` і - `prepareDynamicModel`, тому що провайдер є прохідним і може відкривати нові - id моделей до оновлення статичного каталогу OpenClaw; він також використовує - `capabilities`, `wrapStreamFn` і `isCacheTtlEligible`, щоб винести - специфічні для провайдера заголовки запитів, метадані маршрутизації, патчі reasoning та - політику prompt-cache за межі core. Його політика replay походить із + `prepareDynamicModel`, тому що провайдер є наскрізним і може відкривати нові + ідентифікатори моделей до оновлення статичного каталогу OpenClaw; він також використовує + `capabilities`, `wrapStreamFn` і `isCacheTtlEligible`, щоб зберігати + заголовки запитів, метадані маршрутизації, виправлення reasoning і + політику prompt-cache, специфічні для провайдера, поза core. Його політика повторного відтворення походить із сімейства `passthrough-gemini`, тоді як сімейство потоків `openrouter-thinking` - володіє проксі-впровадженням reasoning і пропусками unsupported-model / `auto`. + володіє проксі-впровадженням reasoning та пропусками для непідтримуваних моделей / `auto`. - GitHub Copilot використовує `catalog`, `auth`, `resolveDynamicModel` і - `capabilities`, а також `prepareRuntimeAuth` і `fetchUsageSnapshot`, тому що йому - потрібні власний вхід за допомогою пристрою, поведінка резервної моделі, - особливості транскриптів Claude, обмін токена GitHub на токен Copilot та - власний endpoint використання. + `capabilities`, а також `prepareRuntimeAuth` і `fetchUsageSnapshot`, + тому що йому потрібні вхід на пристрої, що належить провайдеру, поведінка резервного вибору моделей, особливості + транскрипту Claude, обмін токена GitHub -> токен Copilot і кінцева точка використання, + що належить провайдеру. - OpenAI Codex використовує `catalog`, `resolveDynamicModel`, `normalizeResolvedModel`, `refreshOAuth` і `augmentModelCatalog`, а також `prepareExtraParams`, `resolveUsageAuth` і `fetchUsageSnapshot`, тому що він - усе ще працює на transport OpenAI з core, але володіє нормалізацією свого - transport/base URL, резервною політикою оновлення OAuth, вибором транспорту за замовчуванням, - синтетичними рядками каталогу Codex та інтеграцією з endpoint використання ChatGPT; він - спільно використовує те саме сімейство потоків `openai-responses-defaults`, що й прямий OpenAI. + усе ще працює на транспорті core OpenAI, але володіє власною нормалізацією + транспорту/base URL, політикою резервного оновлення OAuth, вибором транспорту за замовчуванням, + synthetic-рядками каталогу Codex та інтеграцією кінцевої точки використання ChatGPT; він + використовує те саме сімейство потоків `openai-responses-defaults`, що й прямий OpenAI. - Google AI Studio і Gemini CLI OAuth використовують `resolveDynamicModel`, `buildReplayPolicy`, `sanitizeReplayHistory`, `resolveReasoningOutputMode`, `wrapStreamFn` і `isModernModelRef`, тому що - сімейство replay `google-gemini` володіє резервною прямою сумісністю Gemini 3.1, - нативною валідацією replay Gemini, санітизацією bootstrap replay, тегованим - режимом reasoning-output і зіставленням modern-model, тоді як + сімейство повторного відтворення `google-gemini` володіє резервною прямою сумісністю Gemini 3.1, + нативною валідацією повторного відтворення Gemini, очищенням bootstrap-повторного відтворення, режимом + виводу reasoning з тегами та зіставленням сучасних моделей, тоді як сімейство потоків `google-thinking` володіє нормалізацією корисного навантаження thinking Gemini; Gemini CLI OAuth також використовує `formatApiKey`, `resolveUsageAuth` і - `fetchUsageSnapshot` для форматування токенів, розбору токенів і підключення - endpoint квот. + `fetchUsageSnapshot` для форматування токена, розбору токена та підключення + кінцевої точки квоти. - Anthropic Vertex використовує `buildReplayPolicy` через - сімейство replay `anthropic-by-model`, тож очищення replay, специфічне для Claude, залишається - обмеженим id Claude, а не кожним transport `anthropic-messages`. + сімейство повторного відтворення `anthropic-by-model`, щоб очищення повторного відтворення, специфічне для Claude, + залишалося прив’язаним до ідентифікаторів Claude, а не до кожного транспорту `anthropic-messages`. - Amazon Bedrock використовує `buildReplayPolicy`, `matchesContextOverflowError`, `classifyFailoverReason` і `resolveThinkingProfile`, тому що він володіє - класифікацією помилок throttle/not-ready/context-overflow, специфічною для Bedrock, - для трафіку Anthropic-on-Bedrock; його політика replay все ще використовує той самий - guard лише для Claude `anthropic-by-model`. + специфічною для Bedrock класифікацією помилок throttle/not-ready/context-overflow + для трафіку Anthropic-on-Bedrock; його політика повторного відтворення все ще використовує ту саму + guard-логіку лише для Claude — `anthropic-by-model`. - OpenRouter, Kilocode, Opencode і Opencode Go використовують `buildReplayPolicy` - через сімейство replay `passthrough-gemini`, тому що вони проксіюють Gemini - моделі через сумісні з OpenAI transport і потребують санітизації - thought-signature Gemini без нативної валідації replay Gemini чи + через сімейство повторного відтворення `passthrough-gemini`, тому що вони проксіюють моделі Gemini + через OpenAI-сумісні транспорти та потребують очищення + thought-signature Gemini без нативної валідації повторного відтворення Gemini або bootstrap-переписувань. - MiniMax використовує `buildReplayPolicy` через - сімейство replay `hybrid-anthropic-openai`, тому що один провайдер володіє і - семантикою повідомлень Anthropic, і семантикою, сумісною з OpenAI; він зберігає - відкидання thinking-block лише для Claude на боці Anthropic, водночас перевизначаючи режим - reasoning output назад до нативного, а сімейство потоків `minimax-fast-mode` володіє - переписуванням fast-mode моделі на спільному шляху потоку. + сімейство повторного відтворення `hybrid-anthropic-openai`, тому що один провайдер володіє і + семантикою Anthropic-message, і OpenAI-сумісною семантикою; він зберігає видалення + thinking-блоків лише для Claude на боці Anthropic, водночас перевизначаючи режим виводу reasoning назад на нативний, + а сімейство потоків `minimax-fast-mode` володіє переписуванням моделей fast-mode на + спільному шляху потоку. - Moonshot використовує `catalog`, `resolveThinkingProfile` і `wrapStreamFn`, тому що він усе ще використовує спільний - transport OpenAI, але потребує нормалізації корисного навантаження thinking, що належить провайдеру; сімейство - потоків `moonshot-thinking` відображає config і стан `/think` на його - нативне двійкове корисне навантаження thinking. + транспорт OpenAI, але потребує нормалізації корисного навантаження thinking, що належить провайдеру; сімейство + потоків `moonshot-thinking` відображає конфігурацію плюс стан `/think` на свій + нативний бінарний корисний вантаж thinking. - Kilocode використовує `catalog`, `capabilities`, `wrapStreamFn` і `isCacheTtlEligible`, тому що йому потрібні заголовки запитів, що належать провайдеру, - нормалізація корисного навантаження reasoning, підказки транскриптів Gemini та керування - TTL кешу Anthropic; сімейство потоків `kilocode-thinking` зберігає впровадження Kilo thinking + нормалізація корисного навантаження reasoning, підказки транскрипту Gemini та + керування TTL кешу Anthropic; сімейство потоків `kilocode-thinking` зберігає впровадження Kilo thinking на спільному шляху проксі-потоку, водночас пропускаючи `kilo/auto` та - інші id проксі-моделей, які не підтримують явні корисні навантаження reasoning. + інші ідентифікатори проксі-моделей, які не підтримують явні корисні навантаження reasoning. - Z.AI використовує `resolveDynamicModel`, `prepareExtraParams`, `wrapStreamFn`, `isCacheTtlEligible`, `resolveThinkingProfile`, `isModernModelRef`, - `resolveUsageAuth` і `fetchUsageSnapshot`, тому що він володіє резервною сумісністю GLM-5, - значеннями `tool_stream` за замовчуванням, двійковим UX thinking, зіставленням modern-model - і як auth використання, так і отриманням квот; сімейство потоків `tool-stream-default-on` - тримає обгортку `tool_stream`, увімкнену за замовчуванням, поза - рукописним glue-кодом для кожного провайдера. + `resolveUsageAuth` і `fetchUsageSnapshot`, тому що він володіє резервною логікою GLM-5, + значеннями `tool_stream` за замовчуванням, UX бінарного thinking, зіставленням сучасних моделей і + як автентифікацією використання, так і отриманням квоти; сімейство потоків `tool-stream-default-on` + тримає обгортку `tool_stream`, увімкнену за замовчуванням, поза рукописним glue-кодом окремих провайдерів. - xAI використовує `normalizeResolvedModel`, `normalizeTransport`, `contributeResolvedModelCompat`, `prepareExtraParams`, `wrapStreamFn`, `resolveSyntheticAuth`, `resolveDynamicModel` і `isModernModelRef`, - тому що він володіє нативною нормалізацією transport Responses для xAI, переписуванням - псевдонімів fast-mode Grok, `tool_stream` за замовчуванням, очищенням strict-tool / reasoning-payload, - повторним використанням резервного auth для інструментів, що належать Plugin, прямим визначенням - моделей Grok для прямої сумісності та compat-патчами, що належать провайдеру, як-от профіль схем - інструментів xAI, непідтримувані ключові слова схем, нативний `web_search` і декодування - аргументів виклику інструментів з HTML-entity. + тому що він володіє нативною нормалізацією транспорту xAI Responses, переписуванням + псевдонімів fast-mode Grok, типовим `tool_stream`, очищенням strict-tool / reasoning-payload, + повторним використанням резервної автентифікації для інструментів, що належать плагіну, прямим визначенням моделей Grok + та виправленнями сумісності, що належать провайдеру, такими як профіль схеми інструментів xAI, + непідтримувані ключові слова схеми, нативний `web_search` і декодування аргументів + виклику інструментів з HTML-сутностями. - Mistral, OpenCode Zen і OpenCode Go використовують лише `capabilities`, щоб - винести особливості транскриптів/інструментів за межі core. -- Вбудовані провайдери лише з каталогом, як-от `byteplus`, `cloudflare-ai-gateway`, + тримати особливості транскрипту/інструментів поза core. +- Вбудовані провайдери лише з каталогом, такі як `byteplus`, `cloudflare-ai-gateway`, `huggingface`, `kimi-coding`, `nvidia`, `qianfan`, `synthetic`, `together`, `venice`, `vercel-ai-gateway` і `volcengine`, використовують лише `catalog`. - Qwen використовує `catalog` для свого текстового провайдера, а також спільні реєстрації розуміння медіа і генерації відео для своїх мультимодальних поверхонь. -- MiniMax і Xiaomi використовують `catalog`, а також хуки використання, тому що їхня поведінка `/usage` - належить Plugin, хоча сам висновок усе ще проходить через спільні transport. +- MiniMax і Xiaomi використовують `catalog` плюс хуки використання, тому що їхня поведінка `/usage` + належить плагіну, хоча сам інференс усе ще проходить через спільні транспорти. ## Допоміжні засоби середовища виконання -Plugin можуть отримувати доступ до вибраних допоміжних засобів core через `api.runtime`. Для TTS: +Плагіни можуть отримувати доступ до вибраних допоміжних засобів core через `api.runtime`. Для TTS: ```ts const clip = await api.runtime.tts.textToSpeech({ @@ -946,14 +939,14 @@ const voices = await api.runtime.tts.listVoices({ Примітки: -- `textToSpeech` повертає звичайне корисне навантаження виводу TTS із core для поверхонь файлів/голосових нотаток. -- Використовує config `messages.tts` і вибір провайдера з core. -- Повертає PCM audio buffer + частоту дискретизації. Plugin мають виконувати ресемплінг/кодування для провайдерів. -- `listVoices` є необов’язковим для кожного провайдера. Використовуйте його для селекторів голосів або потоків налаштування, що належать вендору. -- Списки голосів можуть містити багатші метадані, як-от locale, gender і теги personality для селекторів із урахуванням провайдера. -- OpenAI та ElevenLabs сьогодні підтримують телефонію. Microsoft не підтримує. +- `textToSpeech` повертає звичайне корисне навантаження виходу TTS core для поверхонь файлів/голосових нотаток. +- Використовує конфігурацію core `messages.tts` і вибір провайдера. +- Повертає PCM-аудіобуфер + частоту дискретизації. Плагіни мають виконувати ресемплінг/кодування для провайдерів. +- `listVoices` є необов’язковим для кожного провайдера. Використовуйте його для засобів вибору голосу або потоків налаштування, що належать постачальнику. +- Списки голосів можуть містити багатші метадані, такі як locale, gender і теги personality для засобів вибору, обізнаних про провайдера. +- OpenAI і ElevenLabs сьогодні підтримують телефонію. Microsoft — ні. -Plugin також можуть реєструвати провайдерів мовлення через `api.registerSpeechProvider(...)`. +Плагіни також можуть реєструвати провайдерів мовлення через `api.registerSpeechProvider(...)`. ```ts api.registerSpeechProvider({ @@ -973,15 +966,15 @@ api.registerSpeechProvider({ Примітки: -- Зберігайте політику TTS, резервну поведінку та доставку відповідей у core. -- Використовуйте провайдерів мовлення для поведінки синтезу, що належить вендору. -- Застаріле значення Microsoft `edge` нормалізується до id провайдера `microsoft`. -- Бажана модель володіння є орієнтованою на компанію: один vendor Plugin може володіти - текстовими, мовленнєвими, графічними та майбутніми медіапровайдерами, коли OpenClaw додає відповідні +- Зберігайте політику TTS, резервну логіку та доставку відповіді в core. +- Використовуйте провайдерів мовлення для поведінки синтезу, що належить постачальнику. +- Застарілий вхід Microsoft `edge` нормалізується до ідентифікатора провайдера `microsoft`. +- Бажана модель володіння орієнтована на компанію: один плагін постачальника може володіти + текстовими, мовленнєвими, зображувальними та майбутніми медіапровайдерами, коли OpenClaw додає такі контракти можливостей. -Для розуміння зображень/аудіо/відео Plugin реєструють одного типізованого -провайдера розуміння медіа замість узагальненого сховища ключ/значення: +Для розуміння зображень/аудіо/відео плагіни реєструють одного типізованого +провайдера розуміння медіа замість узагальненого набору ключ/значення: ```ts api.registerMediaUnderstandingProvider({ @@ -995,16 +988,16 @@ api.registerMediaUnderstandingProvider({ Примітки: -- Зберігайте оркестрацію, резервну поведінку, config і підключення каналів у core. -- Зберігайте vendor behavior у Plugin провайдера. +- Зберігайте оркестрацію, резервну логіку, конфігурацію та підключення каналів у core. +- Зберігайте поведінку постачальника в плагіні провайдера. - Адитивне розширення має залишатися типізованим: нові необов’язкові методи, нові необов’язкові - поля результату, нові необов’язкові можливості. + поля результатів, нові необов’язкові можливості. - Генерація відео вже дотримується того самого шаблону: - core володіє контрактом можливості та допоміжним засобом середовища виконання - - vendor Plugin реєструють `api.registerVideoGenerationProvider(...)` + - плагіни постачальників реєструють `api.registerVideoGenerationProvider(...)` - плагіни функцій/каналів використовують `api.runtime.videoGeneration.*` -Для допоміжних засобів середовища виконання media-understanding Plugin можуть викликати: +Для допоміжних засобів середовища виконання media-understanding плагіни можуть викликати: ```ts const image = await api.runtime.mediaUnderstanding.describeImageFile({ @@ -1019,14 +1012,14 @@ const video = await api.runtime.mediaUnderstanding.describeVideoFile({ }); ``` -Для транскрипції аудіо Plugin можуть використовувати або середовище виконання media-understanding, +Для транскрипції аудіо плагіни можуть використовувати або середовище виконання media-understanding, або старіший псевдонім STT: ```ts const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ filePath: "/tmp/inbound-audio.ogg", cfg: api.config, - // Необов’язково, коли MIME не можна надійно визначити: + // Optional when MIME cannot be inferred reliably: mime: "audio/ogg", }); ``` @@ -1035,11 +1028,11 @@ const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ - `api.runtime.mediaUnderstanding.*` — це бажана спільна поверхня для розуміння зображень/аудіо/відео. -- Використовує config аудіо media-understanding із core (`tools.media.audio`) і порядок резервного вибору провайдерів. -- Повертає `{ text: undefined }`, коли вихід транскрипції не створено (наприклад, вхідні дані пропущено або вони не підтримуються). -- `api.runtime.stt.transcribeAudioFile(...)` залишається псевдонімом для сумісності. +- Використовує конфігурацію аудіо core media-understanding (`tools.media.audio`) і порядок резервного вибору провайдерів. +- Повертає `{ text: undefined }`, коли вихід транскрипції не створюється (наприклад, для пропущеного/непідтримуваного вводу). +- `api.runtime.stt.transcribeAudioFile(...)` залишається як псевдонім сумісності. -Plugin також можуть запускати фонові виконання субагентів через `api.runtime.subagent`: +Плагіни також можуть запускати фонові виконання підлеглих агентів через `api.runtime.subagent`: ```ts const result = await api.runtime.subagent.run({ @@ -1053,13 +1046,13 @@ const result = await api.runtime.subagent.run({ Примітки: -- `provider` і `model` — це необов’язкові перевизначення для окремого запуску, а не постійні зміни сеансу. +- `provider` і `model` — це необов’язкові перевизначення для окремого запуску, а не постійні зміни сесії. - OpenClaw враховує ці поля перевизначення лише для довірених викликачів. -- Для резервних запусків, що належать Plugin, оператори мають явно дозволити це через `plugins.entries..subagent.allowModelOverride: true`. -- Використовуйте `plugins.entries..subagent.allowedModels`, щоб обмежити довірені Plugin конкретними канонічними цілями `provider/model`, або `"*"`, щоб явно дозволити будь-яку ціль. -- Запуски субагентів із недовірених Plugin теж працюють, але запити на перевизначення відхиляються замість тихого переходу до резервного варіанта. +- Для запусків резервного вибору, що належать плагіну, оператори мають явно дозволити це через `plugins.entries..subagent.allowModelOverride: true`. +- Використовуйте `plugins.entries..subagent.allowedModels`, щоб обмежити довірені плагіни конкретними канонічними цілями `provider/model`, або `"*"` для явного дозволу будь-якої цілі. +- Запуски subagent з недовірених плагінів усе ще працюють, але запити на перевизначення відхиляються замість тихого переходу до резервного варіанта. -Для вебпошуку Plugin можуть використовувати спільний допоміжний засіб середовища виконання замість +Для вебпошуку плагіни можуть використовувати спільний допоміжний засіб середовища виконання замість звернення до підключення інструментів агента: ```ts @@ -1076,13 +1069,13 @@ const result = await api.runtime.webSearch.search({ }); ``` -Plugin також можуть реєструвати провайдерів вебпошуку через +Плагіни також можуть реєструвати провайдерів вебпошуку через `api.registerWebSearchProvider(...)`. Примітки: - Зберігайте вибір провайдера, визначення облікових даних і спільну семантику запитів у core. -- Використовуйте провайдерів вебпошуку для пошукових transport, специфічних для вендора. +- Використовуйте провайдерів вебпошуку для транспортів пошуку, специфічних для постачальника. - `api.runtime.webSearch.*` — це бажана спільна поверхня для плагінів функцій/каналів, яким потрібна поведінка пошуку без залежності від обгортки інструмента агента. ### `api.runtime.imageGeneration` @@ -1098,12 +1091,12 @@ const providers = api.runtime.imageGeneration.listProviders({ }); ``` -- `generate(...)`: генерує зображення, використовуючи налаштований ланцюжок провайдерів генерації зображень. +- `generate(...)`: створює зображення за допомогою налаштованого ланцюжка провайдерів генерації зображень. - `listProviders(...)`: виводить список доступних провайдерів генерації зображень і їхніх можливостей. ## HTTP-маршрути Gateway -Plugin можуть відкривати HTTP endpoint через `api.registerHttpRoute(...)`. +Плагіни можуть відкривати HTTP-кінцеві точки за допомогою `api.registerHttpRoute(...)`. ```ts api.registerHttpRoute({ @@ -1120,35 +1113,34 @@ api.registerHttpRoute({ Поля маршруту: -- `path`: шлях маршруту в HTTP-сервері gateway. -- `auth`: обов’язково. Використовуйте `"gateway"`, щоб вимагати звичайний auth gateway, або `"plugin"` для auth, яким керує Plugin, чи перевірки Webhook. -- `match`: необов’язково. `"exact"` (за замовчуванням) або `"prefix"`. -- `replaceExisting`: необов’язково. Дозволяє тому самому Plugin замінити власну наявну реєстрацію маршруту. +- `path`: шлях маршруту в межах HTTP-сервера gateway. +- `auth`: обов’язкове поле. Використовуйте `"gateway"`, щоб вимагати звичайну автентифікацію gateway, або `"plugin"` для автентифікації, якою керує плагін / перевірки Webhook. +- `match`: необов’язкове поле. `"exact"` (типово) або `"prefix"`. +- `replaceExisting`: необов’язкове поле. Дозволяє тому самому плагіну замінювати власну наявну реєстрацію маршруту. - `handler`: повертайте `true`, коли маршрут обробив запит. Примітки: -- `api.registerHttpHandler(...)` було видалено, і він спричинить помилку завантаження Plugin. Натомість використовуйте `api.registerHttpRoute(...)`. -- Маршрути Plugin мають явно оголошувати `auth`. -- Конфлікти точних `path + match` відхиляються, якщо тільки не встановлено `replaceExisting: true`, і один Plugin не може замінити маршрут іншого Plugin. -- Перекривні маршрути з різними рівнями `auth` відхиляються. Зберігайте ланцюжки передачі `exact`/`prefix` лише в межах одного рівня auth. -- Маршрути `auth: "plugin"` **не** отримують автоматично область середовища виконання оператора. Вони призначені для Webhook або перевірки підпису, якими керує Plugin, а не для привілейованих допоміжних викликів Gateway. -- Маршрути `auth: "gateway"` працюють усередині області середовища виконання запиту Gateway, але ця область навмисно є консервативною: - - bearer auth зі спільним секретом (`gateway.auth.mode = "token"` / `"password"`) утримує області середовища виконання маршрутів Plugin на рівні `operator.write`, навіть якщо викликач надсилає `x-openclaw-scopes` - - довірені HTTP-режими з ідентичністю (наприклад, `trusted-proxy` або `gateway.auth.mode = "none"` у приватному ingress) враховують `x-openclaw-scopes` лише тоді, коли заголовок явно присутній - - якщо `x-openclaw-scopes` відсутній у таких запитах до маршрутів Plugin з ідентичністю, область середовища виконання повертається до `operator.write` -- Практичне правило: не припускайте, що маршрут Plugin з auth gateway є неявною поверхнею адміністратора. Якщо ваш маршрут потребує поведінки лише для адміністратора, вимагайте режим auth з ідентичністю та документуйте явний контракт заголовка `x-openclaw-scopes`. +- `api.registerHttpHandler(...)` вилучено, і це спричинить помилку завантаження плагіна. Натомість використовуйте `api.registerHttpRoute(...)`. +- Маршрути плагінів мають явно оголошувати `auth`. +- Конфлікти точного `path + match` відхиляються, якщо не вказано `replaceExisting: true`, і один плагін не може замінити маршрут іншого плагіна. +- Перекривні маршрути з різними рівнями `auth` відхиляються. Залишайте ланцюжки переходу `exact`/`prefix` лише в межах одного рівня `auth`. +- Маршрути `auth: "plugin"` **не** отримують автоматично області середовища виконання оператора. Вони призначені для Webhook-ів/перевірки підписів, якими керує плагін, а не для привілейованих допоміжних викликів Gateway. +- Маршрути `auth: "gateway"` виконуються в межах області середовища виконання запиту Gateway, але ця область навмисно консервативна: + - bearer-автентифікація зі спільним секретом (`gateway.auth.mode = "token"` / `"password"`) утримує області середовища виконання маршруту плагіна прив’язаними до `operator.write`, навіть якщо викликач надсилає `x-openclaw-scopes` + - довірені HTTP-режими з ідентичністю (наприклад, `trusted-proxy` або `gateway.auth.mode = "none"` на приватному ingress) враховують `x-openclaw-scopes` лише тоді, коли заголовок явно присутній + - якщо `x-openclaw-scopes` відсутній у таких запитах маршруту плагіна з ідентичністю, область середовища виконання повертається до `operator.write` +- Практичне правило: не припускайте, що маршрут плагіна з gateway-auth є неявною поверхнею адміністратора. Якщо вашому маршруту потрібна поведінка лише для адміністратора, вимагайте режим автентифікації з ідентичністю та документуйте явний контракт заголовка `x-openclaw-scopes`. ## Шляхи імпорту Plugin SDK -Використовуйте підшляхи SDK замість монолітного імпорту `openclaw/plugin-sdk` під час -створення Plugin: +Під час створення плагінів використовуйте підшляхи SDK замість монолітного імпорту `openclaw/plugin-sdk`: -- `openclaw/plugin-sdk/plugin-entry` для примітивів реєстрації Plugin. -- `openclaw/plugin-sdk/core` для узагальненого спільного контракту, орієнтованого на Plugin. +- `openclaw/plugin-sdk/plugin-entry` для примітивів реєстрації плагінів. +- `openclaw/plugin-sdk/core` для загального спільного контракту, орієнтованого на плагіни. - `openclaw/plugin-sdk/config-schema` для експорту кореневої Zod-схеми `openclaw.json` (`OpenClawSchema`). -- Стабільні примітиви каналів, як-от `openclaw/plugin-sdk/channel-setup`, +- Стабільні примітиви каналів, такі як `openclaw/plugin-sdk/channel-setup`, `openclaw/plugin-sdk/setup-runtime`, `openclaw/plugin-sdk/setup-adapter-runtime`, `openclaw/plugin-sdk/setup-tools`, @@ -1161,17 +1153,17 @@ api.registerHttpRoute({ `openclaw/plugin-sdk/command-auth`, `openclaw/plugin-sdk/secret-input` і `openclaw/plugin-sdk/webhook-ingress` для спільного підключення - налаштування/auth/відповідей/Webhook. `channel-inbound` — це спільний дім для debounce, зіставлення згадок, - допоміжних засобів політики вхідних згадок, форматування envelope та - допоміжних засобів контексту вхідних envelope. - `channel-setup` — це вузький шов налаштування необов’язкового встановлення. + налаштування/автентифікації/відповідей/Webhook. `channel-inbound` — це спільне місце для debounce, зіставлення згадок, + допоміжних засобів політики вхідних згадок, форматування envelope та допоміжних засобів контексту + вхідного envelope. + `channel-setup` — це вузька поверхня налаштування для необов’язкового встановлення. `setup-runtime` — це безпечна для середовища виконання поверхня налаштування, яка використовується `setupEntry` / - відкладеним запуском, включно з безпечними для імпорту адаптерами патчів налаштування. - `setup-adapter-runtime` — це env-aware шов адаптера налаштування облікового запису. - `setup-tools` — це невеликий шов допоміжних засобів CLI/архівів/документації (`formatCliCommand`, + відкладеним запуском, включно з безпечними для імпорту адаптерами patch для налаштування. + `setup-adapter-runtime` — це поверхня адаптера налаштування облікових записів, обізнана про env. + `setup-tools` — це мала поверхня допоміжних засобів для CLI/архівів/документації (`formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR`). -- Підшляхи доменів, як-от `openclaw/plugin-sdk/channel-config-helpers`, +- Доменні підшляхи, такі як `openclaw/plugin-sdk/channel-config-helpers`, `openclaw/plugin-sdk/allow-from`, `openclaw/plugin-sdk/channel-config-schema`, `openclaw/plugin-sdk/telegram-command-config`, @@ -1189,193 +1181,201 @@ api.registerHttpRoute({ `openclaw/plugin-sdk/status-helpers`, `openclaw/plugin-sdk/text-runtime`, `openclaw/plugin-sdk/runtime-store` і - `openclaw/plugin-sdk/directory-runtime` для спільних допоміжних засобів середовища виконання/config. - `telegram-command-config` — це вузький публічний шов для нормалізації/валідації користувацьких - команд Telegram і залишається доступним, навіть якщо поверхня контракту вбудованого + `openclaw/plugin-sdk/directory-runtime` для спільних допоміжних засобів середовища виконання/конфігурації. + `telegram-command-config` — це вузька публічна поверхня для нормалізації/валідації користувацьких + команд Telegram і залишається доступною, навіть якщо поверхня контракту вбудованого Telegram тимчасово недоступна. - `text-runtime` — це спільний шов text/markdown/logging, включно з - видаленням видимого асистенту тексту, допоміжними засобами рендерингу/розбиття markdown, допоміжними засобами редагування, - допоміжними засобами тегів директив і утилітами безпечного тексту. -- Для специфічних для схвалення швів каналів слід надавати перевагу одному контракту - `approvalCapability` у Plugin. Потім core читає auth схвалення, доставку, рендеринг, - нативну маршрутизацію та поведінку lazy native-handler через цю єдину можливість, - замість змішування поведінки схвалення з не пов’язаними полями Plugin. + `text-runtime` — це спільна поверхня тексту/markdown/логування, включно з + видаленням тексту, видимого асистенту, допоміжними засобами рендерингу/розбиття markdown, засобами + редагування, допоміжними засобами тегів директив і утилітами безпечного тексту. +- Поверхні каналів, специфічні для схвалень, мають надавати перевагу одному контракту `approvalCapability` + у плагіні. Тоді core читає автентифікацію схвалень, доставку, рендеринг, + нативну маршрутизацію та ліниву поведінку нативного обробника через цю одну можливість + замість змішування поведінки схвалення з не пов’язаними полями плагіна. - `openclaw/plugin-sdk/channel-runtime` є застарілим і залишається лише як - shim сумісності для старіших Plugin. Новий код має імпортувати вужчі - узагальнені примітиви, а код у репозиторії не повинен додавати нові імпорти цього + shim сумісності для старіших плагінів. Новий код має імпортувати вужчі + загальні примітиви, а код репозиторію не повинен додавати нові імпорти цього shim. -- Внутрішні частини вбудованих розширень залишаються приватними. Зовнішні Plugin мають використовувати лише підшляхи `openclaw/plugin-sdk/*`. Core/тестовий код OpenClaw може використовувати - публічні точки входу репозиторію під коренем пакета Plugin, як-от `index.js`, `api.js`, - `runtime-api.js`, `setup-entry.js`, а також вузько спрямовані файли, як-от - `login-qr-api.js`. Ніколи не імпортуйте `src/*` пакета Plugin з core або з +- Внутрішні компоненти вбудованих розширень залишаються приватними. Зовнішні плагіни повинні використовувати лише + підшляхи `openclaw/plugin-sdk/*`. Код core/test OpenClaw може використовувати + публічні точки входу репозиторію в корені пакета плагіна, такі як `index.js`, `api.js`, + `runtime-api.js`, `setup-entry.js`, і вузько спрямовані файли, такі як + `login-qr-api.js`. Ніколи не імпортуйте `src/*` пакета плагіна з core або з іншого розширення. -- Розділення точок входу репозиторію: - `/api.js` — це панель допоміжних засобів/типів, - `/runtime-api.js` — це панель лише для середовища виконання, - `/index.js` — це точка входу вбудованого Plugin, - а `/setup-entry.js` — це точка входу Plugin налаштування. +- Поділ точки входу репозиторію: + `/api.js` — це barrel допоміжних засобів/типів, + `/runtime-api.js` — це barrel лише для середовища виконання, + `/index.js` — це точка входу вбудованого плагіна, + а `/setup-entry.js` — це точка входу плагіна налаштування. - Поточні приклади вбудованих провайдерів: - Anthropic використовує `api.js` / `contract-api.js` для допоміжних засобів потоку Claude, таких - як `wrapAnthropicProviderStream`, допоміжні засоби beta-header і розбір `service_tier`. - - OpenAI використовує `api.js` для побудовників провайдерів, допоміжних засобів моделей за замовчуванням і - побудовників провайдерів реального часу. - - OpenRouter використовує `api.js` для свого побудовника провайдера та допоміжних засобів - onboarding/config, тоді як `register.runtime.js` усе ще може повторно експортувати узагальнені + як `wrapAnthropicProviderStream`, допоміжні засоби beta-заголовків і розбір + `service_tier`. + - OpenAI використовує `api.js` для конструкторів провайдера, допоміжних засобів моделі за замовчуванням і + конструкторів провайдерів реального часу. + - OpenRouter використовує `api.js` для свого конструктора провайдера, а також допоміжних засобів + onboarding/конфігурації, тоді як `register.runtime.js` усе ще може повторно експортувати загальні допоміжні засоби `plugin-sdk/provider-stream` для локального використання в репозиторії. -- Публічні точки входу, завантажені через фасад, надають перевагу активному знімку config середовища виконання, - коли він існує, а потім повертаються до визначеного config-файлу на диску, коли - OpenClaw ще не надає знімок середовища виконання. -- Узагальнені спільні примітиви залишаються бажаним публічним контрактом SDK. Невеликий - зарезервований набір допоміжних швів, позначених вбудованими каналами, усе ще існує. Розглядайте їх як шви для підтримки/сумісності вбудованих компонентів, а не як нові цілі імпорту для сторонніх рішень; нові міжканальні контракти, як і раніше, мають потрапляти до - узагальнених підшляхів `plugin-sdk/*` або локальних панелей Plugin `api.js` / +- Публічні точки входу, завантажені через facade, віддають перевагу активному знімку конфігурації середовища виконання, + коли він існує, а потім повертаються до визначеного файла конфігурації на диску, коли + OpenClaw ще не обслуговує знімок середовища виконання. +- Загальні спільні примітиви залишаються бажаним публічним контрактом SDK. Невеликий + зарезервований набір поверхонь допоміжних засобів, брендованих під вбудовані канали, усе ще + існує. Розглядайте їх як поверхні для підтримки вбудованих компонентів/сумісності, а не як нові цілі імпорту для сторонніх компонентів; нові міжканальні контракти все одно мають потрапляти до + загальних підшляхів `plugin-sdk/*` або локальних barrel-файлів плагіна `api.js` / `runtime-api.js`. Примітка щодо сумісності: -- Уникайте кореневої панелі `openclaw/plugin-sdk` у новому коді. +- Уникайте кореневого barrel `openclaw/plugin-sdk` у новому коді. - Спочатку надавайте перевагу вузьким стабільним примітивам. Новіші підшляхи setup/pairing/reply/ feedback/contract/inbound/threading/command/secret-input/webhook/infra/ - allowlist/status/message-tool — це бажаний контракт для нової роботи з - вбудованими та зовнішніми Plugin. - Розбір/зіставлення цілей має належати до `openclaw/plugin-sdk/channel-targets`. - Перевірки дій із повідомленнями та допоміжні засоби message-id для реакцій мають належати до + allowlist/status/message-tool є бажаним контрактом для нової роботи з + вбудованими та зовнішніми плагінами. + Аналіз/зіставлення цілей має належати до `openclaw/plugin-sdk/channel-targets`. + Шлюзи дій повідомлень і допоміжні засоби message-id для реакцій мають належати до `openclaw/plugin-sdk/channel-actions`. -- Панелі допоміжних засобів, специфічні для вбудованих розширень, не є стабільними за замовчуванням. Якщо - допоміжний засіб потрібен лише вбудованому розширенню, зберігайте його за - локальним швом `api.js` або `runtime-api.js` цього розширення замість просування в +- Barrel-файли допоміжних засобів, специфічних для вбудованих розширень, за замовчуванням не є стабільними. Якщо + допоміжний засіб потрібен лише вбудованому розширенню, тримайте його за + локальною поверхнею `api.js` або `runtime-api.js` розширення замість просування до `openclaw/plugin-sdk/`. -- Нові спільні шви допоміжних засобів мають бути узагальненими, а не прив’язаними до каналу. Спільний розбір - цілей має належати до `openclaw/plugin-sdk/channel-targets`; внутрішні частини, специфічні для каналу, - мають залишатися за локальним швом `api.js` або `runtime-api.js` Plugin-власника. -- Підшляхи, специфічні для можливостей, як-от `image-generation`, - `media-understanding` і `speech`, існують, тому що вбудовані/нативні Plugin - використовують їх уже сьогодні. Їхня наявність сама по собі не означає, що кожен експортований допоміжний засіб є - замороженим зовнішнім контрактом у довгостроковій перспективі. +- Нові спільні поверхні допоміжних засобів мають бути загальними, а не брендованими під конкретний канал. Спільний аналіз + цілей має належати до `openclaw/plugin-sdk/channel-targets`; внутрішні компоненти, специфічні для каналу, + мають залишатися за локальною поверхнею `api.js` або `runtime-api.js` + плагіна-власника. +- Підшляхи, специфічні для можливостей, такі як `image-generation`, + `media-understanding` і `speech`, існують тому, що вбудовані/нативні плагіни використовують + їх уже сьогодні. Їхня наявність сама по собі не означає, що кожен експортований допоміжний засіб є + довгостроковим замороженим зовнішнім контрактом. ## Схеми інструмента повідомлень -Plugin мають володіти внесками до схеми `describeMessageTool(...)`, специфічними для каналу. -Зберігайте поля, специфічні для провайдера, у Plugin, а не в спільному core. +Плагіни мають володіти внесками до схем `describeMessageTool(...)`, специфічними для каналу, +для примітивів, відмінних від повідомлень, таких як реакції, позначення прочитаного та опитування. +Спільне представлення надсилання має використовувати загальний контракт `MessagePresentation` +замість нативних для провайдера полів button, component, block або card. +Див. [Представлення повідомлень](/uk/plugins/message-presentation), щоб ознайомитися з контрактом, +правилами резервного вибору, зіставленням провайдерів і контрольним списком для авторів плагінів. -Для спільних переносних фрагментів схеми повторно використовуйте узагальнені допоміжні засоби, експортовані через -`openclaw/plugin-sdk/channel-actions`: +Плагіни, здатні надсилати, оголошують те, що вони можуть відображати, через можливості повідомлень: -- `createMessageToolButtonsSchema()` для корисного навантаження у стилі сітки кнопок -- `createMessageToolCardSchema()` для структурованого корисного навантаження карток +- `presentation` для семантичних блоків представлення (`text`, `context`, `divider`, `buttons`, `select`) +- `delivery-pin` для запитів закріпленої доставки -Якщо форма схеми має сенс лише для одного провайдера, визначайте її у власному -коді цього Plugin замість просування в спільний SDK. +Core вирішує, чи відображати представлення нативно, чи деградувати його до тексту. +Не відкривайте нативні для провайдера аварійні шляхи UI з загального інструмента повідомлень. +Застарілі допоміжні засоби SDK для застарілих нативних схем залишаються експортованими для наявних +сторонніх плагінів, але нові плагіни не повинні їх використовувати. ## Визначення цілей каналу -Плагіни каналів мають володіти семантикою цілей, специфічною для каналу. Зберігайте -спільний outbound host узагальненим і використовуйте поверхню адаптера повідомлень для правил провайдера: +Плагіни каналів мають володіти семантикою цілей, специфічною для каналу. Зберігайте спільний +вихідний хост загальним і використовуйте поверхню адаптера обміну повідомленнями для правил провайдера: -- `messaging.inferTargetChatType({ to })` визначає, чи нормалізовану ціль - слід трактувати як `direct`, `group` чи `channel` до пошуку в директорії. +- `messaging.inferTargetChatType({ to })` вирішує, чи слід розглядати нормалізовану ціль + як `direct`, `group` або `channel` до пошуку в директорії. - `messaging.targetResolver.looksLikeId(raw, normalized)` повідомляє core, чи - слід для вхідних даних одразу переходити до визначення за схожістю з id замість пошуку в директорії. -- `messaging.targetResolver.resolveTarget(...)` — це резервний шлях Plugin, коли + слід одразу перейти до визначення типу id замість пошуку в директорії. +- `messaging.targetResolver.resolveTarget(...)` — це резервний механізм плагіна, коли core потребує фінального визначення, що належить провайдеру, після нормалізації або після промаху пошуку в директорії. -- `messaging.resolveOutboundSessionRoute(...)` володіє побудовою маршруту вихідного сеансу, - специфічною для провайдера, після визначення цілі. +- `messaging.resolveOutboundSessionRoute(...)` володіє побудовою маршруту вихідної сесії, + специфічною для провайдера, після того як ціль визначено. Рекомендований поділ: -- Використовуйте `inferTargetChatType` для рішень про категорію, які мають ухвалюватися до - пошуку серед контактів/груп. -- Використовуйте `looksLikeId` для перевірок на кшталт «трактувати це як явний/нативний id цілі». +- Використовуйте `inferTargetChatType` для рішень щодо категорій, які мають ухвалюватися до + пошуку серед peer/group. +- Використовуйте `looksLikeId` для перевірок на кшталт «розглядати це як явний/нативний ідентифікатор цілі». - Використовуйте `resolveTarget` для резервної нормалізації, специфічної для провайдера, а не для широкого пошуку в директорії. -- Зберігайте нативні id провайдера, як-от chat id, thread id, JID, handle та room - id, у значеннях `target` або параметрах, специфічних для провайдера, а не в узагальнених полях SDK. +- Зберігайте нативні для провайдера ідентифікатори, такі як chat id, thread id, JID, handle і room + id, усередині значень `target` або параметрів, специфічних для провайдера, а не в загальних полях SDK. -## Директорії на основі config +## Директорії на основі конфігурації -Plugin, які формують записи директорій із config, мають зберігати цю логіку в -Plugin і повторно використовувати спільні допоміжні засоби з +Плагіни, які виводять записи директорії з конфігурації, мають зберігати цю логіку в +плагіні та повторно використовувати спільні допоміжні засоби з `openclaw/plugin-sdk/directory-runtime`. -Використовуйте це, коли каналу потрібні контакти/групи на основі config, наприклад: +Використовуйте це, коли каналу потрібні peer/group на основі конфігурації, наприклад: -- контакти DM на основі allowlist -- налаштовані мапи каналів/груп -- статичні резервні варіанти директорій в межах облікового запису +- DM peer на основі allowlist +- налаштовані карти channel/group +- статичні резервні варіанти директорії в межах облікового запису -Спільні допоміжні засоби в `directory-runtime` обробляють лише узагальнені операції: +Спільні допоміжні засоби в `directory-runtime` обробляють лише загальні операції: - фільтрацію запитів -- застосування лімітів -- дедуплікацію/допоміжні засоби нормалізації +- застосування обмежень +- дедуплікацію/нормалізацію - побудову `ChannelDirectoryEntry[]` -Специфічні для каналу перевірка облікових записів і нормалізація id мають залишатися в -реалізації Plugin. +Перевірка облікового запису й нормалізація ідентифікаторів, специфічні для каналу, мають залишатися +в реалізації плагіна. ## Каталоги провайдерів -Плагіни провайдерів можуть визначати каталоги моделей для висновку через +Плагіни провайдерів можуть визначати каталоги моделей для інференсу через `registerProvider({ catalog: { run(...) { ... } } })`. -`catalog.run(...)` повертає ту саму форму, яку OpenClaw записує в +`catalog.run(...)` повертає ту саму форму, яку OpenClaw записує до `models.providers`: - `{ provider }` для одного запису провайдера - `{ providers }` для кількох записів провайдерів -Використовуйте `catalog`, коли Plugin володіє специфічними для провайдера id моделей, значеннями -`base URL` за замовчуванням або метаданими моделей, захищеними auth. +Використовуйте `catalog`, коли плагін володіє специфічними для провайдера model id, типовими значеннями base URL або метаданими моделей, захищеними автентифікацією. -`catalog.order` визначає, коли каталог Plugin зливається відносно +`catalog.order` керує тим, коли каталог плагіна зливається відносно вбудованих неявних провайдерів OpenClaw: -- `simple`: звичайні провайдери на основі API key або env -- `profile`: провайдери, які з’являються, коли існують профілі auth +- `simple`: звичайні провайдери з API-ключем або на основі env +- `profile`: провайдери, які з’являються, коли існують профілі автентифікації - `paired`: провайдери, які синтезують кілька пов’язаних записів провайдерів - `late`: останній прохід, після інших неявних провайдерів -Пізніші провайдери перемагають у разі колізії ключів, тож Plugin можуть навмисно перевизначати -вбудований запис провайдера з тим самим id провайдера. +Пізніші провайдери перемагають у разі конфлікту ключів, тож плагіни можуть навмисно перевизначати +вбудований запис провайдера з тим самим ідентифікатором провайдера. Сумісність: - `discovery` усе ще працює як застарілий псевдонім - якщо зареєстровано і `catalog`, і `discovery`, OpenClaw використовує `catalog` -## Канал лише для читання: перевірка стану +## Інспекція каналу лише для читання -Якщо ваш Plugin реєструє канал, надавайте перевагу реалізації -`plugin.config.inspectAccount(cfg, accountId)` разом із `resolveAccount(...)`. +Якщо ваш плагін реєструє канал, надавайте перевагу реалізації +`plugin.config.inspectAccount(cfg, accountId)` поряд із `resolveAccount(...)`. Чому: - `resolveAccount(...)` — це шлях середовища виконання. Він може припускати, що облікові дані - повністю матеріалізовані, і швидко завершуватися з помилкою, коли потрібні секрети відсутні. -- Шляхи команд лише для читання, як-от `openclaw status`, `openclaw status --all`, - `openclaw channels status`, `openclaw channels resolve` і потоки doctor/config - repair, не повинні вимагати матеріалізації облікових даних середовища виконання лише для - опису config. + повністю матеріалізовані, і швидко завершуватися з помилкою, коли необхідні секрети відсутні. +- Шляхи команд лише для читання, такі як `openclaw status`, `openclaw status --all`, + `openclaw channels status`, `openclaw channels resolve`, а також потоки doctor/config + repair не повинні потребувати матеріалізації облікових даних середовища виконання лише для + опису конфігурації. Рекомендована поведінка `inspectAccount(...)`: - Повертайте лише описовий стан облікового запису. - Зберігайте `enabled` і `configured`. -- Додавайте поля джерела/статусу облікових даних, коли це доречно, наприклад: +- За потреби включайте поля джерела/стану облікових даних, наприклад: - `tokenSource`, `tokenStatus` - `botTokenSource`, `botTokenStatus` - `appTokenSource`, `appTokenStatus` - `signingSecretSource`, `signingSecretStatus` -- Вам не потрібно повертати сирі значення токенів лише для повідомлення про доступність у режимі лише для читання. Достатньо повернути `tokenStatus: "available"` (і відповідне поле джерела). -- Використовуйте `configured_unavailable`, коли облікові дані налаштовано через SecretRef, але вони - недоступні в поточному шляху команди. +- Вам не потрібно повертати сирі значення токенів лише для повідомлення про доступність у режимі лише читання. Достатньо повернути `tokenStatus: "available"` (і відповідне поле джерела) для команд стилю status. +- Використовуйте `configured_unavailable`, коли облікові дані налаштовано через SecretRef, але + вони недоступні в поточному шляху команди. -Це дає змогу командам лише для читання повідомляти «налаштовано, але недоступно в цьому шляху команди» +Це дозволяє командам лише для читання повідомляти «налаштовано, але недоступно в цьому шляху команди» замість аварійного завершення або хибного повідомлення, що обліковий запис не налаштовано. -## Пакетні набори +## Пакети пакетів -Каталог Plugin може містити `package.json` з `openclaw.extensions`: +Каталог плагіна може містити `package.json` з `openclaw.extensions`: ```json { @@ -1387,62 +1387,65 @@ Plugin і повторно використовувати спільні доп } ``` -Кожен запис стає Plugin. Якщо набір містить кілька розширень, id Plugin +Кожен запис стає плагіном. Якщо пакет містить кілька розширень, ідентифікатор плагіна стає `name/`. -Якщо ваш Plugin імпортує залежності npm, встановіть їх у цей каталог, щоб +Якщо ваш плагін імпортує npm-залежності, встановіть їх у цьому каталозі, щоб `node_modules` був доступний (`npm install` / `pnpm install`). -Запобіжник безпеки: кожен запис `openclaw.extensions` має залишатися всередині каталогу Plugin -після визначення symlink. Записи, які виходять за межі каталогу пакета, відхиляються. +Захисне обмеження безпеки: кожен запис `openclaw.extensions` має залишатися в межах каталогу плагіна +після визначення символічних посилань. Записи, що виходять за межі каталогу пакета, відхиляються. -Примітка щодо безпеки: `openclaw plugins install` встановлює залежності Plugin за допомогою -`npm install --omit=dev --ignore-scripts` (без lifecycle scripts і без dev dependencies під час виконання). Зберігайте дерева залежностей Plugin «чистими JS/TS» й уникайте пакетів, яким потрібні збірки `postinstall`. +Примітка щодо безпеки: `openclaw plugins install` встановлює залежності плагіна за допомогою +`npm install --omit=dev --ignore-scripts` (без lifecycle scripts, без dev-залежностей під час виконання). Тримайте дерево залежностей плагіна +«чистим JS/TS» і уникайте пакетів, які вимагають збірок через `postinstall`. -Необов’язково: `openclaw.setupEntry` може вказувати на легкий модуль лише для налаштування. -Коли OpenClaw потрібні поверхні налаштування для вимкненого Plugin каналу або -коли Plugin каналу увімкнено, але ще не налаштовано, він завантажує `setupEntry` -замість повної точки входу Plugin. Це робить запуск і налаштування легшими, -коли основна точка входу Plugin також підключає інструменти, хуки або інший код, -призначений лише для середовища виконання. +Необов’язково: `openclaw.setupEntry` може вказувати на легковаговий модуль лише для налаштування. +Коли OpenClaw потребує поверхні налаштування для вимкненого плагіна каналу або +коли плагін каналу увімкнено, але ще не налаштовано, він завантажує `setupEntry` +замість повної точки входу плагіна. Це робить запуск і налаштування легшими, +коли основна точка входу плагіна також підключає інструменти, хуки або інший код +лише для середовища виконання. Необов’язково: `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` -може перевести Plugin каналу на той самий шлях `setupEntry` під час -фази запуску gateway до початку прослуховування, навіть якщо канал уже налаштовано. +може підключити плагін каналу до того самого шляху `setupEntry` під час +фази запуску gateway до початку прослуховування, навіть коли канал уже налаштовано. Використовуйте це лише тоді, коли `setupEntry` повністю покриває поверхню запуску, яка має існувати -до того, як gateway почне прослуховування. На практиці це означає, що точка входу налаштування -має реєструвати кожну можливість каналу, від якої залежить запуск, зокрема: +до того, як gateway почне прослуховувати. На практиці це означає, що точка входу налаштування +має зареєструвати кожну можливість каналу, від якої залежить запуск, наприклад: - саму реєстрацію каналу -- будь-які HTTP-маршрути, які мають бути доступні до того, як gateway почне прослуховування -- будь-які методи gateway, інструменти або сервіси, які мають існувати в тому самому вікні часу +- будь-які HTTP-маршрути, які мають бути доступні до того, як gateway почне прослуховувати +- будь-які методи gateway, інструменти або сервіси, які мають існувати в це саме вікно Якщо ваша повна точка входу все ще володіє будь-якою необхідною можливістю запуску, не вмикайте -цей прапорець. Залишайте для Plugin стандартну поведінку й дозвольте OpenClaw завантажити +цей прапорець. Залишайте для плагіна типову поведінку і дозвольте OpenClaw завантажити повну точку входу під час запуску. -Вбудовані канали також можуть публікувати допоміжні засоби поверхні контракту лише для налаштування, з якими core -може радитися до завантаження повного середовища виконання каналу. Поточна поверхня +Вбудовані канали також можуть публікувати допоміжні засоби поверхні контракту лише для налаштування, які core +може використовувати до завантаження повного середовища виконання каналу. Поточна поверхня просування налаштування така: - `singleAccountKeysToMove` - `namedAccountPromotionKeys` - `resolveSingleAccountPromotionTarget(...)` -Core використовує цю поверхню, коли йому потрібно просунути застарілий config однокористувацького каналу -до `channels..accounts.*` без завантаження повної точки входу Plugin. -Поточний вбудований приклад — Matrix: він переносить лише ключі auth/bootstrap у -іменований просунутий обліковий запис, коли іменовані облікові записи вже існують, і може -зберегти налаштований неканонічний ключ default-account замість того, щоб завжди створювати +Core використовує цю поверхню, коли йому потрібно просунути застарілу конфігурацію каналу з одним обліковим записом до +`channels..accounts.*` без завантаження повної точки входу плагіна. +Matrix — поточний вбудований приклад: він переміщує лише ключі auth/bootstrap до +іменованого просунутого облікового запису, коли іменовані облікові записи вже існують, і може +зберегти налаштований неканонічний ключ облікового запису за замовчуванням замість завжди створювати `accounts.default`. -Ці адаптери патчів налаштування зберігають відкладене виявлення поверхні контракту вбудованих компонентів. Час імпорту залишається малим; поверхня просування завантажується лише під час першого використання замість повторного входу у вбудований запуск каналу під час імпорту модуля. +Ці адаптери patch для налаштування зберігають лінивим виявлення поверхні контракту вбудованих компонентів. +Час імпорту залишається малим; поверхня просування завантажується лише під час першого використання +замість повторного входу до запуску вбудованого каналу під час імпорту модуля. -Коли ці поверхні запуску містять методи Gateway RPC, зберігайте їх на -префіксі, специфічному для Plugin. Простори імен адміністратора core (`config.*`, -`exec.approvals.*`, `wizard.*`, `update.*`) залишаються зарезервованими та завжди визначаються -як `operator.admin`, навіть якщо Plugin запитує вужчу область. +Коли ці поверхні запуску включають методи Gateway RPC, тримайте їх на +префіксі, специфічному для плагіна. Простори імен адміністратора core (`config.*`, +`exec.approvals.*`, `wizard.*`, `update.*`) залишаються зарезервованими й завжди визначаються +як `operator.admin`, навіть якщо плагін запитує вужчу область. Приклад: @@ -1461,8 +1464,8 @@ Core використовує цю поверхню, коли йому потр ### Метадані каталогу каналів -Плагіни каналів можуть оголошувати метадані налаштування/виявлення через `openclaw.channel` і -підказки встановлення через `openclaw.install`. Це зберігає дані каталогу core вільними від даних. +Плагіни каналів можуть оголошувати метадані налаштування/виявлення через `openclaw.channel`, а +підказки встановлення — через `openclaw.install`. Це дозволяє core не містити дані каталогу. Приклад: @@ -1490,20 +1493,20 @@ Core використовує цю поверхню, коли йому потр } ``` -Корисні поля `openclaw.channel` поза мінімальним прикладом: +Корисні поля `openclaw.channel`, окрім мінімального прикладу: - `detailLabel`: вторинна мітка для багатших поверхонь каталогу/статусу -- `docsLabel`: перевизначення тексту посилання для посилання на документацію -- `preferOver`: id Plugin/каналів нижчого пріоритету, які цей запис каталогу має перевищувати +- `docsLabel`: перевизначає текст посилання для посилання на документацію +- `preferOver`: ідентифікатори плагінів/каналів нижчого пріоритету, які цей запис каталогу має перевершувати - `selectionDocsPrefix`, `selectionDocsOmitLabel`, `selectionExtras`: елементи керування текстом поверхні вибору -- `markdownCapable`: позначає канал як здатний до Markdown для рішень про форматування вихідних даних +- `markdownCapable`: позначає канал як сумісний з markdown для рішень щодо вихідного форматування - `exposure.configured`: приховує канал із поверхонь списку налаштованих каналів, якщо встановлено `false` -- `exposure.setup`: приховує канал із інтерактивних селекторів налаштування/конфігурації, якщо встановлено `false` -- `exposure.docs`: позначає канал як внутрішній/приватний для поверхонь навігації документацією +- `exposure.setup`: приховує канал з інтерактивних засобів вибору налаштування/конфігурації, якщо встановлено `false` +- `exposure.docs`: позначає канал як внутрішній/приватний для поверхонь навігації документації - `showConfigured` / `showInSetup`: застарілі псевдоніми, які все ще приймаються для сумісності; надавайте перевагу `exposure` - `quickstartAllowFrom`: підключає канал до стандартного потоку quickstart `allowFrom` -- `forceAccountBinding`: вимагає явного прив’язування облікового запису, навіть якщо існує лише один обліковий запис -- `preferSessionLookupForAnnounceTarget`: надає перевагу пошуку сеансу під час визначення цілей оголошення +- `forceAccountBinding`: вимагає явної прив’язки облікового запису, навіть коли існує лише один обліковий запис +- `preferSessionLookupForAnnounceTarget`: надає перевагу пошуку сесії під час визначення цілей announce OpenClaw також може зливати **зовнішні каталоги каналів** (наприклад, експорт реєстру MPM). Помістіть JSON-файл в одне з таких місць: @@ -1513,18 +1516,18 @@ OpenClaw також може зливати **зовнішні каталоги - `~/.openclaw/plugins/catalog.json` Або вкажіть `OPENCLAW_PLUGIN_CATALOG_PATHS` (або `OPENCLAW_MPM_CATALOG_PATHS`) на -один або кілька JSON-файлів (із розділенням комами/крапками з комою/через `PATH`). Кожен файл має +один чи кілька JSON-файлів (розділених комою/крапкою з комою/`PATH`). Кожен файл має містити `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`. Парсер також приймає `"packages"` або `"plugins"` як застарілі псевдоніми для ключа `"entries"`. -## Plugin рушія контексту +## Плагіни рушія контексту -Plugin рушія контексту володіють оркестрацією контексту сеансу для інжесту, збирання -та Compaction. Реєструйте їх зі свого Plugin через +Плагіни рушія контексту володіють оркестрацією контексту сесії для надходження, збирання +та Compaction. Реєструйте їх зі свого плагіна через `api.registerContextEngine(id, factory)`, а потім вибирайте активний рушій через `plugins.slots.contextEngine`. -Використовуйте це, коли вашому Plugin потрібно замінити або розширити стандартний -конвеєр контексту, а не просто додати пошук у пам’яті чи хуки. +Використовуйте це, коли вашому плагіну потрібно замінити або розширити типовий конвеєр контексту, +а не просто додати пошук пам’яті чи хуки. ```ts import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core"; @@ -1552,8 +1555,8 @@ export default function (api) { } ``` -Якщо ваш рушій **не** володіє алгоритмом Compaction, збережіть реалізацію `compact()` -і явно делегуйте її: +Якщо ваш рушій **не** володіє алгоритмом Compaction, залиште `compact()` +реалізованим і явно делегуйте його: ```ts import { @@ -1590,43 +1593,43 @@ export default function (api) { ## Додавання нової можливості -Коли Plugin потрібна поведінка, яка не вписується в поточний API, не обходьте -систему Plugin через приватний доступ до внутрішніх частин. Додайте відсутню можливість. +Коли плагіну потрібна поведінка, яка не вписується в поточний API, не обходьте +систему плагінів через приватне проникнення всередину. Додайте відсутню можливість. Рекомендована послідовність: 1. визначте контракт core - Вирішіть, якою спільною поведінкою має володіти core: політикою, резервною поведінкою, злиттям config, - життєвим циклом, семантикою для каналів і формою допоміжних засобів середовища виконання. -2. додайте типізовані поверхні реєстрації Plugin/середовища виконання + Вирішіть, якою спільною поведінкою має володіти core: політикою, резервною логікою, злиттям конфігурації, + життєвим циклом, семантикою, орієнтованою на канали, і формою допоміжного засобу середовища виконання. +2. додайте типізовані поверхні реєстрації/середовища виконання плагіна Розширте `OpenClawPluginApi` і/або `api.runtime` найменшою корисною типізованою поверхнею можливості. -3. під’єднайте споживачів core + каналів/функцій +3. під’єднайте core + споживачів каналів/функцій Канали та плагіни функцій мають використовувати нову можливість через core, - а не імпортувати реалізацію вендора напряму. -4. зареєструйте реалізації вендорів - Потім vendor Plugin реєструють свої backend для цієї можливості. + а не шляхом прямого імпорту реалізації постачальника. +4. зареєструйте реалізації постачальників + Потім плагіни постачальників реєструють свої бекенди для цієї можливості. 5. додайте покриття контракту - Додайте тести, щоб володіння та форма реєстрації з часом залишалися явними. + Додайте тести, щоб форма володіння та реєстрації з часом залишалися явними. -Саме так OpenClaw зберігає чітку позицію, не перетворюючись на систему, жорстко закодовану під -світогляд одного провайдера. Див. [Практичний посібник із можливостей](/uk/plugins/architecture) -для конкретного контрольного списку файлів і готового прикладу. +Саме так OpenClaw зберігає виразну позицію, не стаючи жорстко прив’язаним до +погляду одного провайдера. Див. [Збірник рецептів можливостей](/uk/plugins/architecture), +щоб отримати конкретний список файлів і готовий приклад. ### Контрольний список можливості Коли ви додаєте нову можливість, реалізація зазвичай має торкатися цих поверхонь разом: -- типи контракту core у `src//types.ts` -- helper runner/runtime core у `src//runtime.ts` -- поверхня реєстрації API Plugin у `src/plugins/types.ts` -- підключення реєстру Plugin у `src/plugins/registry.ts` -- відкриття середовища виконання Plugin у `src/plugins/runtime/*`, коли плагіни функцій/каналів - мають її використовувати +- типи контрактів core у `src//types.ts` +- допоміжний засіб runner/середовища виконання core у `src//runtime.ts` +- поверхня реєстрації API плагіна в `src/plugins/types.ts` +- підключення реєстру плагінів у `src/plugins/registry.ts` +- відкриття середовища виконання плагіна в `src/plugins/runtime/*`, коли плагіни функцій/каналів + мають це використовувати - допоміжні засоби capture/test у `src/test-utils/plugin-registration.ts` - перевірки володіння/контракту в `src/plugins/contracts/registry.ts` -- документація для операторів/Plugin у `docs/` +- документація для операторів/плагінів у `docs/` Якщо однієї з цих поверхонь бракує, це зазвичай ознака того, що можливість ще не повністю інтегрована. @@ -1636,14 +1639,14 @@ export default function (api) { Мінімальний шаблон: ```ts -// контракт core +// core contract export type VideoGenerationProviderPlugin = { id: string; label: string; generateVideo: (req: VideoGenerationRequest) => Promise; }; -// API Plugin +// plugin API api.registerVideoGenerationProvider({ id: "openai", label: "OpenAI", @@ -1652,14 +1655,14 @@ api.registerVideoGenerationProvider({ }, }); -// спільний helper середовища виконання для плагінів функцій/каналів +// shared runtime helper for feature/channel plugins const clip = await api.runtime.videoGeneration.generate({ prompt: "Show the robot walking through the lab.", cfg, }); ``` -Шаблон контрактного тесту: +Шаблон тесту контракту: ```ts expect(findVideoGenerationProviderIdsForPlugin("openai")).toEqual(["openai"]); @@ -1668,6 +1671,6 @@ expect(findVideoGenerationProviderIdsForPlugin("openai")).toEqual(["openai"]); Це зберігає правило простим: - core володіє контрактом можливості + оркестрацією -- vendor Plugin володіють реалізаціями вендорів -- плагіни функцій/каналів використовують helpers середовища виконання -- контрактні тести зберігають явність володіння +- плагіни постачальників володіють реалізаціями постачальників +- плагіни функцій/каналів використовують допоміжні засоби середовища виконання +- тести контрактів зберігають явність володіння diff --git a/docs/uk/plugins/manifest.md b/docs/uk/plugins/manifest.md index 083cf712c..2f78fde3b 100644 --- a/docs/uk/plugins/manifest.md +++ b/docs/uk/plugins/manifest.md @@ -1,14 +1,14 @@ --- read_when: - Ви створюєте Plugin для OpenClaw - - Вам потрібно постачати схему конфігурації Plugin або налагоджувати помилки валідації Plugin -summary: Вимоги до маніфесту Plugin + схеми JSON (сувора валідація конфігурації) + - Вам потрібно постачати схему конфігурації plugin або налагоджувати помилки валідації plugin +summary: Вимоги до маніфесту Plugin та JSON schema (сувора валідація конфігурації) title: Маніфест Plugin x-i18n: - generated_at: "2026-04-21T17:54:48Z" + generated_at: "2026-04-21T20:37:38Z" model: gpt-5.4 provider: openai - source_hash: 304c08035724dfb1ce6349972729b621aafc00880d4d259db78c22b86e9056ba + source_hash: 3664a984ac283378e11a76a68dfa320dc4d5a2aa40d973c731eb31e87d6eeeef source_path: plugins/manifest.md workflow: 15 --- @@ -17,63 +17,61 @@ x-i18n: Ця сторінка стосується лише **власного маніфесту Plugin OpenClaw**. -Сумісні макети пакетів описано в розділі [Пакети Plugin](/uk/plugins/bundles). +Сумісні компонування bundle описано в [Plugin bundles](/uk/plugins/bundles). -Сумісні формати пакетів використовують інші файли маніфесту: +Сумісні формати bundle використовують інші файли маніфесту: -- Пакет Codex: `.codex-plugin/plugin.json` -- Пакет Claude: `.claude-plugin/plugin.json` або стандартний макет компонента Claude +- bundle Codex: `.codex-plugin/plugin.json` +- bundle Claude: `.claude-plugin/plugin.json` або стандартне компонування компонента Claude без маніфесту -- Пакет Cursor: `.cursor-plugin/plugin.json` +- bundle Cursor: `.cursor-plugin/plugin.json` -OpenClaw також автоматично виявляє ці макети пакетів, але вони не проходять валідацію +OpenClaw також автоматично виявляє ці компонування bundle, але вони не проходять валідацію за схемою `openclaw.plugin.json`, описаною тут. -Для сумісних пакетів OpenClaw наразі зчитує метадані пакета разом з оголошеними -коренями Skills, коренями команд Claude, типовими значеннями `settings.json` пакета Claude, -типовими значеннями Claude bundle LSP і підтримуваними наборами хуків, якщо макет відповідає +Для сумісних bundle OpenClaw наразі читає метадані bundle разом з оголошеними +коренями skill, коренями команд Claude, типовими значеннями `settings.json` bundle Claude, +типовими значеннями LSP bundle Claude та підтримуваними наборами hook, коли компонування відповідає очікуванням середовища виконання OpenClaw. Кожен власний Plugin OpenClaw **повинен** постачатися з файлом `openclaw.plugin.json` у -**корені Plugin**. OpenClaw використовує цей маніфест для валідації конфігурації -**без виконання коду Plugin**. Відсутні або недійсні маніфести вважаються -помилками Plugin і блокують валідацію конфігурації. +**корені plugin**. OpenClaw використовує цей маніфест для валідації конфігурації +**без виконання коду plugin**. Відсутні або невалідні маніфести вважаються +помилками plugin і блокують валідацію конфігурації. -Дивіться повний посібник із системи Plugin: [Plugins](/uk/tools/plugin). -Щодо власної моделі можливостей і поточних рекомендацій щодо зовнішньої сумісності: +Повний посібник із системи plugin див. у: [Plugins](/uk/tools/plugin). +Про власну модель можливостей і поточні рекомендації щодо зовнішньої сумісності: [Модель можливостей](/uk/plugins/architecture#public-capability-model). -## Для чого потрібен цей файл +## Що робить цей файл -`openclaw.plugin.json` — це метадані, які OpenClaw зчитує до завантаження коду -вашого Plugin. +`openclaw.plugin.json` — це метадані, які OpenClaw читає перед завантаженням +коду вашого plugin. Використовуйте його для: -- ідентичності Plugin +- ідентичності plugin - валідації конфігурації -- метаданих автентифікації та онбордингу, які мають бути доступні без запуску - середовища виконання Plugin -- недорогих підказок активації, які поверхні площини керування можуть перевіряти до завантаження середовища виконання -- недорогих дескрипторів налаштування, які поверхні налаштування/онбордингу можуть перевіряти до завантаження - середовища виконання -- метаданих псевдонімів і автоувімкнення, які мають визначатися до завантаження середовища виконання Plugin -- скорочених метаданих володіння сімействами моделей, які мають автоматично активувати - Plugin до завантаження середовища виконання -- статичних знімків володіння можливостями, що використовуються для сумісного підключення вбудованих компонентів і покриття контрактів +- метаданих auth та onboarding, які мають бути доступні без запуску середовища виконання plugin +- недорогих підказок активації, які поверхні control-plane можуть перевіряти до завантаження runtime +- недорогих дескрипторів налаштування, які поверхні setup/onboarding можуть перевіряти до завантаження runtime +- метаданих alias та auto-enable, які мають розв’язуватися до завантаження runtime plugin +- скорочених метаданих про належність до сімейства моделей, які мають автоматично активувати + plugin до завантаження runtime +- статичних знімків належності можливостей, що використовуються для вбудованого compat-зв’язування та + покриття контрактів - недорогих метаданих QA runner, які спільний хост `openclaw qa` може перевіряти - до завантаження середовища виконання Plugin -- метаданих конфігурації, специфічних для каналу, які мають об’єднуватися в - поверхні каталогу та валідації без завантаження середовища виконання + до завантаження runtime plugin +- метаданих конфігурації, специфічних для channel, які мають об’єднуватися з поверхнями каталогу та валідації без завантаження runtime - підказок UI для конфігурації Не використовуйте його для: -- реєстрації поведінки середовища виконання -- оголошення точок входу коду +- реєстрації поведінки runtime +- оголошення code entrypoint - метаданих встановлення npm -Для цього призначені код вашого Plugin і `package.json`. +Це належить до коду вашого plugin та `package.json`. ## Мінімальний приклад @@ -153,66 +151,66 @@ OpenClaw також автоматично виявляє ці макети па ## Довідник полів верхнього рівня -| Поле | Обов’язкове | Тип | Що це означає | -| ----------------------------------- | ----------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `id` | Так | `string` | Канонічний ідентифікатор Plugin. Саме цей ідентифікатор використовується в `plugins.entries.`. | -| `configSchema` | Так | `object` | Вбудована JSON Schema для конфігурації цього Plugin. | -| `enabledByDefault` | Ні | `true` | Позначає вбудований Plugin як увімкнений за замовчуванням. Не вказуйте це поле або встановіть будь-яке значення, відмінне від `true`, щоб Plugin залишався вимкненим за замовчуванням. | -| `legacyPluginIds` | Ні | `string[]` | Застарілі ідентифікатори, які нормалізуються до цього канонічного ідентифікатора Plugin. | -| `autoEnableWhenConfiguredProviders` | Ні | `string[]` | Ідентифікатори provider, які мають автоматично вмикати цей Plugin, коли автентифікація, конфігурація або посилання на моделі згадують їх. | -| `kind` | Ні | `"memory"` \| `"context-engine"` | Оголошує винятковий тип Plugin, який використовується в `plugins.slots.*`. | -| `channels` | Ні | `string[]` | Ідентифікатори channel, якими володіє цей Plugin. Використовуються для виявлення та валідації конфігурації. | -| `providers` | Ні | `string[]` | Ідентифікатори provider, якими володіє цей Plugin. | -| `modelSupport` | Ні | `object` | Скорочені метадані сімейств моделей, що належать маніфесту та використовуються для автоматичного завантаження Plugin до запуску середовища виконання. | -| `providerEndpoints` | Ні | `object[]` | Метадані hosts/baseUrl кінцевих точок, що належать маніфесту, для маршрутів provider, які ядро має класифікувати до завантаження середовища виконання provider. | -| `cliBackends` | Ні | `string[]` | Ідентифікатори CLI backend, якими володіє цей Plugin. Використовуються для автоматичної активації під час запуску на основі явних посилань у конфігурації. | -| `syntheticAuthRefs` | Ні | `string[]` | Посилання на provider або CLI backend, для яких під час холодного виявлення моделей до завантаження середовища виконання потрібно перевіряти синтетичний хук автентифікації, що належить Plugin. | -| `nonSecretAuthMarkers` | Ні | `string[]` | Значення-заповнювачі API key, що належать вбудованому Plugin і представляють несекретний локальний стан, OAuth або стан ambient credential. | -| `commandAliases` | Ні | `object[]` | Імена команд, якими володіє цей Plugin і які мають формувати діагностику конфігурації та CLI з урахуванням Plugin до завантаження середовища виконання. | -| `providerAuthEnvVars` | Ні | `Record` | Недорогі env-метадані автентифікації provider, які OpenClaw може перевіряти без завантаження коду Plugin. | -| `providerAuthAliases` | Ні | `Record` | Ідентифікатори provider, які мають повторно використовувати інший ідентифікатор provider для пошуку автентифікації, наприклад coding provider, що використовує той самий API key та профілі автентифікації. | -| `channelEnvVars` | Ні | `Record` | Недорогі env-метадані channel, які OpenClaw може перевіряти без завантаження коду Plugin. Використовуйте це для керованих через env поверхонь налаштування або автентифікації channel, які мають бачити загальні допоміжні засоби запуску/конфігурації. | -| `providerAuthChoices` | Ні | `object[]` | Недорогі метадані варіантів автентифікації для засобів вибору під час онбордингу, визначення пріоритетного provider та простого зв’язування CLI-прапорців. | -| `activation` | Ні | `object` | Недорогі підказки активації для завантаження, що запускається provider, командою, channel, маршрутом і можливістю. Лише метадані; фактична поведінка, як і раніше, належить середовищу виконання Plugin. | -| `setup` | Ні | `object` | Недорогі дескриптори налаштування/онбордингу, які поверхні виявлення та налаштування можуть перевіряти без завантаження середовища виконання Plugin. | -| `qaRunners` | Ні | `object[]` | Недорогі дескриптори QA runner, які спільний хост `openclaw qa` використовує до завантаження середовища виконання Plugin. | -| `contracts` | Ні | `object` | Статичний знімок вбудованих можливостей для speech, realtime transcription, realtime voice, media-understanding, image-generation, music-generation, video-generation, web-fetch, web search і володіння інструментами. | -| `channelConfigs` | Ні | `Record` | Метадані конфігурації channel, що належать маніфесту та об’єднуються в поверхні виявлення й валідації до завантаження середовища виконання. | -| `skills` | Ні | `string[]` | Каталоги Skills для завантаження, відносно кореня Plugin. | -| `name` | Ні | `string` | Людинозрозуміла назва Plugin. | -| `description` | Ні | `string` | Короткий опис, що показується в поверхнях Plugin. | -| `version` | Ні | `string` | Інформаційна версія Plugin. | -| `uiHints` | Ні | `Record` | Мітки UI, заповнювачі та підказки щодо чутливості для полів конфігурації. | +| Поле | Обов’язкове | Тип | Що воно означає | +| ----------------------------------- | ----------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | Так | `string` | Канонічний ідентифікатор plugin. Це ідентифікатор, що використовується в `plugins.entries.`. | +| `configSchema` | Так | `object` | Вбудована JSON Schema для конфігурації цього plugin. | +| `enabledByDefault` | Ні | `true` | Позначає вбудований plugin як увімкнений типово. Не вказуйте це поле або задайте будь-яке значення, відмінне від `true`, щоб plugin залишався типово вимкненим. | +| `legacyPluginIds` | Ні | `string[]` | Застарілі ідентифікатори, які нормалізуються до цього канонічного ідентифікатора plugin. | +| `autoEnableWhenConfiguredProviders` | Ні | `string[]` | Ідентифікатори provider, які мають автоматично вмикати цей plugin, коли auth, конфігурація або посилання на моделі згадують їх. | +| `kind` | Ні | `"memory"` \| `"context-engine"` | Оголошує ексклюзивний вид plugin, який використовується в `plugins.slots.*`. | +| `channels` | Ні | `string[]` | Ідентифікатори channel, якими володіє цей plugin. Використовується для виявлення та валідації конфігурації. | +| `providers` | Ні | `string[]` | Ідентифікатори provider, якими володіє цей plugin. | +| `modelSupport` | Ні | `object` | Скорочені метадані про сімейство моделей, що належать маніфесту й використовуються для автоматичного завантаження plugin до запуску runtime. | +| `providerEndpoints` | Ні | `object[]` | Метадані хостів/`baseUrl` endpoint, що належать маніфесту, для маршрутів provider, які core має класифікувати до завантаження runtime provider. | +| `cliBackends` | Ні | `string[]` | Ідентифікатори backend CLI, якими володіє цей plugin. Використовується для автоактивації під час запуску на основі явних посилань у конфігурації. | +| `syntheticAuthRefs` | Ні | `string[]` | Посилання на provider або backend CLI, для яких слід перевіряти синтетичний hook auth, що належить plugin, під час холодного виявлення моделей до завантаження runtime. | +| `nonSecretAuthMarkers` | Ні | `string[]` | Значення-заповнювачі API key, що належать вбудованому plugin і представляють не секретний локальний стан, OAuth або ambient credential state. | +| `commandAliases` | Ні | `object[]` | Імена команд, якими володіє цей plugin і які мають формувати діагностику конфігурації та CLI, обізнану про plugin, до завантаження runtime. | +| `providerAuthEnvVars` | Ні | `Record` | Недорогі метадані env для auth provider, які OpenClaw може перевіряти без завантаження коду plugin. | +| `providerAuthAliases` | Ні | `Record` | Ідентифікатори provider, які мають повторно використовувати інший ідентифікатор provider для пошуку auth, наприклад provider для кодування, що спільно використовує API key і профілі auth базового provider. | +| `channelEnvVars` | Ні | `Record` | Недорогі метадані env для channel, які OpenClaw може перевіряти без завантаження коду plugin. Використовуйте це для поверхонь налаштування channel або auth, керованих env, які мають бачити типові допоміжні засоби запуску/конфігурації. | +| `providerAuthChoices` | Ні | `object[]` | Недорогі метадані вибору auth для picker під час onboarding, визначення бажаного provider та простого зв’язування прапорців CLI. | +| `activation` | Ні | `object` | Недорогі підказки активації для завантаження, що запускається provider, командою, channel, маршрутом або можливістю. Лише метадані; фактична поведінка все одно належить runtime plugin. | +| `setup` | Ні | `object` | Недорогі дескриптори setup/onboarding, які поверхні виявлення та налаштування можуть перевіряти без завантаження runtime plugin. | +| `qaRunners` | Ні | `object[]` | Недорогі дескриптори QA runner, які використовує спільний хост `openclaw qa` до завантаження runtime plugin. | +| `contracts` | Ні | `object` | Статичний знімок вбудованих можливостей для speech, realtime transcription, realtime voice, media-understanding, image-generation, music-generation, video-generation, web-fetch, web search і належності tool. | +| `channelConfigs` | Ні | `Record` | Метадані конфігурації channel, що належать маніфесту та об’єднуються з поверхнями виявлення й валідації до завантаження runtime. | +| `skills` | Ні | `string[]` | Каталоги Skills для завантаження, відносно кореня plugin. | +| `name` | Ні | `string` | Людинозрозуміла назва plugin. | +| `description` | Ні | `string` | Короткий опис, що показується в поверхнях plugin. | +| `version` | Ні | `string` | Інформаційна версія plugin. | +| `uiHints` | Ні | `Record` | Мітки UI, placeholders і підказки щодо чутливості для полів конфігурації. | ## Довідник `providerAuthChoices` -Кожен запис `providerAuthChoices` описує один варіант онбордингу або автентифікації. -OpenClaw зчитує це до завантаження середовища виконання provider. +Кожен запис `providerAuthChoices` описує один варіант onboarding або auth. +OpenClaw читає це до завантаження runtime provider. -| Поле | Обов’язкове | Тип | Що це означає | +| Поле | Обов’язкове | Тип | Що воно означає | | --------------------- | ----------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------- | | `provider` | Так | `string` | Ідентифікатор provider, до якого належить цей варіант. | -| `method` | Так | `string` | Ідентифікатор методу автентифікації, до якого слід диспетчеризувати. | -| `choiceId` | Так | `string` | Стабільний ідентифікатор варіанта автентифікації, який використовується онбордингом і потоками CLI. | -| `choiceLabel` | Ні | `string` | Мітка для користувача. Якщо не вказано, OpenClaw використовує `choiceId`. | -| `choiceHint` | Ні | `string` | Короткий допоміжний текст для засобу вибору. | -| `assistantPriority` | Ні | `number` | Менші значення сортуються раніше в інтерактивних засобах вибору, керованих асистентом. | -| `assistantVisibility` | Ні | `"visible"` \| `"manual-only"` | Приховує варіант із засобів вибору асистента, але все ще дозволяє ручний вибір через CLI. | -| `deprecatedChoiceIds` | Ні | `string[]` | Застарілі ідентифікатори варіантів, які мають перенаправляти користувачів до цього варіанта-замінника. | +| `method` | Так | `string` | Ідентифікатор методу auth, до якого слід виконати диспетчеризацію. | +| `choiceId` | Так | `string` | Стабільний ідентифікатор варіанта auth, який використовується в потоках onboarding і CLI. | +| `choiceLabel` | Ні | `string` | Мітка для користувача. Якщо не вказано, OpenClaw використовує `choiceId` як запасний варіант. | +| `choiceHint` | Ні | `string` | Короткий допоміжний текст для picker. | +| `assistantPriority` | Ні | `number` | Менші значення сортуються раніше в інтерактивних picker, керованих асистентом. | +| `assistantVisibility` | Ні | `"visible"` \| `"manual-only"` | Приховує варіант із picker асистента, але все ще дозволяє ручний вибір через CLI. | +| `deprecatedChoiceIds` | Ні | `string[]` | Застарілі ідентифікатори варіантів, які мають переспрямовувати користувачів до цього варіанта-заміни. | | `groupId` | Ні | `string` | Необов’язковий ідентифікатор групи для групування пов’язаних варіантів. | | `groupLabel` | Ні | `string` | Мітка для користувача для цієї групи. | | `groupHint` | Ні | `string` | Короткий допоміжний текст для групи. | -| `optionKey` | Ні | `string` | Внутрішній ключ параметра для простих потоків автентифікації з одним прапорцем. | -| `cliFlag` | Ні | `string` | Назва CLI-прапорця, наприклад `--openrouter-api-key`. | -| `cliOption` | Ні | `string` | Повна форма параметра CLI, наприклад `--openrouter-api-key `. | -| `cliDescription` | Ні | `string` | Опис, що використовується в довідці CLI. | -| `onboardingScopes` | Ні | `Array<"text-inference" \| "image-generation">` | На яких поверхнях онбордингу має з’являтися цей варіант. Якщо не вказано, типовим значенням є `["text-inference"]`. | +| `optionKey` | Ні | `string` | Внутрішній ключ опції для простих потоків auth з одним прапорцем. | +| `cliFlag` | Ні | `string` | Назва прапорця CLI, наприклад `--openrouter-api-key`. | +| `cliOption` | Ні | `string` | Повна форма опції CLI, наприклад `--openrouter-api-key `. | +| `cliDescription` | Ні | `string` | Опис, який використовується в довідці CLI. | +| `onboardingScopes` | Ні | `Array<"text-inference" \| "image-generation">` | У яких поверхнях onboarding має з’являтися цей варіант. Якщо не вказано, типово використовується `["text-inference"]`. | ## Довідник `commandAliases` -Використовуйте `commandAliases`, коли Plugin володіє назвою команди середовища виконання, яку користувачі можуть -помилково вказати в `plugins.allow` або спробувати виконати як кореневу CLI-команду. OpenClaw -використовує ці метадані для діагностики без імпорту коду середовища виконання Plugin. +Використовуйте `commandAliases`, коли plugin володіє назвою runtime-команди, яку користувачі можуть +помилково вказати в `plugins.allow` або спробувати запустити як кореневу команду CLI. OpenClaw +використовує ці метадані для діагностики без імпорту коду runtime plugin. ```json { @@ -226,22 +224,22 @@ OpenClaw зчитує це до завантаження середовища в } ``` -| Поле | Обов’язкове | Тип | Що це означає | +| Поле | Обов’язкове | Тип | Що воно означає | | ------------ | ----------- | ----------------- | ------------------------------------------------------------------------ | -| `name` | Так | `string` | Назва команди, яка належить цьому Plugin. | -| `kind` | Ні | `"runtime-slash"` | Позначає псевдонім як slash-команду чату, а не кореневу CLI-команду. | -| `cliCommand` | Ні | `string` | Пов’язана коренева CLI-команда, яку слід запропонувати для CLI-операцій, якщо вона існує. | +| `name` | Так | `string` | Назва команди, яка належить цьому plugin. | +| `kind` | Ні | `"runtime-slash"` | Позначає alias як slash-команду чату, а не кореневу команду CLI. | +| `cliCommand` | Ні | `string` | Пов’язана коренева команда CLI, яку слід запропонувати для операцій CLI, якщо вона існує. | ## Довідник `activation` -Використовуйте `activation`, коли Plugin може недорого оголосити, які події площини керування +Використовуйте `activation`, коли plugin може дешево оголосити, які події control-plane мають активувати його пізніше. ## Довідник `qaRunners` -Використовуйте `qaRunners`, коли Plugin додає один або кілька transport runner під спільним коренем -`openclaw qa`. Зберігайте ці метадані недорогими та статичними; фактична реєстрація CLI -все ще належить середовищу виконання Plugin через легку поверхню +Використовуйте `qaRunners`, коли plugin додає один або більше transport runner у межах +спільного кореня `openclaw qa`. Зберігайте ці метадані дешевими й статичними; runtime plugin +усе одно володіє фактичною реєстрацією CLI через легку поверхню `runtime-api.ts`, яка експортує `qaRunnerCliRegistrations`. ```json @@ -249,22 +247,22 @@ OpenClaw зчитує це до завантаження середовища в "qaRunners": [ { "commandName": "matrix", - "description": "Запустити lane живого QA для Matrix з Docker на одноразовому homeserver" + "description": "Run the Docker-backed Matrix live QA lane against a disposable homeserver" } ] } ``` -| Поле | Обов’язкове | Тип | Що це означає | -| ------------- | ----------- | -------- | --------------------------------------------------------------------- | -| `commandName` | Так | `string` | Підкоманда, змонтована під `openclaw qa`, наприклад `matrix`. | -| `description` | Ні | `string` | Резервний текст довідки, що використовується, коли спільному хосту потрібна stub-команда. | +| Поле | Обов’язкове | Тип | Що воно означає | +| ------------- | ----------- | -------- | ------------------------------------------------------------------- | +| `commandName` | Так | `string` | Підкоманда, змонтована в `openclaw qa`, наприклад `matrix`. | +| `description` | Ні | `string` | Резервний текст довідки, який використовується, коли спільному хосту потрібна stub-команда. | -Цей блок — лише метадані. Він не реєструє поведінку середовища виконання і не -замінює `register(...)`, `setupEntry` або інші точки входу середовища виконання/Plugin. -Поточні споживачі використовують його як підказку для звуження перед ширшим завантаженням Plugin, тож -відсутність метаданих активації зазвичай впливає лише на продуктивність; це не повинно -змінювати коректність, поки ще існують застарілі резервні механізми володіння маніфестом. +Цей блок є лише метаданими. Він не реєструє поведінку runtime і не +замінює `register(...)`, `setupEntry` чи інші entrypoint runtime/plugin. +Поточні споживачі використовують його як підказку для звуження перед ширшим завантаженням plugin, тож +відсутність метаданих activation зазвичай лише погіршує продуктивність; вона не має +змінювати коректність, поки все ще існують резервні варіанти на основі застарілого володіння маніфестом. ```json { @@ -278,28 +276,28 @@ OpenClaw зчитує це до завантаження середовища в } ``` -| Поле | Обов’язкове | Тип | Що це означає | +| Поле | Обов’язкове | Тип | Що воно означає | | ---------------- | ----------- | ---------------------------------------------------- | ------------------------------------------------------------------ | -| `onProviders` | Ні | `string[]` | Ідентифікатори provider, які мають активувати цей Plugin на запит. | -| `onCommands` | Ні | `string[]` | Ідентифікатори команд, які мають активувати цей Plugin. | -| `onChannels` | Ні | `string[]` | Ідентифікатори channel, які мають активувати цей Plugin. | -| `onRoutes` | Ні | `string[]` | Типи маршрутів, які мають активувати цей Plugin. | -| `onCapabilities` | Ні | `Array<"provider" \| "channel" \| "tool" \| "hook">` | Загальні підказки можливостей, що використовуються плануванням активації площини керування. | +| `onProviders` | Ні | `string[]` | Ідентифікатори provider, які мають активувати цей plugin за запитом. | +| `onCommands` | Ні | `string[]` | Ідентифікатори команд, які мають активувати цей plugin. | +| `onChannels` | Ні | `string[]` | Ідентифікатори channel, які мають активувати цей plugin. | +| `onRoutes` | Ні | `string[]` | Види маршрутів, які мають активувати цей plugin. | +| `onCapabilities` | Ні | `Array<"provider" \| "channel" \| "tool" \| "hook">` | Загальні підказки можливостей, що використовуються під час планування активації control-plane. | Поточні активні споживачі: -- планування CLI, що запускається командою, використовує резервний механізм +- планування CLI, запущене командою, використовує резервний варіант із застарілих `commandAliases[].cliCommand` або `commandAliases[].name` -- планування налаштування/channel, що запускається channel, використовує резервний механізм - володіння `channels[]`, якщо явні метадані активації channel відсутні -- планування налаштування/середовища виконання, що запускається provider, використовує резервний механізм - `providers[]` і володіння верхньорівневими `cliBackends[]`, якщо явні метадані активації provider - відсутні +- планування setup/channel, запущене channel, використовує резервний варіант із застарілого володіння + `channels[]`, якщо явні метадані активації channel відсутні +- планування setup/runtime, запущене provider, використовує резервний варіант із застарілого + володіння `providers[]` і `cliBackends[]` верхнього рівня, якщо явні метадані + активації provider відсутні ## Довідник `setup` -Використовуйте `setup`, коли поверхням налаштування й онбордингу потрібні недорогі метадані, що належать Plugin, -до завантаження середовища виконання. +Використовуйте `setup`, коли поверхням setup та onboarding потрібні дешеві метадані, що належать plugin, +до завантаження runtime. ```json { @@ -318,41 +316,41 @@ OpenClaw зчитує це до завантаження середовища в } ``` -Верхньорівневе `cliBackends` залишається дійсним і надалі описує CLI backend для inference. -`setup.cliBackends` — це поверхня дескрипторів, специфічна для налаштування, для потоків -площини керування/налаштування, яка має залишатися лише метаданими. +`cliBackends` верхнього рівня залишається валідним і далі описує inference-backend CLI. +`setup.cliBackends` — це поверхня дескрипторів, специфічна для setup, для +потоків control-plane/setup, які мають залишатися лише метаданими. -Якщо вони присутні, `setup.providers` і `setup.cliBackends` є пріоритетною -поверхнею пошуку на основі дескрипторів для виявлення налаштування. Якщо дескриптор лише звужує -кандидатний Plugin, а налаштуванню все ще потрібні багатші runtime-хуки під час налаштування, -встановіть `requiresRuntime: true` і залиште `setup-api` як +Якщо вони присутні, `setup.providers` і `setup.cliBackends` є бажаною +поверхнею пошуку для виявлення setup за принципом descriptor-first. Якщо дескриптор лише +звужує кандидатний plugin, а setup все ще потребує більш насичених hook runtime на етапі setup, +установіть `requiresRuntime: true` і збережіть `setup-api` як резервний шлях виконання. -Оскільки пошук налаштування може виконувати код `setup-api`, що належить Plugin, -нормалізовані значення `setup.providers[].id` і `setup.cliBackends[]` мають залишатися унікальними -серед виявлених Plugin. Неоднозначне володіння завершується безпечним блокуванням, а не вибором +Оскільки пошук setup може виконувати код `setup-api`, що належить plugin, +нормалізовані значення `setup.providers[].id` і `setup.cliBackends[]` мають залишатися унікальними серед +виявлених plugin. Неоднозначне володіння завершується безпечною відмовою замість вибору переможця за порядком виявлення. ### Довідник `setup.providers` -| Поле | Обов’язкове | Тип | Що це означає | -| ------------- | ----------- | ---------- | -------------------------------------------------------------------------------------- | -| `id` | Так | `string` | Ідентифікатор provider, який відкривається під час налаштування або онбордингу. Підтримуйте глобальну унікальність нормалізованих ідентифікаторів. | -| `authMethods` | Ні | `string[]` | Ідентифікатори методів налаштування/автентифікації, які цей provider підтримує без завантаження повного середовища виконання. | -| `envVars` | Ні | `string[]` | Env vars, які загальні поверхні налаштування/статусу можуть перевіряти до завантаження середовища виконання Plugin. | +| Поле | Обов’язкове | Тип | Що воно означає | +| ------------- | ----------- | ---------- | ------------------------------------------------------------------------------------- | +| `id` | Так | `string` | Ідентифікатор provider, який показується під час setup або onboarding. Зберігайте нормалізовані ідентифікатори глобально унікальними. | +| `authMethods` | Ні | `string[]` | Ідентифікатори методів setup/auth, які цей provider підтримує без завантаження повного runtime. | +| `envVars` | Ні | `string[]` | Змінні env, які типові поверхні setup/status можуть перевіряти до завантаження runtime plugin. | ### Поля `setup` -| Поле | Обов’язкове | Тип | Що це означає | +| Поле | Обов’язкове | Тип | Що воно означає | | ------------------ | ----------- | ---------- | ---------------------------------------------------------------------------------------------------- | -| `providers` | Ні | `object[]` | Дескриптори налаштування provider, доступні під час налаштування й онбордингу. | -| `cliBackends` | Ні | `string[]` | Ідентифікатори backend, які використовуються під час налаштування для пошуку спочатку за дескрипторами. Підтримуйте глобальну унікальність нормалізованих ідентифікаторів. | -| `configMigrations` | Ні | `string[]` | Ідентифікатори міграцій конфігурації, що належать поверхні налаштування цього Plugin. | -| `requiresRuntime` | Ні | `boolean` | Чи потребує налаштування виконання `setup-api` після пошуку за дескриптором. | +| `providers` | Ні | `object[]` | Дескриптори setup provider, які показуються під час setup та onboarding. | +| `cliBackends` | Ні | `string[]` | Ідентифікатори backend для етапу setup, які використовуються для пошуку setup за принципом descriptor-first. Зберігайте нормалізовані ідентифікатори глобально унікальними. | +| `configMigrations` | Ні | `string[]` | Ідентифікатори міграцій конфігурації, якими володіє поверхня setup цього plugin. | +| `requiresRuntime` | Ні | `boolean` | Чи потребує setup виконання `setup-api` після пошуку за дескриптором. | ## Довідник `uiHints` -`uiHints` — це мапа від назв полів конфігурації до невеликих підказок для рендерингу. +`uiHints` — це мапа від імен полів конфігурації до невеликих підказок рендерингу. ```json { @@ -367,21 +365,21 @@ OpenClaw зчитує це до завантаження середовища в } ``` -Кожна підказка поля може містити: +Кожна підказка для поля може містити: -| Поле | Тип | Що це означає | +| Поле | Тип | Що воно означає | | ------------- | ---------- | --------------------------------------- | | `label` | `string` | Мітка поля для користувача. | | `help` | `string` | Короткий допоміжний текст. | | `tags` | `string[]` | Необов’язкові теги UI. | | `advanced` | `boolean` | Позначає поле як розширене. | | `sensitive` | `boolean` | Позначає поле як секретне або чутливе. | -| `placeholder` | `string` | Текст-заповнювач для полів форми. | +| `placeholder` | `string` | Текст placeholder для полів форми. | ## Довідник `contracts` -Використовуйте `contracts` лише для статичних метаданих володіння можливостями, які OpenClaw може -зчитувати без імпорту середовища виконання Plugin. +Використовуйте `contracts` лише для статичних метаданих про належність можливостей, які OpenClaw може +читати без імпорту runtime plugin. ```json { @@ -401,22 +399,22 @@ OpenClaw зчитує це до завантаження середовища в Кожен список є необов’язковим: -| Поле | Тип | Що це означає | -| -------------------------------- | ---------- | -------------------------------------------------------------------- | -| `speechProviders` | `string[]` | Ідентифікатори speech provider, якими володіє цей Plugin. | -| `realtimeTranscriptionProviders` | `string[]` | Ідентифікатори provider для realtime transcription, якими володіє цей Plugin. | -| `realtimeVoiceProviders` | `string[]` | Ідентифікатори provider для realtime voice, якими володіє цей Plugin. | -| `mediaUnderstandingProviders` | `string[]` | Ідентифікатори provider для media-understanding, якими володіє цей Plugin. | -| `imageGenerationProviders` | `string[]` | Ідентифікатори provider для image-generation, якими володіє цей Plugin. | -| `videoGenerationProviders` | `string[]` | Ідентифікатори provider для video-generation, якими володіє цей Plugin. | -| `webFetchProviders` | `string[]` | Ідентифікатори provider для web-fetch, якими володіє цей Plugin. | -| `webSearchProviders` | `string[]` | Ідентифікатори provider для web search, якими володіє цей Plugin. | -| `tools` | `string[]` | Назви agent tool, якими володіє цей Plugin, для перевірок контрактів вбудованих компонентів. | +| Поле | Тип | Що воно означає | +| -------------------------------- | ---------- | -------------------------------------------------------------- | +| `speechProviders` | `string[]` | Ідентифікатори speech provider, якими володіє цей plugin. | +| `realtimeTranscriptionProviders` | `string[]` | Ідентифікатори provider для realtime transcription, якими володіє цей plugin. | +| `realtimeVoiceProviders` | `string[]` | Ідентифікатори provider для realtime voice, якими володіє цей plugin. | +| `mediaUnderstandingProviders` | `string[]` | Ідентифікатори provider для media-understanding, якими володіє цей plugin. | +| `imageGenerationProviders` | `string[]` | Ідентифікатори provider для image-generation, якими володіє цей plugin. | +| `videoGenerationProviders` | `string[]` | Ідентифікатори provider для video-generation, якими володіє цей plugin. | +| `webFetchProviders` | `string[]` | Ідентифікатори provider для web-fetch, якими володіє цей plugin. | +| `webSearchProviders` | `string[]` | Ідентифікатори provider для web search, якими володіє цей plugin. | +| `tools` | `string[]` | Назви agent tool, якими володіє цей plugin, для перевірок контрактів вбудованих plugin. | ## Довідник `channelConfigs` -Використовуйте `channelConfigs`, коли Plugin каналу потребує недорогих метаданих конфігурації -до завантаження середовища виконання. +Використовуйте `channelConfigs`, коли plugin channel потребує дешевих метаданих конфігурації +до завантаження runtime. ```json { @@ -436,27 +434,28 @@ OpenClaw зчитує це до завантаження середовища в } }, "label": "Matrix", - "description": "Підключення до homeserver Matrix", + "description": "Matrix homeserver connection", "preferOver": ["matrix-legacy"] } } } ``` -Кожен запис каналу може містити: +Кожен запис channel може містити: -| Поле | Тип | Що це означає | -| ------------- | ------------------------ | -------------------------------------------------------------------------------------------- | -| `schema` | `object` | JSON Schema для `channels.`. Обов’язкова для кожного оголошеного запису конфігурації каналу. | -| `uiHints` | `Record` | Необов’язкові мітки UI/заповнювачі/підказки чутливості для цього розділу конфігурації каналу. | -| `label` | `string` | Мітка каналу, що об’єднується в поверхні вибору та інспектування, коли runtime-метадані ще не готові. | -| `description` | `string` | Короткий опис каналу для поверхонь інспектування та каталогу. | -| `preferOver` | `string[]` | Ідентифікатори застарілих або менш пріоритетних Plugin, які цей канал має випереджати в поверхнях вибору. | +| Поле | Тип | Що воно означає | +| ------------- | ------------------------ | ------------------------------------------------------------------------------------------ | +| `schema` | `object` | JSON Schema для `channels.`. Обов’язкове для кожного оголошеного запису конфігурації channel. | +| `uiHints` | `Record` | Необов’язкові мітки UI/placeholders/підказки щодо чутливості для цього розділу конфігурації channel. | +| `label` | `string` | Мітка channel, що об’єднується з поверхнями picker та inspect, коли метадані runtime ще не готові. | +| `description` | `string` | Короткий опис channel для поверхонь inspect і каталогу. | +| `preferOver` | `string[]` | Ідентифікатори застарілих або менш пріоритетних plugin, які цей channel має випереджати в поверхнях вибору. | ## Довідник `modelSupport` -Використовуйте `modelSupport`, коли OpenClaw має виводити ваш provider Plugin із -скорочених ідентифікаторів моделей, таких як `gpt-5.4` або `claude-sonnet-4.6`, до завантаження середовища виконання Plugin. +Використовуйте `modelSupport`, коли OpenClaw має виводити ваш provider plugin із +скорочених ідентифікаторів моделей на кшталт `gpt-5.4` або `claude-sonnet-4.6` до завантаження +runtime plugin. ```json { @@ -469,75 +468,76 @@ OpenClaw зчитує це до завантаження середовища в OpenClaw застосовує такий пріоритет: -- явні посилання `provider/model` використовують метадані маніфесту `providers`, що описують власника -- `modelPatterns` мають вищий пріоритет, ніж `modelPrefixes` -- якщо збігаються один невбудований Plugin і один вбудований Plugin, перемагає невбудований - Plugin +- явні посилання `provider/model` використовують метадані маніфесту `providers`, що належать відповідному plugin +- `modelPatterns` мають вищий пріоритет за `modelPrefixes` +- якщо збігаються один невбудований plugin і один вбудований plugin, перемагає невбудований + plugin - решта неоднозначностей ігнорується, доки користувач або конфігурація не вкаже provider Поля: -| Поле | Тип | Що це означає | +| Поле | Тип | Що воно означає | | --------------- | ---------- | -------------------------------------------------------------------------------- | -| `modelPrefixes` | `string[]` | Префікси, які зіставляються через `startsWith` зі скороченими ідентифікаторами моделей. | -| `modelPatterns` | `string[]` | Джерела regex, які зіставляються зі скороченими ідентифікаторами моделей після видалення суфікса профілю. | +| `modelPrefixes` | `string[]` | Префікси, що зіставляються через `startsWith` зі скороченими ідентифікаторами моделей. | +| `modelPatterns` | `string[]` | Джерела regex, що зіставляються зі скороченими ідентифікаторами моделей після видалення суфікса профілю. | -Застарілі ключі можливостей верхнього рівня позначені як застарілі. Використовуйте `openclaw doctor --fix`, щоб +Застарілі ключі можливостей верхнього рівня не рекомендуються до використання. Використовуйте `openclaw doctor --fix`, щоб перемістити `speechProviders`, `realtimeTranscriptionProviders`, `realtimeVoiceProviders`, `mediaUnderstandingProviders`, `imageGenerationProviders`, `videoGenerationProviders`, `webFetchProviders` і `webSearchProviders` до `contracts`; звичайне -завантаження маніфесту більше не розглядає ці поля верхнього рівня як -володіння можливостями. +завантаження маніфесту більше не трактує ці поля верхнього рівня як +належність можливостей. -## Маніфест і `package.json` +## Маніфест проти package.json Ці два файли виконують різні завдання: -| Файл | Для чого використовується | -| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| `openclaw.plugin.json` | Виявлення, валідація конфігурації, метадані варіантів автентифікації та підказки UI, які мають існувати до запуску коду Plugin | -| `package.json` | Метадані npm, встановлення залежностей і блок `openclaw`, який використовується для точок входу, обмежень встановлення, налаштування або метаданих каталогу | +| Файл | Для чого його використовувати | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| `openclaw.plugin.json` | Виявлення, валідація конфігурації, метадані вибору auth і підказки UI, які мають існувати до запуску коду plugin | +| `package.json` | Метадані npm, встановлення залежностей і блок `openclaw`, що використовується для entrypoint, обмежень встановлення, setup або метаданих каталогу | -Якщо ви не впевнені, куди належить певний фрагмент метаданих, використовуйте таке правило: +Якщо ви не впевнені, куди має належати певний фрагмент метаданих, використовуйте таке правило: -- якщо OpenClaw має знати про це до завантаження коду Plugin, помістіть це в `openclaw.plugin.json` -- якщо це стосується пакування, файлів входу або поведінки встановлення npm, помістіть це в `package.json` +- якщо OpenClaw має знати це до завантаження коду plugin, помістіть це в `openclaw.plugin.json` +- якщо це стосується пакування, файлів entrypoint або поведінки встановлення npm, помістіть це в `package.json` -### Поля `package.json`, які впливають на виявлення +### Поля package.json, які впливають на виявлення -Частина метаданих Plugin до запуску середовища виконання навмисно зберігається в `package.json` у блоці +Деякі метадані plugin до запуску runtime навмисно зберігаються в `package.json` у блоці `openclaw`, а не в `openclaw.plugin.json`. Важливі приклади: -| Поле | Що це означає | -| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -| `openclaw.extensions` | Оголошує власні точки входу Plugin. | -| `openclaw.setupEntry` | Легка точка входу лише для налаштування, що використовується під час онбордингу, відкладеного запуску каналу та discovery стану channel status/SecretRef лише для читання. | -| `openclaw.channel` | Недорогі метадані каталогу каналу, такі як мітки, шляхи до документації, псевдоніми та текст для вибору. | -| `openclaw.channel.configuredState` | Недорогі метадані перевірки configured-state, які можуть відповісти на запитання «чи вже існує налаштування лише через env?» без завантаження повного runtime каналу. | -| `openclaw.channel.persistedAuthState` | Недорогі метадані перевірки persisted-auth, які можуть відповісти на запитання «чи вже виконано вхід хоч десь?» без завантаження повного runtime каналу. | -| `openclaw.install.npmSpec` / `openclaw.install.localPath` | Підказки для встановлення/оновлення вбудованих і зовнішньо опублікованих Plugin. | -| `openclaw.install.defaultChoice` | Бажаний шлях встановлення, коли доступно кілька джерел встановлення. | -| `openclaw.install.minHostVersion` | Мінімальна підтримувана версія хоста OpenClaw із нижньою межею semver, наприклад `>=2026.3.22`. | -| `openclaw.install.allowInvalidConfigRecovery` | Дозволяє вузький шлях відновлення через перевстановлення вбудованого Plugin, коли конфігурація недійсна. | -| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | Дозволяє поверхням каналу лише для налаштування завантажуватися до повного Plugin каналу під час запуску. | +| Поле | Що воно означає | +| ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| `openclaw.extensions` | Оголошує власні entrypoint plugin. | +| `openclaw.setupEntry` | Легкий entrypoint лише для setup, що використовується під час onboarding, відкладеного запуску channel і discovery статусу/SecretRef лише для читання. | +| `openclaw.channel` | Дешеві метадані каталогу channel, як-от мітки, шляхи до документації, alias і текст для вибору. | +| `openclaw.channel.configuredState` | Легкі метадані перевірки configured-state, які можуть відповісти на питання «чи вже існує налаштування лише через env?» без завантаження повного runtime channel. | +| `openclaw.channel.persistedAuthState` | Легкі метадані перевірки persisted-auth, які можуть відповісти на питання «чи вже виконано вхід кудись?» без завантаження повного runtime channel. | +| `openclaw.install.npmSpec` / `openclaw.install.localPath` | Підказки встановлення/оновлення для вбудованих і зовнішньо опублікованих plugin. | +| `openclaw.install.defaultChoice` | Бажаний шлях встановлення, коли доступно кілька джерел встановлення. | +| `openclaw.install.minHostVersion` | Мінімальна підтримувана версія хоста OpenClaw із використанням нижньої межі semver, наприклад `>=2026.3.22`. | +| `openclaw.install.allowInvalidConfigRecovery` | Дозволяє вузький шлях відновлення перевстановлення вбудованого plugin, коли конфігурація невалідна. | +| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | Дозволяє поверхням channel лише для setup завантажуватися до повного plugin channel під час запуску. | -`openclaw.install.minHostVersion` примусово перевіряється під час встановлення та -завантаження реєстру маніфестів. Недійсні значення відхиляються; новіші, але дійсні значення пропускають -Plugin на старіших хостах. +`openclaw.install.minHostVersion` застосовується під час встановлення та +завантаження реєстру маніфестів. Невалідні значення відхиляються; новіші, але валідні значення +пропускають plugin на старіших хостах. -Plugin каналу мають надавати `openclaw.setupEntry`, коли статус, список каналів -або сканування SecretRef повинні визначати налаштовані облікові записи без завантаження повного -середовища виконання. Точка входу setup має надавати метадані каналу разом із безпечними для налаштування адаптерами конфігурації, -статусу та секретів; мережеві клієнти, слухачі Gateway і transport runtime слід тримати в основній точці входу extension. +Plugin channel мають надавати `openclaw.setupEntry`, коли status, список channel +або сканування SecretRef мають визначати налаштовані облікові записи без завантаження повного +runtime. Entrypoint setup має відкривати метадані channel разом із безпечними для setup адаптерами +конфігурації, status і secrets; зберігайте мережеві клієнти, слухачі Gateway і transport runtime +в основному entrypoint extension. -`openclaw.install.allowInvalidConfigRecovery` навмисно є вузьким механізмом. Воно -не робить довільні зламані конфігурації придатними до встановлення. Сьогодні воно лише дозволяє потокам встановлення -відновлюватися після певних застарілих збоїв оновлення вбудованого Plugin, наприклад -відсутнього шляху до вбудованого Plugin або застарілого запису `channels.` для того самого -вбудованого Plugin. Непов’язані помилки конфігурації, як і раніше, блокують встановлення і спрямовують операторів +`openclaw.install.allowInvalidConfigRecovery` навмисно має вузьке застосування. Воно +не робить довільно зламані конфігурації придатними для встановлення. Наразі воно лише дозволяє потокам встановлення +відновлюватися після конкретних застарілих збоїв оновлення вбудованого plugin, наприклад +відсутнього шляху до вбудованого plugin або застарілого запису `channels.` для того самого +вбудованого plugin. Непов’язані помилки конфігурації все одно блокують встановлення і спрямовують операторів до `openclaw doctor --fix`. `openclaw.channel.persistedAuthState` — це метадані пакета для крихітного модуля перевірки: @@ -556,12 +556,12 @@ Plugin каналу мають надавати `openclaw.setupEntry`, коли } ``` -Використовуйте це, коли потоки налаштування, doctor або configured-state потребують недорогої -перевірки автентифікації у форматі «так/ні» до завантаження повного Plugin каналу. Цільовий експорт має бути невеликою -функцією, яка лише зчитує збережений стан; не спрямовуйте її через повний barrel середовища виконання каналу. +Використовуйте це, коли потокам setup, doctor або configured-state потрібна дешева +перевірка auth у форматі так/ні до завантаження повного plugin channel. Цільовий export має бути +невеликою функцією, що читає лише збережений стан; не спрямовуйте її через повний barrel runtime channel. -`openclaw.channel.configuredState` використовує таку саму форму для недорогих перевірок -configured-state лише через env: +`openclaw.channel.configuredState` має таку саму форму для дешевих перевірок +configured state лише через env: ```json { @@ -577,75 +577,92 @@ configured-state лише через env: } ``` -Використовуйте це, коли канал може відповісти щодо configured-state на основі env або інших малих -нерuntime-входів. Якщо перевірка потребує повного розв’язання конфігурації або справжнього -середовища виконання каналу, залишайте цю логіку в хуку Plugin `config.hasConfiguredState`. +Використовуйте це, коли channel може визначати configured state через env або інші малі +вхідні дані, не пов’язані з runtime. Якщо перевірка потребує повного розв’язання конфігурації або реального +runtime channel, залиште цю логіку в hook `config.hasConfiguredState` plugin. + +## Пріоритет виявлення (дубльовані ідентифікатори plugin) + +OpenClaw виявляє plugin із кількох коренів (вбудовані, глобальне встановлення, робочий простір, явні шляхи, вибрані в конфігурації). Якщо два виявлені plugin мають однаковий `id`, зберігається лише маніфест із **найвищим пріоритетом**; дублікати з нижчим пріоритетом відкидаються замість паралельного завантаження. + +Пріоритет від найвищого до найнижчого: + +1. **Вибраний у конфігурації** — шлях, явно зафіксований у `plugins.entries.` +2. **Вбудований** — plugin, що постачаються з OpenClaw +3. **Глобальне встановлення** — plugin, встановлені в глобальний корінь plugin OpenClaw +4. **Робочий простір** — plugin, виявлені відносно поточного робочого простору + +Наслідки: + +- Розгалужена або застаріла копія вбудованого plugin, що лежить у робочому просторі, не затьмарить вбудовану збірку. +- Щоб справді перевизначити вбудований plugin локальним, зафіксуйте його через `plugins.entries.`, щоб він переміг за пріоритетом, а не покладайтеся на виявлення в робочому просторі. +- Відкидання дублікатів журналюється, щоб Doctor і діагностика запуску могли вказати на відкинуту копію. ## Вимоги до JSON Schema -- **Кожен Plugin повинен постачатися з JSON Schema**, навіть якщо він не приймає конфігурацію. -- Порожня схема допустима (наприклад, `{ "type": "object", "additionalProperties": false }`). -- Схеми перевіряються під час читання/запису конфігурації, а не під час виконання. +- **Кожен plugin повинен постачатися з JSON Schema**, навіть якщо він не приймає конфігурацію. +- Порожня схема припустима (наприклад, `{ "type": "object", "additionalProperties": false }`). +- Схеми проходять валідацію під час читання/запису конфігурації, а не під час runtime. ## Поведінка валідації - Невідомі ключі `channels.*` є **помилками**, якщо тільки ідентифікатор channel не оголошено - маніфестом Plugin. + в маніфесті plugin. - `plugins.entries.`, `plugins.allow`, `plugins.deny` і `plugins.slots.*` - мають посилатися на **виявлювані** ідентифікатори Plugin. Невідомі ідентифікатори є **помилками**. -- Якщо Plugin встановлено, але він має зламаний або відсутній маніфест чи схему, - валідація завершується невдачею, а Doctor повідомляє про помилку Plugin. -- Якщо конфігурація Plugin існує, але Plugin **вимкнено**, конфігурація зберігається і - у Doctor + журналах показується **попередження**. + мають посилатися на **такі ідентифікатори plugin, які можна виявити**. Невідомі ідентифікатори є **помилками**. +- Якщо plugin встановлено, але він має зламаний або відсутній маніфест чи схему, + валідація завершується з помилкою, а Doctor повідомляє про помилку plugin. +- Якщо конфігурація plugin існує, але plugin **вимкнено**, конфігурація зберігається, і + у Doctor + журналах з’являється **попередження**. -Повну схему `plugins.*` дивіться в [Довіднику конфігурації](/uk/gateway/configuration). +Повну схему `plugins.*` див. у [Довідник конфігурації](/uk/gateway/configuration). ## Примітки -- Маніфест **обов’язковий для власних Plugin OpenClaw**, включно із завантаженням з локальної файлової системи. -- Середовище виконання, як і раніше, завантажує модуль Plugin окремо; маніфест використовується лише для +- Маніфест **обов’язковий для власних Plugin OpenClaw**, включно із завантаженнями з локальної файлової системи. +- Runtime і далі окремо завантажує модуль plugin; маніфест використовується лише для виявлення + валідації. -- Власні маніфести розбираються за допомогою JSON5, тому коментарі, кінцеві коми та - ключі без лапок приймаються, якщо кінцеве значення все ще є об’єктом. -- Завантажувач маніфесту зчитує лише задокументовані поля маніфесту. Уникайте додавання - тут власних ключів верхнього рівня. -- `providerAuthEnvVars` — це недорогий шлях метаданих для перевірок автентифікації, валідації - env-marker і подібних поверхонь автентифікації provider, які не повинні запускати - середовище виконання Plugin лише для перевірки назв env. -- `providerAuthAliases` дозволяє варіантам provider повторно використовувати env vars - автентифікації іншого provider, профілі автентифікації, автентифікацію на основі конфігурації та варіант - онбордингу API key без жорсткого кодування цього зв’язку в ядрі. -- `providerEndpoints` дозволяє Plugin provider володіти простими метаданими зіставлення - хостів/baseUrl кінцевих точок. Використовуйте це лише для класів кінцевих точок, які ядро вже підтримує; - поведінка середовища виконання, як і раніше, належить Plugin. -- `syntheticAuthRefs` — це недорогий шлях метаданих для синтетичних - хуків автентифікації, що належать provider і мають бути видимими для холодного виявлення моделей до того, як з’явиться - runtime-реєстр. Вказуйте лише ті посилання, чий runtime provider або CLI backend справді - реалізує `resolveSyntheticAuth`. -- `nonSecretAuthMarkers` — це недорогий шлях метаданих для значень-заповнювачів - API key, що належать вбудованому Plugin, таких як локальні, OAuth або маркери ambient credential. - Ядро розглядає їх як несекретні для відображення автентифікації та аудиту секретів без - жорсткого кодування provider-власника. -- `channelEnvVars` — це недорогий шлях метаданих для резервного використання shell-env, підказок - налаштування та подібних поверхонь каналу, які не повинні запускати середовище виконання Plugin +- Власні маніфести парсяться за допомогою JSON5, тому коментарі, кінцеві коми та + ключі без лапок допускаються, якщо фінальне значення все ще є об’єктом. +- Завантажувач маніфесту читає лише задокументовані поля маніфесту. Уникайте додавання + власних ключів верхнього рівня тут. +- `providerAuthEnvVars` — це дешевий шлях метаданих для перевірок auth, валідації + env-marker і подібних поверхонь auth provider, які не повинні запускати runtime plugin лише для перевірки назв env. -- `providerAuthChoices` — це недорогий шлях метаданих для засобів вибору варіантів автентифікації, - визначення `--auth-choice`, зіставлення пріоритетного provider і простої реєстрації - CLI-прапорців онбордингу до завантаження середовища виконання provider. Для метаданих - runtime wizard, яким потрібен код provider, див. - [Хуки середовища виконання provider](/uk/plugins/architecture#provider-runtime-hooks). -- Виняткові типи Plugin вибираються через `plugins.slots.*`. +- `providerAuthAliases` дає змогу варіантам provider повторно використовувати auth + env vars, профілі auth, auth на основі конфігурації та варіант onboarding API key іншого provider + без жорсткого кодування цього зв’язку в core. +- `providerEndpoints` дає plugin provider змогу володіти простими метаданими зіставлення + host/baseUrl endpoint. Використовуйте це лише для класів endpoint, які core вже підтримує; + поведінка runtime все одно належить plugin. +- `syntheticAuthRefs` — це дешевий шлях метаданих для синтетичних hook auth, що належать provider + і мають бути видимими для холодного виявлення моделей до появи реєстру runtime. + Перелічуйте лише ті посилання, чий runtime provider або backend CLI справді + реалізує `resolveSyntheticAuth`. +- `nonSecretAuthMarkers` — це дешевий шлях метаданих для значень-заповнювачів API key, що належать + вбудованому plugin, як-от маркери локальних, OAuth або ambient credential. + Core трактує їх як не секретні для відображення auth і аудиту секретів без + жорсткого кодування власника provider. +- `channelEnvVars` — це дешевий шлях метаданих для shell-env fallback, запитів setup + і подібних поверхонь channel, які не повинні запускати runtime plugin + лише для перевірки назв env. +- `providerAuthChoices` — це дешевий шлях метаданих для picker вибору auth, + розв’язання `--auth-choice`, мапінгу бажаного provider і простої реєстрації + прапорців CLI для onboarding до завантаження runtime provider. Метадані wizard runtime, + які потребують коду provider, див. у + [Хуки runtime provider](/uk/plugins/architecture#provider-runtime-hooks). +- Ексклюзивні види plugin вибираються через `plugins.slots.*`. - `kind: "memory"` вибирається через `plugins.slots.memory`. - `kind: "context-engine"` вибирається через `plugins.slots.contextEngine` - (типове значення: вбудований `legacy`). -- `channels`, `providers`, `cliBackends` і `skills` можна не вказувати, якщо - Plugin їх не потребує. -- Якщо ваш Plugin залежить від native module, задокументуйте кроки збирання і всі + (типово: вбудований `legacy`). +- `channels`, `providers`, `cliBackends` і `skills` можна не вказувати, якщо plugin + їх не потребує. +- Якщо ваш plugin залежить від власних модулів, задокументуйте кроки збірки та всі вимоги до allowlist менеджера пакетів (наприклад, pnpm `allow-build-scripts` - `pnpm rebuild `). ## Пов’язане -- [Створення Plugins](/uk/plugins/building-plugins) — початок роботи з Plugins +- [Створення Plugins](/uk/plugins/building-plugins) — початок роботи з plugin - [Архітектура Plugin](/uk/plugins/architecture) — внутрішня архітектура - [Огляд SDK](/uk/plugins/sdk-overview) — довідник SDK Plugin diff --git a/docs/uk/plugins/message-presentation.md b/docs/uk/plugins/message-presentation.md new file mode 100644 index 000000000..9e6d7d0f8 --- /dev/null +++ b/docs/uk/plugins/message-presentation.md @@ -0,0 +1,344 @@ +--- +read_when: + - Додавання або змінення рендерингу картки повідомлення, кнопки чи списку вибору + - Створення plugin-а каналу, який підтримує розширені вихідні повідомлення + - Змінення представлення інструментів повідомлень або можливостей доставлення + - Налагодження регресій рендерингу карток/блоків/компонентів, специфічних для провайдера +summary: Семантичні картки повідомлень, кнопки, списки вибору, резервний текст і підказки щодо доставлення для plugin-ів каналів +title: Представлення повідомлення +x-i18n: + generated_at: "2026-04-21T20:37:39Z" + model: gpt-5.4 + provider: openai + source_hash: a6913b2b4331598a1396d19a572fba1fffde6cb9a6efa2192f30fe12404eb48d + source_path: plugins/message-presentation.md + workflow: 15 +--- + +# Представлення повідомлень + +Представлення повідомлень — це спільний контракт OpenClaw для розширеного інтерфейсу вихідного чату. +Він дає змогу агентам, командам CLI, потокам погодження та plugin-ам описати +намір повідомлення один раз, тоді як кожен plugin каналу рендерить найкращу +нативну форму, яку він підтримує. + +Використовуйте представлення для переносного інтерфейсу повідомлень: + +- текстові секції +- короткий контекстний текст/текст нижнього колонтитула +- роздільники +- кнопки +- меню вибору +- заголовок картки та тон + +Не додавайте нові нативні для провайдера поля, такі як Discord `components`, Slack +`blocks`, Telegram `buttons`, Teams `card` або Feishu `card`, до спільного +інструмента повідомлень. Це результати рендерингу, якими володіє plugin каналу. + +## Контракт + +Автори plugin-ів імпортують публічний контракт із: + +```ts +import type { + MessagePresentation, + ReplyPayloadDelivery, +} from "openclaw/plugin-sdk/interactive-runtime"; +``` + +Форма: + +```ts +type MessagePresentation = { + title?: string; + tone?: "neutral" | "info" | "success" | "warning" | "danger"; + blocks: MessagePresentationBlock[]; +}; + +type MessagePresentationBlock = + | { type: "text"; text: string } + | { type: "context"; text: string } + | { type: "divider" } + | { type: "buttons"; buttons: MessagePresentationButton[] } + | { type: "select"; placeholder?: string; options: MessagePresentationOption[] }; + +type MessagePresentationButton = { + label: string; + value?: string; + url?: string; + style?: "primary" | "secondary" | "success" | "danger"; +}; + +type MessagePresentationOption = { + label: string; + value: string; +}; + +type ReplyPayloadDelivery = { + pin?: + | boolean + | { + enabled: boolean; + notify?: boolean; + required?: boolean; + }; +}; +``` + +Семантика кнопок: + +- `value` — це значення дії застосунку, яке спрямовується назад через + наявний шлях взаємодії каналу, коли канал підтримує натискні елементи керування. +- `url` — це кнопка-посилання. Вона може існувати без `value`. +- `label` є обов’язковим і також використовується в текстовому резервному варіанті. +- `style` є рекомендаційним. Рендерери мають зіставляти непідтримувані стилі з безпечним + значенням за замовчуванням, а не завершувати надсилання з помилкою. + +Семантика меню вибору: + +- `options[].value` — це вибране значення застосунку. +- `placeholder` є рекомендаційним і може ігноруватися каналами без нативної + підтримки вибору. +- Якщо канал не підтримує меню вибору, резервний текст перелічує мітки. + +## Приклади продюсера + +Проста картка: + +```json +{ + "title": "Deploy approval", + "tone": "warning", + "blocks": [ + { "type": "text", "text": "Canary is ready to promote." }, + { "type": "context", "text": "Build 1234, staging passed." }, + { + "type": "buttons", + "buttons": [ + { "label": "Approve", "value": "deploy:approve", "style": "success" }, + { "label": "Decline", "value": "deploy:decline", "style": "danger" } + ] + } + ] +} +``` + +Кнопка-посилання лише з URL: + +```json +{ + "blocks": [ + { "type": "text", "text": "Release notes are ready." }, + { + "type": "buttons", + "buttons": [{ "label": "Open notes", "url": "https://example.com/release" }] + } + ] +} +``` + +Меню вибору: + +```json +{ + "title": "Choose environment", + "blocks": [ + { + "type": "select", + "placeholder": "Environment", + "options": [ + { "label": "Canary", "value": "env:canary" }, + { "label": "Production", "value": "env:prod" } + ] + } + ] +} +``` + +Надсилання через CLI: + +```bash +openclaw message send --channel slack \ + --target channel:C123 \ + --message "Deploy approval" \ + --presentation '{"title":"Deploy approval","tone":"warning","blocks":[{"type":"text","text":"Canary is ready."},{"type":"buttons","buttons":[{"label":"Approve","value":"deploy:approve","style":"success"},{"label":"Decline","value":"deploy:decline","style":"danger"}]}]}' +``` + +Закріплене доставлення: + +```bash +openclaw message send --channel telegram \ + --target -1001234567890 \ + --message "Topic opened" \ + --pin +``` + +Закріплене доставлення з явним JSON: + +```json +{ + "pin": { + "enabled": true, + "notify": true, + "required": false + } +} +``` + +## Контракт рендерера + +Plugin-и каналів оголошують підтримку рендерингу у своєму вихідному адаптері: + +```ts +const adapter: ChannelOutboundAdapter = { + deliveryMode: "direct", + presentationCapabilities: { + supported: true, + buttons: true, + selects: true, + context: true, + divider: true, + }, + deliveryCapabilities: { + pin: true, + }, + renderPresentation({ payload, presentation, ctx }) { + return renderNativePayload(payload, presentation, ctx); + }, + async pinDeliveredMessage({ target, messageId, pin }) { + await pinNativeMessage(target, messageId, { notify: pin.notify === true }); + }, +}; +``` + +Поля можливостей навмисно прості булеві. Вони описують, що саме +рендерер може зробити інтерактивним, а не кожне обмеження нативної платформи. Рендерери все одно +володіють платформоспецифічними обмеженнями, такими як максимальна кількість кнопок, кількість блоків і +розмір картки. + +## Основний потік рендерингу + +Коли `ReplyPayload` або дія повідомлення містить `presentation`, ядро: + +1. Нормалізує payload представлення. +2. Визначає вихідний адаптер цільового каналу. +3. Зчитує `presentationCapabilities`. +4. Викликає `renderPresentation`, коли адаптер може рендерити payload. +5. Повертається до консервативного тексту, якщо адаптер відсутній або не може рендерити. +6. Надсилає отриманий payload звичайним шляхом доставлення каналу. +7. Застосовує метадані доставлення, такі як `delivery.pin`, після першого успішно + надісланого повідомлення. + +Ядро володіє поведінкою резервного варіанта, щоб продюсери могли залишатися незалежними від каналів. Channel +plugin-и володіють нативним рендерингом і обробленням взаємодій. + +## Правила деградації + +Представлення має бути безпечним для надсилання в обмежених каналах. + +Резервний текст містить: + +- `title` як перший рядок +- блоки `text` як звичайні абзаци +- блоки `context` як компактні контекстні рядки +- блоки `divider` як візуальний роздільник +- мітки кнопок, включно з URL для кнопок-посилань +- мітки варіантів вибору + +Непідтримувані нативні елементи керування мають деградувати, а не спричиняти збій усього надсилання. +Приклади: + +- Telegram із вимкненими вбудованими кнопками надсилає текстовий резервний варіант. +- Канал без підтримки меню вибору перелічує варіанти вибору як текст. +- Кнопка лише з URL стає або нативною кнопкою-посиланням, або резервним рядком URL. +- Необов’язкові збої закріплення не призводять до збою доставленого повідомлення. + +Головний виняток — `delivery.pin.required: true`; якщо закріплення запитується як +обов’язкове і канал не може закріпити надіслане повідомлення, доставлення повідомляє про збій. + +## Відображення провайдерів + +Поточні вбудовані рендерери: + +| Канал | Ціль нативного рендерингу | Примітки | +| --------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| Discord | Components і контейнери компонентів | Зберігає застаріле `channelData.discord.components` для наявних продюсерів payload, нативних для провайдера, але нові спільні надсилання мають використовувати `presentation`. | +| Slack | Block Kit | Зберігає застаріле `channelData.slack.blocks` для наявних продюсерів payload, нативних для провайдера, але нові спільні надсилання мають використовувати `presentation`. | +| Telegram | Текст плюс вбудовані клавіатури | Кнопки/меню вибору вимагають можливості вбудованих кнопок для цільової поверхні; інакше використовується текстовий резервний варіант. | +| Mattermost | Текст плюс інтерактивні props | Інші блоки деградують до тексту. | +| Microsoft Teams | Adaptive Cards | Простий текст `message` включається разом із карткою, коли надано обидва. | +| Feishu | Інтерактивні картки | Заголовок картки може використовувати `title`; тіло уникає дублювання цього заголовка. | +| Прості канали | Текстовий резервний варіант | Канали без рендерера все одно отримують читабельний вивід. | + +Сумісність із payload, нативними для провайдера, є перехідною можливістю для наявних +продюсерів відповідей. Це не причина додавати нові спільні нативні поля. + +## Presentation проти InteractiveReply + +`InteractiveReply` — це старіша внутрішня підмножина, яка використовується засобами погодження та взаємодії. Вона підтримує: + +- текст +- кнопки +- меню вибору + +`MessagePresentation` — це канонічний спільний контракт надсилання. Він додає: + +- заголовок +- тон +- контекст +- роздільник +- кнопки лише з URL +- загальні метадані доставлення через `ReplyPayload.delivery` + +Використовуйте допоміжні функції з `openclaw/plugin-sdk/interactive-runtime` під час мосту зі старішим +кодом: + +```ts +import { + interactiveReplyToPresentation, + normalizeMessagePresentation, + presentationToInteractiveReply, + renderMessagePresentationFallbackText, +} from "openclaw/plugin-sdk/interactive-runtime"; +``` + +Новий код має безпосередньо приймати або створювати `MessagePresentation`. + +## Закріплення доставлення + +Закріплення — це поведінка доставлення, а не представлення. Використовуйте `delivery.pin` замість +нативних для провайдера полів, таких як `channelData.telegram.pin`. + +Семантика: + +- `pin: true` закріплює перше успішно доставлене повідомлення. +- `pin.notify` за замовчуванням дорівнює `false`. +- `pin.required` за замовчуванням дорівнює `false`. +- Необов’язкові збої закріплення деградують і залишають надіслане повідомлення недоторканим. +- Обов’язкові збої закріплення призводять до збою доставлення. +- Фрагментовані повідомлення закріплюють перший доставлений фрагмент, а не хвостовий. + +Ручні дії повідомлень `pin`, `unpin` і `pins` усе ще існують для наявних +повідомлень, де провайдер підтримує ці операції. + +## Контрольний список автора plugin-а + +- Оголосіть `presentation` з `describeMessageTool(...)`, коли канал може + рендерити або безпечно деградувати семантичне представлення. +- Додайте `presentationCapabilities` до runtime вихідного адаптера. +- Реалізуйте `renderPresentation` у runtime коді, а не в control-plane коді + налаштування plugin-а. +- Не допускайте потрапляння нативних бібліотек інтерфейсу в гарячі шляхи налаштування/каталогу. +- Зберігайте платформні обмеження в рендерері та тестах. +- Додайте резервні тести для непідтримуваних кнопок, меню вибору, кнопок URL, дублювання title/text і змішаних надсилань `message` плюс `presentation`. +- Додайте підтримку закріплення доставлення через `deliveryCapabilities.pin` і + `pinDeliveredMessage` лише тоді, коли провайдер може закріпити id надісланого повідомлення. +- Не відкривайте нові нативні для провайдера поля card/block/component/button через + спільну схему дій повідомлень. + +## Пов’язана документація + +- [Message CLI](/cli/message) +- [Огляд Plugin SDK](/uk/plugins/sdk-overview) +- [Архітектура plugin-ів](/uk/plugins/architecture#message-tool-schemas) +- [План рефакторингу представлення каналів](/uk/plan/ui-channels) diff --git a/docs/uk/plugins/sdk-overview.md b/docs/uk/plugins/sdk-overview.md index 4618ace6a..06dab8eee 100644 --- a/docs/uk/plugins/sdk-overview.md +++ b/docs/uk/plugins/sdk-overview.md @@ -1,16 +1,16 @@ --- read_when: - - Вам потрібно знати, з якого підшляху SDK імпортувати - - Вам потрібен довідник для всіх методів реєстрації в OpenClawPluginApi - - Ви шукаєте конкретний експорт SDK + - Вам потрібно знати, з якого підшляху SDK імпортувати. + - Вам потрібен довідник з усіх методів реєстрації в OpenClawPluginApi. + - Ви шукаєте конкретний експорт SDK. sidebarTitle: SDK Overview summary: Мапа імпорту, довідник API реєстрації та архітектура SDK title: Огляд Plugin SDK x-i18n: - generated_at: "2026-04-21T04:19:31Z" + generated_at: "2026-04-21T20:37:39Z" model: gpt-5.4 provider: openai - source_hash: 4561c074bb45529cd94d9d23ce7820b668cbc4ff6317230fdd5a5f27c5f14c67 + source_hash: 16ef34e4ad4550967d06ea6bd94b3400431c0fb536bf267cc4e8a09ec9483695 source_path: plugins/sdk-overview.md workflow: 15 --- @@ -18,16 +18,16 @@ x-i18n: # Огляд Plugin SDK Plugin SDK — це типізований контракт між plugin-ами та ядром. Ця сторінка є -довідником щодо **що імпортувати** і **що можна реєструвати**. +довідником з **того, що імпортувати**, і **того, що можна зареєструвати**. - **Шукаєте практичний посібник?** - - Перший plugin? Почніть із [Початок роботи](/uk/plugins/building-plugins) + **Шукаєте покроковий посібник?** + - Перший plugin? Почніть із [Getting Started](/uk/plugins/building-plugins) - Channel plugin? Див. [Channel Plugins](/uk/plugins/sdk-channel-plugins) - Provider plugin? Див. [Provider Plugins](/uk/plugins/sdk-provider-plugins) -## Угода щодо імпорту +## Правило імпорту Завжди імпортуйте з конкретного підшляху: @@ -36,21 +36,22 @@ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; ``` -Кожен підшлях є невеликим, самодостатнім модулем. Це пришвидшує запуск і +Кожен підшлях — це невеликий самодостатній модуль. Це пришвидшує запуск і запобігає проблемам із циклічними залежностями. Для специфічних для channel -допоміжних засобів entry/build надавайте перевагу `openclaw/plugin-sdk/channel-core`; залишайте `openclaw/plugin-sdk/core` для +допоміжних засобів entry/build віддавайте перевагу `openclaw/plugin-sdk/channel-core`; залишайте `openclaw/plugin-sdk/core` для ширшої парасолькової поверхні та спільних допоміжних засобів, таких як `buildChannelConfigSchema`. -Не додавайте та не використовуйте provider-іменовані зручні seams, такі як +Не додавайте і не використовуйте зручні шари з назвами provider-ів, такі як `openclaw/plugin-sdk/slack`, `openclaw/plugin-sdk/discord`, `openclaw/plugin-sdk/signal`, `openclaw/plugin-sdk/whatsapp`, або -допоміжні seams із брендуванням channel. Вбудовані plugin-и мають компонувати загальні -підшляхи SDK усередині власних barrel-файлів `api.ts` або `runtime-api.ts`, а ядро -має або використовувати ці локальні barrel-файли plugin-ів, або додавати вузький загальний контракт SDK, коли потреба справді є між channel-ами. +допоміжні шари, брендові для channel. Вбудовані plugin-и мають компонувати узагальнені +підшляхи SDK у власних barrel-файлах `api.ts` або `runtime-api.ts`, а ядро +має або використовувати ці локальні для plugin-а barrel-файли, або додавати вузький узагальнений контракт SDK, +коли така потреба справді є між channel-ами. Згенерована мапа експорту все ще містить невеликий набір допоміжних -seams для вбудованих plugin-ів, таких як `plugin-sdk/feishu`, `plugin-sdk/feishu-setup`, +шарів для вбудованих plugin-ів, таких як `plugin-sdk/feishu`, `plugin-sdk/feishu-setup`, `plugin-sdk/zalo`, `plugin-sdk/zalo-setup` і `plugin-sdk/matrix*`. Ці підшляхи існують лише для підтримки та сумісності вбудованих plugin-ів; вони навмисно не включені до загальної таблиці нижче й не є рекомендованим @@ -59,16 +60,16 @@ seams для вбудованих plugin-ів, таких як `plugin-sdk/feish ## Довідник підшляхів Найуживаніші підшляхи, згруповані за призначенням. Згенерований повний список із -200+ підшляхів міститься в `scripts/lib/plugin-sdk-entrypoints.json`. +понад 200 підшляхів міститься в `scripts/lib/plugin-sdk-entrypoints.json`. Зарезервовані допоміжні підшляхи для вбудованих plugin-ів усе ще з’являються в цьому згенерованому списку. -Розглядайте їх як поверхні деталей реалізації/сумісності, якщо тільки сторінка документації -явно не просуває одну з них як публічну. +Розглядайте їх як поверхні деталей реалізації/сумісності, якщо лише сторінка документації +явно не позначає одну з них як публічну. -### Plugin entry +### Entry plugin-а -| Subpath | Ключові експорти | -| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| Підшлях | Ключові експорти | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `plugin-sdk/plugin-entry` | `definePluginEntry` | | `plugin-sdk/core` | `defineChannelPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase`, `defineSetupPluginEntry`, `buildChannelConfigSchema` | | `plugin-sdk/config-schema` | `OpenClawSchema` | @@ -76,60 +77,60 @@ seams для вбудованих plugin-ів, таких як `plugin-sdk/feish - | Subpath | Ключові експорти | + | Підшлях | Ключові експорти | | --- | --- | | `plugin-sdk/channel-core` | `defineChannelPluginEntry`, `defineSetupPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase` | | `plugin-sdk/config-schema` | Експорт кореневої Zod-схеми `openclaw.json` (`OpenClawSchema`) | | `plugin-sdk/channel-setup` | `createOptionalChannelSetupSurface`, `createOptionalChannelSetupAdapter`, `createOptionalChannelSetupWizard`, а також `DEFAULT_ACCOUNT_ID`, `createTopLevelChannelDmPolicy`, `setSetupChannelEnabled`, `splitSetupEntries` | - | `plugin-sdk/setup` | Спільні допоміжні засоби майстра налаштування, prompts allowlist і будівники статусу налаштування | + | `plugin-sdk/setup` | Спільні допоміжні засоби майстра налаштування, підказки allowlist, збирачі статусу налаштування | | `plugin-sdk/setup-runtime` | `createPatchedAccountSetupAdapter`, `createEnvPatchedAccountSetupAdapter`, `createSetupInputPresenceValidator`, `noteChannelLookupFailure`, `noteChannelLookupSummary`, `promptResolvedAllowFrom`, `splitSetupEntries`, `createAllowlistSetupWizardProxy`, `createDelegatedSetupWizardProxy` | | `plugin-sdk/setup-adapter-runtime` | `createEnvPatchedAccountSetupAdapter` | | `plugin-sdk/setup-tools` | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | - | `plugin-sdk/account-core` | Допоміжні засоби для конфігурації/керування доступом до дій для багатьох облікових записів, допоміжні засоби резервного вибору облікового запису за замовчуванням | + | `plugin-sdk/account-core` | Допоміжні засоби для мультиакаунтної конфігурації/гейтів дій, допоміжні засоби резервного вибору акаунта за замовчуванням | | `plugin-sdk/account-id` | `DEFAULT_ACCOUNT_ID`, допоміжні засоби нормалізації account-id | - | `plugin-sdk/account-resolution` | Допоміжні засоби пошуку облікового запису + резервного вибору за замовчуванням | - | `plugin-sdk/account-helpers` | Вузькі допоміжні засоби для списку облікових записів/дій із обліковими записами | + | `plugin-sdk/account-resolution` | Допоміжні засоби пошуку акаунта + резервного вибору за замовчуванням | + | `plugin-sdk/account-helpers` | Вузькі допоміжні засоби для списку акаунтів/дій з акаунтами | | `plugin-sdk/channel-pairing` | `createChannelPairingController` | | `plugin-sdk/channel-reply-pipeline` | `createChannelReplyPipeline` | | `plugin-sdk/channel-config-helpers` | `createHybridChannelConfigAdapter` | | `plugin-sdk/channel-config-schema` | Типи схеми конфігурації channel | - | `plugin-sdk/telegram-command-config` | Допоміжні засоби нормалізації/валідації користувацьких команд Telegram із резервним використанням контракту вбудованих plugin-ів | - | `plugin-sdk/command-gating` | Вузькі допоміжні засоби керування доступом до команд | + | `plugin-sdk/telegram-command-config` | Допоміжні засоби нормалізації/валідації користувацьких команд Telegram із резервною підтримкою контракту вбудованих plugin-ів | + | `plugin-sdk/command-gating` | Вузькі допоміжні засоби гейту авторизації команд | | `plugin-sdk/channel-policy` | `resolveChannelGroupRequireMention` | | `plugin-sdk/channel-lifecycle` | `createAccountStatusSink` | - | `plugin-sdk/inbound-envelope` | Спільні допоміжні засоби для побудови вхідних маршрутів + envelope | - | `plugin-sdk/inbound-reply-dispatch` | Спільні допоміжні засоби запису та диспетчеризації вхідних повідомлень | - | `plugin-sdk/messaging-targets` | Допоміжні засоби розбору/зіставлення target | + | `plugin-sdk/inbound-envelope` | Спільні допоміжні засоби маршрутизації вхідних повідомлень + побудови envelope | + | `plugin-sdk/inbound-reply-dispatch` | Спільні допоміжні засоби запису й dispatch для вхідних повідомлень | + | `plugin-sdk/messaging-targets` | Допоміжні засоби розбору/зіставлення цілей | | `plugin-sdk/outbound-media` | Спільні допоміжні засоби завантаження вихідних медіа | - | `plugin-sdk/outbound-runtime` | Допоміжні засоби для вихідної ідентичності, делегата надсилання та планування payload | - | `plugin-sdk/poll-runtime` | Вузькі допоміжні засоби нормалізації опитувань | - | `plugin-sdk/thread-bindings-runtime` | Допоміжні засоби життєвого циклу та адаптера для прив’язок thread | - | `plugin-sdk/agent-media-payload` | Застарілий будівник payload медіа агента | - | `plugin-sdk/conversation-runtime` | Допоміжні засоби для прив’язки conversation/thread, pairing і налаштованих прив’язок | + | `plugin-sdk/outbound-runtime` | Допоміжні засоби вихідної ідентичності, делегата надсилання та планування payload | + | `plugin-sdk/poll-runtime` | Вузькі допоміжні засоби нормалізації poll | + | `plugin-sdk/thread-bindings-runtime` | Допоміжні засоби життєвого циклу прив’язок потоків і адаптерів | + | `plugin-sdk/agent-media-payload` | Застарілий builder payload медіа агента | + | `plugin-sdk/conversation-runtime` | Допоміжні засоби прив’язки conversation/thread, pairing та налаштованих binding | | `plugin-sdk/runtime-config-snapshot` | Допоміжний засіб snapshot конфігурації runtime | - | `plugin-sdk/runtime-group-policy` | Допоміжні засоби визначення group-policy у runtime | + | `plugin-sdk/runtime-group-policy` | Допоміжні засоби визначення policy груп у runtime | | `plugin-sdk/channel-status` | Спільні допоміжні засоби snapshot/summary статусу channel | | `plugin-sdk/channel-config-primitives` | Вузькі примітиви схеми конфігурації channel | | `plugin-sdk/channel-config-writes` | Допоміжні засоби авторизації запису конфігурації channel | - | `plugin-sdk/channel-plugin-common` | Спільні експорти prelude для channel plugin | + | `plugin-sdk/channel-plugin-common` | Спільні prelude-експорти channel plugin-ів | | `plugin-sdk/allowlist-config-edit` | Допоміжні засоби редагування/читання конфігурації allowlist | - | `plugin-sdk/group-access` | Спільні допоміжні засоби прийняття рішень щодо group-access | + | `plugin-sdk/group-access` | Спільні допоміжні засоби рішень щодо доступу груп | | `plugin-sdk/direct-dm` | Спільні допоміжні засоби auth/guard для прямих DM | - | `plugin-sdk/interactive-runtime` | Допоміжні засоби нормалізації/скорочення payload інтерактивних відповідей | - | `plugin-sdk/channel-inbound` | Compatibility barrel для debounce вхідних повідомлень, зіставлення згадок, допоміжних засобів mention-policy та допоміжних засобів envelope | - | `plugin-sdk/channel-mention-gating` | Вузькі допоміжні засоби mention-policy без ширшої поверхні inbound runtime | - | `plugin-sdk/channel-location` | Контекст розташування channel і допоміжні засоби форматування | - | `plugin-sdk/channel-logging` | Допоміжні засоби логування channel для скидання вхідних повідомлень і збоїв typing/ack | - | `plugin-sdk/channel-send-result` | Типи результату відповіді | - | `plugin-sdk/channel-actions` | `createMessageToolButtonsSchema`, `createMessageToolCardSchema` | - | `plugin-sdk/channel-targets` | Допоміжні засоби розбору/зіставлення target | + | `plugin-sdk/interactive-runtime` | Допоміжні засоби семантичного представлення повідомлень, доставки та застарілих інтерактивних відповідей. Див. [Message Presentation](/uk/plugins/message-presentation) | + | `plugin-sdk/channel-inbound` | Barrel сумісності для debounce вхідних повідомлень, зіставлення згадок, допоміжних засобів policy згадок і допоміжних засобів envelope | + | `plugin-sdk/channel-mention-gating` | Вузькі допоміжні засоби policy згадок без ширшої surface runtime вхідних повідомлень | + | `plugin-sdk/channel-location` | Допоміжні засоби контексту розташування channel та форматування | + | `plugin-sdk/channel-logging` | Допоміжні засоби логування channel для відкидання вхідних повідомлень і збоїв typing/ack | + | `plugin-sdk/channel-send-result` | Типи результатів відповіді | + | `plugin-sdk/channel-actions` | Допоміжні засоби дій із повідомленнями channel, а також застарілі допоміжні засоби нативної схеми, збережені для сумісності plugin-ів | + | `plugin-sdk/channel-targets` | Допоміжні засоби розбору/зіставлення цілей | | `plugin-sdk/channel-contract` | Типи контракту channel | | `plugin-sdk/channel-feedback` | Підключення feedback/reaction | - | `plugin-sdk/channel-secret-runtime` | Вузькі допоміжні засоби контракту секретів, такі як `collectSimpleChannelFieldAssignments`, `getChannelSurface`, `pushAssignment`, і типи target секретів | + | `plugin-sdk/channel-secret-runtime` | Вузькі допоміжні засоби контракту secret, такі як `collectSimpleChannelFieldAssignments`, `getChannelSurface`, `pushAssignment`, і типи цілей secret | - | Subpath | Ключові експорти | + | Підшлях | Ключові експорти | | --- | --- | | `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | | `plugin-sdk/provider-setup` | Кураторські допоміжні засоби налаштування локального/self-hosted provider | @@ -137,142 +138,142 @@ seams для вбудованих plugin-ів, таких як `plugin-sdk/feish | `plugin-sdk/cli-backend` | Значення CLI backend за замовчуванням + константи watchdog | | `plugin-sdk/provider-auth-runtime` | Допоміжні засоби визначення API-ключа в runtime для provider plugin-ів | | `plugin-sdk/provider-auth-api-key` | Допоміжні засоби онбордингу/запису профілю API-ключа, такі як `upsertApiKeyProfile` | - | `plugin-sdk/provider-auth-result` | Стандартний будівник результату OAuth auth | + | `plugin-sdk/provider-auth-result` | Стандартний builder результату OAuth auth | | `plugin-sdk/provider-auth-login` | Спільні допоміжні засоби інтерактивного входу для provider plugin-ів | - | `plugin-sdk/provider-env-vars` | Допоміжні засоби пошуку змінних середовища auth provider | + | `plugin-sdk/provider-env-vars` | Допоміжні засоби пошуку env-var auth provider-а | | `plugin-sdk/provider-auth` | `createProviderApiKeyAuthMethod`, `ensureApiKeyFromOptionEnvOrPrompt`, `upsertAuthProfile`, `upsertApiKeyProfile`, `writeOAuthCredentials` | - | `plugin-sdk/provider-model-shared` | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`, спільні будівники replay-policy, допоміжні засоби endpoint provider та допоміжні засоби нормалізації model-id, такі як `normalizeNativeXaiModelId` | + | `plugin-sdk/provider-model-shared` | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`, спільні builder-и policy повторного відтворення, допоміжні засоби endpoint provider-а та допоміжні засоби нормалізації model-id, такі як `normalizeNativeXaiModelId` | | `plugin-sdk/provider-catalog-shared` | `findCatalogTemplate`, `buildSingleProviderApiKeyCatalog`, `supportsNativeStreamingUsageCompat`, `applyProviderNativeStreamingUsageCompat` | - | `plugin-sdk/provider-http` | Загальні допоміжні засоби HTTP/можливостей endpoint provider | + | `plugin-sdk/provider-http` | Узагальнені допоміжні засоби HTTP/capability endpoint provider-а | | `plugin-sdk/provider-web-fetch-contract` | Вузькі допоміжні засоби контракту конфігурації/вибору web-fetch, такі як `enablePluginInConfig` і `WebFetchProviderPlugin` | - | `plugin-sdk/provider-web-fetch` | Допоміжні засоби реєстрації/кешування provider web-fetch | - | `plugin-sdk/provider-web-search-config-contract` | Вузькі допоміжні засоби конфігурації/облікових даних web-search для provider-ів, яким не потрібне підключення ввімкнення plugin-а | + | `plugin-sdk/provider-web-fetch` | Допоміжні засоби реєстрації/кешування provider-а web-fetch | + | `plugin-sdk/provider-web-search-config-contract` | Вузькі допоміжні засоби конфігурації/облікових даних web-search для provider-ів, яким не потрібне підключення enable plugin | | `plugin-sdk/provider-web-search-contract` | Вузькі допоміжні засоби контракту конфігурації/облікових даних web-search, такі як `createWebSearchProviderContractFields`, `enablePluginInConfig`, `resolveProviderWebSearchPluginConfig` і scoped setter/getter-и облікових даних | - | `plugin-sdk/provider-web-search` | Допоміжні засоби реєстрації/кешування/runtime provider web-search | + | `plugin-sdk/provider-web-search` | Допоміжні засоби реєстрації/кешування/runtime provider-а web-search | | `plugin-sdk/provider-tools` | `ProviderToolCompatFamily`, `buildProviderToolCompatFamilyHooks`, очищення схеми Gemini + діагностика, а також допоміжні засоби сумісності xAI, такі як `resolveXaiModelCompatPatch` / `applyXaiModelCompat` | - | `plugin-sdk/provider-usage` | `fetchClaudeUsage` та подібні | - | `plugin-sdk/provider-stream` | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`, типи обгорток stream і спільні допоміжні засоби обгорток Anthropic/Bedrock/Google/Kilocode/Moonshot/OpenAI/OpenRouter/Z.A.I/MiniMax/Copilot | - | `plugin-sdk/provider-transport-runtime` | Допоміжні засоби нативного транспорту provider, такі як guarded fetch, трансформації транспортних повідомлень і потоки подій транспорту з підтримкою запису | - | `plugin-sdk/provider-onboard` | Допоміжні засоби патчу конфігурації онбордингу | - | `plugin-sdk/global-singleton` | Допоміжні засоби singleton/map/cache, локальні для процесу | + | `plugin-sdk/provider-usage` | `fetchClaudeUsage` і подібні | + | `plugin-sdk/provider-stream` | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`, типи stream wrapper і спільні допоміжні засоби wrapper для Anthropic/Bedrock/Google/Kilocode/Moonshot/OpenAI/OpenRouter/Z.A.I/MiniMax/Copilot | + | `plugin-sdk/provider-transport-runtime` | Нативні допоміжні засоби транспорту provider-а, такі як guarded fetch, перетворення транспортних повідомлень і потоки подій транспорту із можливістю запису | + | `plugin-sdk/provider-onboard` | Допоміжні засоби patch конфігурації онбордингу | + | `plugin-sdk/global-singleton` | Допоміжні засоби локального для процесу singleton/map/cache | - | Subpath | Ключові експорти | + | Підшлях | Ключові експорти | | --- | --- | | `plugin-sdk/command-auth` | `resolveControlCommandGate`, допоміжні засоби реєстру команд, допоміжні засоби авторизації відправника | - | `plugin-sdk/command-status` | Будівники повідомлень команд/довідки, такі як `buildCommandsMessagePaginated` і `buildHelpMessage` | - | `plugin-sdk/approval-auth-runtime` | Допоміжні засоби визначення approver і auth дій у тому самому chat | - | `plugin-sdk/approval-client-runtime` | Нативні допоміжні засоби профілю/фільтра схвалення exec | - | `plugin-sdk/approval-delivery-runtime` | Адаптери нативних можливостей/доставки схвалення | - | `plugin-sdk/approval-gateway-runtime` | Спільний допоміжний засіб визначення gateway схвалення | - | `plugin-sdk/approval-handler-adapter-runtime` | Полегшені допоміжні засоби завантаження адаптера нативного схвалення для hot entrypoint-ів channel | - | `plugin-sdk/approval-handler-runtime` | Ширші допоміжні засоби runtime обробника схвалення; надавайте перевагу вужчим adapter/gateway seams, коли їх достатньо | - | `plugin-sdk/approval-native-runtime` | Допоміжні засоби target нативного схвалення + прив’язки облікового запису | - | `plugin-sdk/approval-reply-runtime` | Допоміжні засоби payload відповіді на схвалення exec/plugin | - | `plugin-sdk/command-auth-native` | Нативні допоміжні засоби auth команд + target сесії native | + | `plugin-sdk/command-status` | Builder-и повідомлень команд/довідки, такі як `buildCommandsMessagePaginated` і `buildHelpMessage` | + | `plugin-sdk/approval-auth-runtime` | Допоміжні засоби визначення approver-а та auth дій у тому ж чаті | + | `plugin-sdk/approval-client-runtime` | Нативні допоміжні засоби профілю/фільтра approval для exec | + | `plugin-sdk/approval-delivery-runtime` | Нативні адаптери capability/delivery approval | + | `plugin-sdk/approval-gateway-runtime` | Спільний допоміжний засіб визначення Gateway для approval | + | `plugin-sdk/approval-handler-adapter-runtime` | Полегшені нативні допоміжні засоби завантаження адаптера approval для гарячих entrypoint-ів channel | + | `plugin-sdk/approval-handler-runtime` | Ширші допоміжні засоби runtime handler-а approval; віддавайте перевагу вужчим шарам adapter/gateway, коли їх достатньо | + | `plugin-sdk/approval-native-runtime` | Нативні допоміжні засоби цілі approval + прив’язки акаунта | + | `plugin-sdk/approval-reply-runtime` | Допоміжні засоби payload відповіді approval для exec/plugin | + | `plugin-sdk/command-auth-native` | Нативний auth команд + нативні допоміжні засоби session-target | | `plugin-sdk/command-detection` | Спільні допоміжні засоби виявлення команд | - | `plugin-sdk/command-surface` | Допоміжні засоби нормалізації тіла команд і surface команд | + | `plugin-sdk/command-surface` | Допоміжні засоби нормалізації тіла команди та поверхні команд | | `plugin-sdk/allow-from` | `formatAllowFromLowercase` | - | `plugin-sdk/channel-secret-runtime` | Вузькі допоміжні засоби збирання секретних контрактів для поверхонь секретів channel/plugin | - | `plugin-sdk/secret-ref-runtime` | Вузькі допоміжні засоби `coerceSecretRef` і типізації SecretRef для парсингу secret-contract/config | - | `plugin-sdk/security-runtime` | Спільні допоміжні засоби trust, DM gating, external-content і збирання секретів | - | `plugin-sdk/ssrf-policy` | Допоміжні засоби політики SSRF для allowlist хостів і приватної мережі | - | `plugin-sdk/ssrf-dispatcher` | Вузькі допоміжні засоби pinned-dispatcher без широкої поверхні infra runtime | - | `plugin-sdk/ssrf-runtime` | Допоміжні засоби pinned-dispatcher, fetch із захистом SSRF і політики SSRF | + | `plugin-sdk/channel-secret-runtime` | Вузькі допоміжні засоби збирання secret-контрактів для поверхонь secret channel/plugin | + | `plugin-sdk/secret-ref-runtime` | Вузькі допоміжні засоби `coerceSecretRef` і типізації SecretRef для парсингу secret-контрактів/конфігурації | + | `plugin-sdk/security-runtime` | Спільні допоміжні засоби довіри, гейтингу DM, зовнішнього вмісту та збирання secret | + | `plugin-sdk/ssrf-policy` | Допоміжні засоби policy SSRF для allowlist хостів і приватної мережі | + | `plugin-sdk/ssrf-dispatcher` | Вузькі допоміжні засоби pinned-dispatcher без широкої поверхні runtime infra | + | `plugin-sdk/ssrf-runtime` | Допоміжні засоби pinned-dispatcher, fetch із захистом SSRF і policy SSRF | | `plugin-sdk/secret-input` | Допоміжні засоби парсингу secret input | - | `plugin-sdk/webhook-ingress` | Допоміжні засоби запитів/target Webhook | - | `plugin-sdk/webhook-request-guards` | Допоміжні засоби для розміру тіла запиту/тайм-ауту | + | `plugin-sdk/webhook-ingress` | Допоміжні засоби запиту/цілі Webhook | + | `plugin-sdk/webhook-request-guards` | Допоміжні засоби розміру body/timeout запиту | - | Subpath | Ключові експорти | + | Підшлях | Ключові експорти | | --- | --- | - | `plugin-sdk/runtime` | Широкі допоміжні засоби runtime/logging/backup/встановлення plugin-ів | + | `plugin-sdk/runtime` | Широкі допоміжні засоби runtime/logging/backup/установлення plugin-ів | | `plugin-sdk/runtime-env` | Вузькі допоміжні засоби env runtime, logger, timeout, retry і backoff | - | `plugin-sdk/channel-runtime-context` | Загальні допоміжні засоби реєстрації та пошуку runtime-context channel | + | `plugin-sdk/channel-runtime-context` | Узагальнені допоміжні засоби реєстрації та пошуку runtime-context channel | | `plugin-sdk/runtime-store` | `createPluginRuntimeStore` | - | `plugin-sdk/plugin-runtime` | Спільні допоміжні засоби command/hook/http/interactive для plugin-ів | - | `plugin-sdk/hook-runtime` | Спільні допоміжні засоби конвеєра Webhook/внутрішніх hooks | - | `plugin-sdk/lazy-runtime` | Допоміжні засоби lazy імпорту/прив’язки runtime, такі як `createLazyRuntimeModule`, `createLazyRuntimeMethod` і `createLazyRuntimeSurface` | + | `plugin-sdk/plugin-runtime` | Спільні допоміжні засоби команд/hook/http/interactive plugin-а | + | `plugin-sdk/hook-runtime` | Спільні допоміжні засоби pipeline webhook/internal hook | + | `plugin-sdk/lazy-runtime` | Допоміжні засоби lazy-імпорту/прив’язки runtime, такі як `createLazyRuntimeModule`, `createLazyRuntimeMethod` і `createLazyRuntimeSurface` | | `plugin-sdk/process-runtime` | Допоміжні засоби exec процесів | - | `plugin-sdk/cli-runtime` | Допоміжні засоби форматування CLI, wait і version | - | `plugin-sdk/gateway-runtime` | Допоміжні засоби клієнта Gateway і патчу channel-status | + | `plugin-sdk/cli-runtime` | Допоміжні засоби форматування CLI, очікування та версії | + | `plugin-sdk/gateway-runtime` | Допоміжні засоби клієнта Gateway і patch статусу channel | | `plugin-sdk/config-runtime` | Допоміжні засоби завантаження/запису конфігурації | - | `plugin-sdk/telegram-command-config` | Допоміжні засоби нормалізації назв/описів команд Telegram і перевірки дублювань/конфліктів, навіть коли поверхня контракту вбудованого Telegram недоступна | - | `plugin-sdk/text-autolink-runtime` | Виявлення autolink посилань на файли без широкого barrel `text-runtime` | - | `plugin-sdk/approval-runtime` | Допоміжні засоби схвалення exec/plugin, будівники можливостей схвалення, допоміжні засоби auth/profile, нативні допоміжні засоби маршрутизації/runtime | - | `plugin-sdk/reply-runtime` | Спільні допоміжні засоби runtime вхідних повідомлень/відповідей, chunking, dispatch, Heartbeat, планувальник відповідей | - | `plugin-sdk/reply-dispatch-runtime` | Вузькі допоміжні засоби dispatch/finalize для відповідей | - | `plugin-sdk/reply-history` | Спільні допоміжні засоби short-window історії відповідей, такі як `buildHistoryContext`, `recordPendingHistoryEntry` і `clearHistoryEntriesIfEnabled` | + | `plugin-sdk/telegram-command-config` | Допоміжні засоби нормалізації імені/опису команд Telegram та перевірки дублікатів/конфліктів, навіть коли поверхня контракту вбудованого Telegram недоступна | + | `plugin-sdk/text-autolink-runtime` | Виявлення автопосилань на файлові посилання без широкого barrel-а text-runtime | + | `plugin-sdk/approval-runtime` | Допоміжні засоби approval для exec/plugin, builder-и capability approval, допоміжні засоби auth/profile, нативної маршрутизації/runtime | + | `plugin-sdk/reply-runtime` | Спільні допоміжні засоби runtime для вхідних повідомлень/відповідей, chunking, dispatch, Heartbeat, planner відповіді | + | `plugin-sdk/reply-dispatch-runtime` | Вузькі допоміжні засоби dispatch/finalize відповіді | + | `plugin-sdk/reply-history` | Спільні допоміжні засоби коротковіконної історії відповідей, такі як `buildHistoryContext`, `recordPendingHistoryEntry` і `clearHistoryEntriesIfEnabled` | | `plugin-sdk/reply-reference` | `createReplyReferencePlanner` | | `plugin-sdk/reply-chunking` | Вузькі допоміжні засоби chunking тексту/markdown | - | `plugin-sdk/session-store-runtime` | Допоміжні засоби шляхів session store + `updated-at` | - | `plugin-sdk/state-paths` | Допоміжні засоби шляхів каталогів state/OAuth | - | `plugin-sdk/routing` | Допоміжні засоби маршруту/ключа сесії/прив’язки облікового запису, такі як `resolveAgentRoute`, `buildAgentSessionKey` і `resolveDefaultAgentBoundAccountId` | - | `plugin-sdk/status-helpers` | Спільні допоміжні засоби summary статусу channel/account, значення runtime-state за замовчуванням і допоміжні засоби метаданих issue | - | `plugin-sdk/target-resolver-runtime` | Спільні допоміжні засоби визначення target | + | `plugin-sdk/session-store-runtime` | Допоміжні засоби шляху сховища сесій + `updated-at` | + | `plugin-sdk/state-paths` | Допоміжні засоби шляхів директорій state/OAuth | + | `plugin-sdk/routing` | Допоміжні засоби route/session-key/account binding, такі як `resolveAgentRoute`, `buildAgentSessionKey` і `resolveDefaultAgentBoundAccountId` | + | `plugin-sdk/status-helpers` | Спільні допоміжні засоби summary статусу channel/акаунта, значення стану runtime за замовчуванням і допоміжні засоби метаданих issue | + | `plugin-sdk/target-resolver-runtime` | Спільні допоміжні засоби resolver-а цілей | | `plugin-sdk/string-normalization-runtime` | Допоміжні засоби нормалізації slug/рядків | - | `plugin-sdk/request-url` | Витяг рядкових URL із вхідних даних fetch/request-подібного типу | - | `plugin-sdk/run-command` | Виконавець команд із таймером і нормалізованими результатами stdout/stderr | - | `plugin-sdk/param-readers` | Типові читачі параметрів tool/CLI | - | `plugin-sdk/tool-payload` | Витяг нормалізованих payload з об’єктів результату tool | - | `plugin-sdk/tool-send` | Витяг канонічних полів target надсилання з аргументів tool | - | `plugin-sdk/temp-path` | Спільні допоміжні засоби шляхів тимчасових завантажень | - | `plugin-sdk/logging-core` | Допоміжні засоби logger підсистем і редагування конфіденційних даних | - | `plugin-sdk/markdown-table-runtime` | Допоміжні засоби режиму markdown-таблиць | - | `plugin-sdk/json-store` | Невеликі допоміжні засоби читання/запису JSON state | - | `plugin-sdk/file-lock` | Повторно вхідні допоміжні засоби file-lock | - | `plugin-sdk/persistent-dedupe` | Допоміжні засоби dedupe cache з дисковим збереженням | - | `plugin-sdk/acp-runtime` | Допоміжні засоби runtime/сесій ACP і dispatch відповідей | - | `plugin-sdk/acp-binding-resolve-runtime` | Визначення прив’язки ACP лише для читання без імпортів запуску життєвого циклу | - | `plugin-sdk/agent-config-primitives` | Вузькі примітиви runtime config-schema агента | - | `plugin-sdk/boolean-param` | Читач нестрогих булевих параметрів | - | `plugin-sdk/dangerous-name-runtime` | Допоміжні засоби визначення збігів небезпечних назв | - | `plugin-sdk/device-bootstrap` | Допоміжні засоби bootstrap пристрою та pairing token | + | `plugin-sdk/request-url` | Витягування рядкових URL із входів, подібних до fetch/request | + | `plugin-sdk/run-command` | Runner команд із таймером і нормалізованими результатами stdout/stderr | + | `plugin-sdk/param-readers` | Поширені зчитувачі параметрів tool/CLI | + | `plugin-sdk/tool-payload` | Витягування нормалізованих payload з об’єктів результатів tool | + | `plugin-sdk/tool-send` | Витягування канонічних полів цілі надсилання з аргументів tool | + | `plugin-sdk/temp-path` | Спільні допоміжні засоби шляхів для тимчасових завантажень | + | `plugin-sdk/logging-core` | Допоміжні засоби logger-а підсистеми та редагування чутливих даних | + | `plugin-sdk/markdown-table-runtime` | Допоміжні засоби режиму таблиць Markdown | + | `plugin-sdk/json-store` | Невеликі допоміжні засоби читання/запису стану JSON | + | `plugin-sdk/file-lock` | Допоміжні засоби повторно вхідного file-lock | + | `plugin-sdk/persistent-dedupe` | Допоміжні засоби кешу дедуплікації на диску | + | `plugin-sdk/acp-runtime` | Допоміжні засоби runtime/сесії ACP і dispatch відповіді | + | `plugin-sdk/acp-binding-resolve-runtime` | Визначення прив’язок ACP лише для читання без імпортів запуску життєвого циклу | + | `plugin-sdk/agent-config-primitives` | Вузькі примітиви схеми конфігурації runtime агента | + | `plugin-sdk/boolean-param` | Зчитувач нестрогих boolean-параметрів | + | `plugin-sdk/dangerous-name-runtime` | Допоміжні засоби визначення збігів небезпечних імен | + | `plugin-sdk/device-bootstrap` | Допоміжні засоби початкового налаштування пристрою та токенів pairing | | `plugin-sdk/extension-shared` | Спільні примітиви допоміжних засобів passive-channel, status і ambient proxy | - | `plugin-sdk/models-provider-runtime` | Допоміжні засоби відповідей command/provider для `/models` | - | `plugin-sdk/skill-commands-runtime` | Допоміжні засоби переліку команд Skills | + | `plugin-sdk/models-provider-runtime` | Допоміжні засоби відповідей команд/provider-ів `/models` | + | `plugin-sdk/skill-commands-runtime` | Допоміжні засоби списку команд Skills | | `plugin-sdk/native-command-registry` | Допоміжні засоби реєстру/build/serialize нативних команд | - | `plugin-sdk/agent-harness` | Експериментальна поверхня trusted-plugin для низькорівневих agent harness: типи harness, допоміжні засоби steer/abort активного запуску, допоміжні засоби мосту OpenClaw tool і утиліти результатів attempt | + | `plugin-sdk/agent-harness` | Експериментальна поверхня trusted-plugin для низькорівневих harness агента: типи harness, допоміжні засоби steer/abort активного запуску, допоміжні засоби мосту tool OpenClaw і утиліти результатів attempt | | `plugin-sdk/provider-zai-endpoint` | Допоміжні засоби виявлення endpoint Z.A.I | | `plugin-sdk/infra-runtime` | Допоміжні засоби системних подій/Heartbeat | | `plugin-sdk/collection-runtime` | Невеликі допоміжні засоби обмеженого кешу | | `plugin-sdk/diagnostic-runtime` | Допоміжні засоби діагностичних прапорців і подій | | `plugin-sdk/error-runtime` | Допоміжні засоби графа помилок, форматування, спільної класифікації помилок, `isApprovalNotFoundError` | - | `plugin-sdk/fetch-runtime` | Допоміжні засоби обгорнутого fetch, proxy і pinned lookup | - | `plugin-sdk/runtime-fetch` | Runtime fetch з урахуванням dispatcher без імпортів proxy/guarded-fetch | - | `plugin-sdk/response-limit-runtime` | Читач обмеженого тіла відповіді без широкої поверхні media runtime | - | `plugin-sdk/session-binding-runtime` | Поточний стан прив’язки conversation без маршрутизації налаштованих прив’язок або pairing stores | - | `plugin-sdk/session-store-runtime` | Допоміжні засоби читання session-store без широких імпортів запису/обслуговування конфігурації | - | `plugin-sdk/context-visibility-runtime` | Допоміжні засоби визначення видимості контексту та фільтрації додаткового контексту без широких імпортів config/security | - | `plugin-sdk/string-coerce-runtime` | Вузькі допоміжні засоби приведення та нормалізації primitive record/string без імпортів markdown/logging | - | `plugin-sdk/host-runtime` | Допоміжні засоби нормалізації hostname і хоста SCP | - | `plugin-sdk/retry-runtime` | Допоміжні засоби конфігурації retry і виконавця retry | - | `plugin-sdk/agent-runtime` | Допоміжні засоби каталогу/ідентичності/робочого простору агента | - | `plugin-sdk/directory-runtime` | Запит/дедуплікація каталогів на основі конфігурації | + | `plugin-sdk/fetch-runtime` | Допоміжні засоби обгорнутого fetch, proxy та pinned lookup | + | `plugin-sdk/runtime-fetch` | Fetch runtime з урахуванням dispatcher без імпортів proxy/guarded-fetch | + | `plugin-sdk/response-limit-runtime` | Зчитувач обмеженого body відповіді без широкої поверхні runtime медіа | + | `plugin-sdk/session-binding-runtime` | Поточний стан прив’язки conversation без маршрутизації налаштованих binding або сховищ pairing | + | `plugin-sdk/session-store-runtime` | Допоміжні засоби читання сховища сесій без широких імпортів запису/обслуговування конфігурації | + | `plugin-sdk/context-visibility-runtime` | Визначення видимості контексту та фільтрація додаткового контексту без широких імпортів конфігурації/безпеки | + | `plugin-sdk/string-coerce-runtime` | Вузькі допоміжні засоби приведення й нормалізації примітивних record/string без імпортів markdown/logging | + | `plugin-sdk/host-runtime` | Допоміжні засоби нормалізації hostname і SCP host | + | `plugin-sdk/retry-runtime` | Допоміжні засоби конфігурації retry і runner-а retry | + | `plugin-sdk/agent-runtime` | Допоміжні засоби директорії/ідентичності/робочого простору агента | + | `plugin-sdk/directory-runtime` | Запит/дедуплікація директорій на основі конфігурації | | `plugin-sdk/keyed-async-queue` | `KeyedAsyncQueue` | - - | Subpath | Ключові експорти | + + | Підшлях | Ключові експорти | | --- | --- | - | `plugin-sdk/media-runtime` | Спільні допоміжні засоби fetch/transform/store для медіа, а також будівники media payload | - | `plugin-sdk/media-generation-runtime` | Спільні допоміжні засоби failover для генерації медіа, вибору candidate і повідомлень про відсутню model | - | `plugin-sdk/media-understanding` | Типи provider для розуміння медіа, а також експорти допоміжних засобів для зображень/аудіо, орієнтовані на provider | - | `plugin-sdk/text-runtime` | Спільні допоміжні засоби text/markdown/logging, такі як видалення text, видимого assistant-у, допоміжні засоби render/chunking/table для markdown, допоміжні засоби редагування конфіденційних даних, допоміжні засоби directive-tag і утиліти safe-text | + | `plugin-sdk/media-runtime` | Спільні допоміжні засоби fetch/transform/store медіа, а також builder-и payload медіа | + | `plugin-sdk/media-generation-runtime` | Спільні допоміжні засоби failover для генерації медіа, вибору кандидатів і повідомлень про відсутню модель | + | `plugin-sdk/media-understanding` | Типи provider-а для розуміння медіа, а також provider-орієнтовані експорти допоміжних засобів для зображень/аудіо | + | `plugin-sdk/text-runtime` | Спільні допоміжні засоби text/markdown/logging, такі як вилучення тексту, видимого асистенту, допоміжні засоби render/chunking/table для markdown, допоміжні засоби редагування чутливих даних, допоміжні засоби тегів директив і утиліти безпечного тексту | | `plugin-sdk/text-chunking` | Допоміжний засіб chunking вихідного тексту | - | `plugin-sdk/speech` | Типи speech provider, а також допоміжні засоби directive, registry і validation, орієнтовані на provider | - | `plugin-sdk/speech-core` | Спільні типи speech provider, допоміжні засоби registry, directive і normalization | - | `plugin-sdk/realtime-transcription` | Типи provider для транскрипції в реальному часі та допоміжні засоби registry | - | `plugin-sdk/realtime-voice` | Типи provider для голосу в реальному часі та допоміжні засоби registry | - | `plugin-sdk/image-generation` | Типи provider для генерації зображень | - | `plugin-sdk/image-generation-core` | Спільні типи генерації зображень, допоміжні засоби failover, auth і registry | + | `plugin-sdk/speech` | Типи provider-а мовлення, а також provider-орієнтовані допоміжні засоби директив, реєстру і валідації | + | `plugin-sdk/speech-core` | Спільні допоміжні засоби типів, реєстру, директив і нормалізації provider-а мовлення | + | `plugin-sdk/realtime-transcription` | Типи provider-а транскрипції в реальному часі та допоміжні засоби реєстру | + | `plugin-sdk/realtime-voice` | Типи provider-а голосу в реальному часі та допоміжні засоби реєстру | + | `plugin-sdk/image-generation` | Типи provider-а генерації зображень | + | `plugin-sdk/image-generation-core` | Спільні допоміжні засоби типів, failover, auth і реєстру генерації зображень | | `plugin-sdk/music-generation` | Типи provider/request/result для генерації музики | - | `plugin-sdk/music-generation-core` | Спільні типи генерації музики, допоміжні засоби failover, пошуку provider і парсингу model-ref | + | `plugin-sdk/music-generation-core` | Спільні допоміжні засоби типів генерації музики, failover, пошуку provider-а та парсингу model-ref | | `plugin-sdk/video-generation` | Типи provider/request/result для генерації відео | - | `plugin-sdk/video-generation-core` | Спільні типи генерації відео, допоміжні засоби failover, пошуку provider і парсингу model-ref | - | `plugin-sdk/webhook-targets` | Допоміжні засоби реєстру target Webhook і встановлення маршрутів | + | `plugin-sdk/video-generation-core` | Спільні допоміжні засоби типів генерації відео, failover, пошуку provider-а та парсингу model-ref | + | `plugin-sdk/webhook-targets` | Допоміжні засоби реєстру цілей Webhook і встановлення маршрутів | | `plugin-sdk/webhook-path` | Допоміжні засоби нормалізації шляху Webhook | | `plugin-sdk/web-media` | Спільні допоміжні засоби завантаження віддалених/локальних медіа | | `plugin-sdk/zod` | Повторно експортований `zod` для споживачів plugin SDK | @@ -280,100 +281,101 @@ seams для вбудованих plugin-ів, таких як `plugin-sdk/feish - | Subpath | Ключові експорти | + | Підшлях | Ключові експорти | | --- | --- | - | `plugin-sdk/memory-core` | Поверхня допоміжних засобів bundled memory-core для manager/config/file/CLI | - | `plugin-sdk/memory-core-engine-runtime` | Runtime facade індексу/пошуку Memory | + | `plugin-sdk/memory-core` | Поверхня допоміжних засобів вбудованого memory-core для менеджера/конфігурації/файлів/допоміжних засобів CLI | + | `plugin-sdk/memory-core-engine-runtime` | Фасад runtime індексації/пошуку Memory | | `plugin-sdk/memory-core-host-engine-foundation` | Експорти foundation engine хоста Memory | - | `plugin-sdk/memory-core-host-engine-embeddings` | Контракти embedding хоста Memory, доступ до registry, локальний provider і загальні допоміжні засоби batch/remote | + | `plugin-sdk/memory-core-host-engine-embeddings` | Контракти embedding хоста Memory, доступ до реєстру, локальний provider і узагальнені допоміжні засоби batch/remote | | `plugin-sdk/memory-core-host-engine-qmd` | Експорти QMD engine хоста Memory | | `plugin-sdk/memory-core-host-engine-storage` | Експорти storage engine хоста Memory | - | `plugin-sdk/memory-core-host-multimodal` | Багатомодальні допоміжні засоби хоста Memory | + | `plugin-sdk/memory-core-host-multimodal` | Мультимодальні допоміжні засоби хоста Memory | | `plugin-sdk/memory-core-host-query` | Допоміжні засоби запитів хоста Memory | - | `plugin-sdk/memory-core-host-secret` | Допоміжні засоби секретів хоста Memory | + | `plugin-sdk/memory-core-host-secret` | Допоміжні засоби secret хоста Memory | | `plugin-sdk/memory-core-host-events` | Допоміжні засоби журналу подій хоста Memory | | `plugin-sdk/memory-core-host-status` | Допоміжні засоби статусу хоста Memory | - | `plugin-sdk/memory-core-host-runtime-cli` | Допоміжні засоби CLI runtime хоста Memory | + | `plugin-sdk/memory-core-host-runtime-cli` | Допоміжні засоби runtime CLI хоста Memory | | `plugin-sdk/memory-core-host-runtime-core` | Допоміжні засоби core runtime хоста Memory | - | `plugin-sdk/memory-core-host-runtime-files` | Допоміжні засоби file/runtime хоста Memory | + | `plugin-sdk/memory-core-host-runtime-files` | Допоміжні засоби файлів/runtime хоста Memory | | `plugin-sdk/memory-host-core` | Нейтральний до постачальника псевдонім для допоміжних засобів core runtime хоста Memory | | `plugin-sdk/memory-host-events` | Нейтральний до постачальника псевдонім для допоміжних засобів журналу подій хоста Memory | - | `plugin-sdk/memory-host-files` | Нейтральний до постачальника псевдонім для допоміжних засобів file/runtime хоста Memory | + | `plugin-sdk/memory-host-files` | Нейтральний до постачальника псевдонім для допоміжних засобів файлів/runtime хоста Memory | | `plugin-sdk/memory-host-markdown` | Спільні допоміжні засоби керованого markdown для plugin-ів, суміжних із memory | - | `plugin-sdk/memory-host-search` | Active Memory runtime facade для доступу до search-manager | + | `plugin-sdk/memory-host-search` | Фасад runtime Active Memory для доступу до search-manager | | `plugin-sdk/memory-host-status` | Нейтральний до постачальника псевдонім для допоміжних засобів статусу хоста Memory | - | `plugin-sdk/memory-lancedb` | Поверхня допоміжних засобів bundled memory-lancedb | + | `plugin-sdk/memory-lancedb` | Поверхня допоміжних засобів вбудованого memory-lancedb | - - | Family | Поточні підшляхи | Призначене використання | + + | Родина | Поточні підшляхи | Призначене використання | | --- | --- | --- | - | Browser | `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` | Допоміжні засоби підтримки bundled browser plugin (`browser-support` залишається compatibility barrel) | - | Matrix | `plugin-sdk/matrix`, `plugin-sdk/matrix-helper`, `plugin-sdk/matrix-runtime-heavy`, `plugin-sdk/matrix-runtime-shared`, `plugin-sdk/matrix-runtime-surface`, `plugin-sdk/matrix-surface`, `plugin-sdk/matrix-thread-bindings` | Поверхня допоміжних засобів/runtime bundled Matrix | - | Line | `plugin-sdk/line`, `plugin-sdk/line-core`, `plugin-sdk/line-runtime`, `plugin-sdk/line-surface` | Поверхня допоміжних засобів/runtime bundled LINE | - | IRC | `plugin-sdk/irc`, `plugin-sdk/irc-surface` | Поверхня допоміжних засобів bundled IRC | - | Специфічні для channel допоміжні засоби | `plugin-sdk/googlechat`, `plugin-sdk/zalouser`, `plugin-sdk/bluebubbles`, `plugin-sdk/bluebubbles-policy`, `plugin-sdk/mattermost`, `plugin-sdk/mattermost-policy`, `plugin-sdk/feishu-conversation`, `plugin-sdk/msteams`, `plugin-sdk/nextcloud-talk`, `plugin-sdk/nostr`, `plugin-sdk/tlon`, `plugin-sdk/twitch` | Bundled seams сумісності/допоміжних засобів для channel | - | Специфічні для auth/plugin допоміжні засоби | `plugin-sdk/github-copilot-login`, `plugin-sdk/github-copilot-token`, `plugin-sdk/diagnostics-otel`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` | Bundled seams допоміжних засобів для функцій/plugin-ів; `plugin-sdk/github-copilot-token` наразі експортує `DEFAULT_COPILOT_API_BASE_URL`, `deriveCopilotApiBaseUrlFromToken` і `resolveCopilotApiToken` | + | Browser | `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` | Допоміжні засоби підтримки вбудованого browser plugin-а (`browser-support` залишається barrel-ом сумісності) | + | Matrix | `plugin-sdk/matrix`, `plugin-sdk/matrix-helper`, `plugin-sdk/matrix-runtime-heavy`, `plugin-sdk/matrix-runtime-shared`, `plugin-sdk/matrix-runtime-surface`, `plugin-sdk/matrix-surface`, `plugin-sdk/matrix-thread-bindings` | Поверхня helper-ів/runtime вбудованого Matrix | + | Line | `plugin-sdk/line`, `plugin-sdk/line-core`, `plugin-sdk/line-runtime`, `plugin-sdk/line-surface` | Поверхня helper-ів/runtime вбудованого LINE | + | IRC | `plugin-sdk/irc`, `plugin-sdk/irc-surface` | Поверхня helper-ів вбудованого IRC | + | Специфічні для channel helper-и | `plugin-sdk/googlechat`, `plugin-sdk/zalouser`, `plugin-sdk/bluebubbles`, `plugin-sdk/bluebubbles-policy`, `plugin-sdk/mattermost`, `plugin-sdk/mattermost-policy`, `plugin-sdk/feishu-conversation`, `plugin-sdk/msteams`, `plugin-sdk/nextcloud-talk`, `plugin-sdk/nostr`, `plugin-sdk/tlon`, `plugin-sdk/twitch` | Шари сумісності/helper-ів вбудованих channel | + | Специфічні для auth/plugin helper-и | `plugin-sdk/github-copilot-login`, `plugin-sdk/github-copilot-token`, `plugin-sdk/diagnostics-otel`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` | Шари helper-ів вбудованих функцій/plugin-ів; `plugin-sdk/github-copilot-token` наразі експортує `DEFAULT_COPILOT_API_BASE_URL`, `deriveCopilotApiBaseUrlFromToken` і `resolveCopilotApiToken` | ## API реєстрації -Зворотний виклик `register(api)` отримує об’єкт `OpenClawPluginApi` з такими +Зворотний виклик `register(api)` отримує об’єкт `OpenClawPluginApi` із такими методами: -### Реєстрація можливостей +### Реєстрація capability -| Method | Що він реєструє | -| ------------------------------------------------ | ---------------------------------- | -| `api.registerProvider(...)` | Текстовий inference (LLM) | +| Метод | Що реєструє | +| ------------------------------------------------ | -------------------------------------- | +| `api.registerProvider(...)` | Текстовий inference (LLM) | | `api.registerAgentHarness(...)` | Експериментальний низькорівневий виконавець агента | -| `api.registerCliBackend(...)` | Локальний backend inference CLI | -| `api.registerChannel(...)` | Канал обміну повідомленнями | -| `api.registerSpeechProvider(...)` | Синтез text-to-speech / STT | +| `api.registerCliBackend(...)` | Локальний backend inference CLI | +| `api.registerChannel(...)` | Канал обміну повідомленнями | +| `api.registerSpeechProvider(...)` | Синтез text-to-speech / STT | | `api.registerRealtimeTranscriptionProvider(...)` | Потокова транскрипція в реальному часі | -| `api.registerRealtimeVoiceProvider(...)` | Двобічні голосові сесії в реальному часі | -| `api.registerMediaUnderstandingProvider(...)` | Аналіз зображень/аудіо/відео | -| `api.registerImageGenerationProvider(...)` | Генерація зображень | -| `api.registerMusicGenerationProvider(...)` | Генерація музики | -| `api.registerVideoGenerationProvider(...)` | Генерація відео | -| `api.registerWebFetchProvider(...)` | Provider web fetch / scrape | -| `api.registerWebSearchProvider(...)` | Вебпошук | +| `api.registerRealtimeVoiceProvider(...)` | Дуплексні голосові сесії в реальному часі | +| `api.registerMediaUnderstandingProvider(...)` | Аналіз зображень/аудіо/відео | +| `api.registerImageGenerationProvider(...)` | Генерація зображень | +| `api.registerMusicGenerationProvider(...)` | Генерація музики | +| `api.registerVideoGenerationProvider(...)` | Генерація відео | +| `api.registerWebFetchProvider(...)` | Provider web fetch / scrape | +| `api.registerWebSearchProvider(...)` | Вебпошук | -### Інструменти та команди +### Tools і команди -| Method | Що він реєструє | -| ------------------------------- | -------------------------------------------- | -| `api.registerTool(tool, opts?)` | Інструмент агента (обов’язковий або `{ optional: true }`) | -| `api.registerCommand(def)` | Користувацька команда (обходить LLM) | +| Метод | Що реєструє | +| ------------------------------ | -------------------------------------------- | +| `api.registerTool(tool, opts?)` | Tool агента (обов’язковий або `{ optional: true }`) | +| `api.registerCommand(def)` | Користувацька команда (оминає LLM) | ### Інфраструктура -| Method | Що він реєструє | -| ---------------------------------------------- | ---------------------------------- | -| `api.registerHook(events, handler, opts?)` | Hook події | -| `api.registerHttpRoute(params)` | HTTP endpoint Gateway | -| `api.registerGatewayMethod(name, handler)` | RPC-метод Gateway | -| `api.registerCli(registrar, opts?)` | Підкоманда CLI | -| `api.registerService(service)` | Фонова служба | -| `api.registerInteractiveHandler(registration)` | Інтерактивний обробник | -| `api.registerMemoryPromptSupplement(builder)` | Адитивний розділ prompt, суміжний із memory | -| `api.registerMemoryCorpusSupplement(adapter)` | Адитивний corpus для пошуку/читання memory | +| Метод | Що реєструє | +| --------------------------------------------- | -------------------------------------- | +| `api.registerHook(events, handler, opts?)` | Hook подій | +| `api.registerHttpRoute(params)` | HTTP endpoint Gateway | +| `api.registerGatewayMethod(name, handler)` | RPC-метод Gateway | +| `api.registerCli(registrar, opts?)` | Підкоманда CLI | +| `api.registerService(service)` | Фонова служба | +| `api.registerInteractiveHandler(registration)` | Інтерактивний handler | +| `api.registerMemoryPromptSupplement(builder)` | Адитивний розділ prompt, суміжний із memory | +| `api.registerMemoryCorpusSupplement(adapter)` | Адитивний corpus для пошуку/читання memory | Зарезервовані простори імен адміністрування ядра (`config.*`, `exec.approvals.*`, `wizard.*`, `update.*`) завжди залишаються `operator.admin`, навіть якщо plugin намагається призначити -вужчу область gateway method. Для методів, що належать plugin-у, надавайте перевагу префіксам, специфічним для plugin-а. +вужчу область видимості методу Gateway. Для методів, що належать plugin-у, +віддавайте перевагу префіксам, специфічним для plugin-а. ### Метадані реєстрації CLI `api.registerCli(registrar, opts?)` приймає два типи метаданих верхнього рівня: -- `commands`: явні корені команд, якими володіє registrar -- `descriptors`: дескриптори команд на етапі парсингу, що використовуються для кореневої довідки CLI, - маршрутизації та lazy реєстрації CLI plugin-а +- `commands`: явні корені команд, що належать registrar-у +- `descriptors`: дескриптори команд на етапі парсингу, які використовуються для кореневої довідки CLI, + маршрутизації та lazy-реєстрації CLI plugin-а -Якщо ви хочете, щоб команда plugin-а залишалася lazy-loaded у звичайному шляху кореневого CLI, -надайте `descriptors`, які охоплюють кожен корінь команди верхнього рівня, що його експонує +Якщо ви хочете, щоб команда plugin-а залишалася lazy-loaded у звичайному кореневому шляху CLI, +надайте `descriptors`, що охоплюють кожен корінь команди верхнього рівня, який відкриває цей registrar. ```typescript @@ -386,7 +388,7 @@ api.registerCli( descriptors: [ { name: "matrix", - description: "Керування обліковими записами Matrix, верифікацією, пристроями та станом профілю", + description: "Керування акаунтами Matrix, верифікацією, пристроями та станом профілю", hasSubcommands: true, }, ], @@ -394,96 +396,96 @@ api.registerCli( ); ``` -Використовуйте лише `commands`, коли вам не потрібна lazy реєстрація кореневого CLI. -Цей eager-сумісний шлях залишається підтримуваним, але він не встановлює -placeholders на основі descriptor для lazy loading на етапі парсингу. +Використовуйте лише `commands`, коли вам не потрібна lazy-реєстрація кореневого CLI. +Цей eager-шлях сумісності залишається підтримуваним, але він не встановлює +placeholder-и на основі descriptor для lazy-завантаження на етапі парсингу. ### Реєстрація CLI backend `api.registerCliBackend(...)` дає plugin-у змогу володіти конфігурацією за замовчуванням для локального -backend AI CLI, такого як `codex-cli`. +AI CLI backend, такого як `codex-cli`. -- `id` backend стає префіксом provider у посиланнях на model, таких як `codex-cli/gpt-5`. -- `config` backend використовує ту саму форму, що й `agents.defaults.cliBackends.`. -- Конфігурація користувача все одно має пріоритет. OpenClaw зливає `agents.defaults.cliBackends.` поверх +- `id` backend-у стає префіксом provider-а в model ref, наприклад `codex-cli/gpt-5`. +- `config` backend-у використовує ту саму форму, що й `agents.defaults.cliBackends.`. +- Конфігурація користувача все одно має перевагу. OpenClaw об’єднує `agents.defaults.cliBackends.` поверх значення plugin-а за замовчуванням перед запуском CLI. - Використовуйте `normalizeConfig`, коли backend потребує переписувань для сумісності після злиття - (наприклад, нормалізація старих форм прапорців). + (наприклад, для нормалізації старих форм прапорців). ### Ексклюзивні слоти -| Method | Що він реєструє | -| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| `api.registerContextEngine(id, factory)` | Контекстний engine (лише один активний одночасно). Зворотний виклик `assemble()` отримує `availableTools` і `citationsMode`, щоб engine міг налаштовувати додавання до prompt. | -| `api.registerMemoryCapability(capability)` | Уніфікована можливість memory | -| `api.registerMemoryPromptSection(builder)` | Будівник розділу prompt для memory | -| `api.registerMemoryFlushPlan(resolver)` | Resolver плану flush для memory | -| `api.registerMemoryRuntime(runtime)` | Адаптер runtime memory | +| Метод | Що реєструє | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| `api.registerContextEngine(id, factory)` | Context engine (лише один активний одночасно). Зворотний виклик `assemble()` отримує `availableTools` і `citationsMode`, щоб engine міг адаптувати доповнення до prompt. | +| `api.registerMemoryCapability(capability)` | Уніфіковану capability memory | +| `api.registerMemoryPromptSection(builder)` | Builder розділу prompt для memory | +| `api.registerMemoryFlushPlan(resolver)` | Resolver плану flush для memory | +| `api.registerMemoryRuntime(runtime)` | Адаптер runtime для memory | -### Адаптери embedding для memory +### Адаптери embedding для Memory -| Method | Що він реєструє | -| ---------------------------------------------- | -------------------------------------------- | -| `api.registerMemoryEmbeddingProvider(adapter)` | Адаптер embedding для memory для активного plugin-а | +| Метод | Що реєструє | +| --------------------------------------------- | -------------------------------------------- | +| `api.registerMemoryEmbeddingProvider(adapter)` | Адаптер embedding для Memory для активного plugin-а | - `registerMemoryCapability` — це рекомендований API ексклюзивного plugin-а memory. -- `registerMemoryCapability` також може експонувати `publicArtifacts.listArtifacts(...)`, +- `registerMemoryCapability` також може надавати `publicArtifacts.listArtifacts(...)`, щоб companion plugin-и могли споживати експортовані артефакти memory через - `openclaw/plugin-sdk/memory-host-core` замість звернення до приватної структури + `openclaw/plugin-sdk/memory-host-core`, а не звертатися до приватного layout конкретного plugin-а memory. - `registerMemoryPromptSection`, `registerMemoryFlushPlan` і - `registerMemoryRuntime` — це застаріло-сумісні API ексклюзивних plugin-ів memory. -- `registerMemoryEmbeddingProvider` дає активному plugin-у memory змогу реєструвати один - або більше id адаптерів embedding (наприклад, `openai`, `gemini` або власний id, + `registerMemoryRuntime` — це застарілі, але сумісні API ексклюзивних plugin-ів memory. +- `registerMemoryEmbeddingProvider` дає активному plugin-у memory змогу зареєструвати один + або більше id адаптерів embedding (наприклад, `openai`, `gemini` або користувацький id, визначений plugin-ом). - Конфігурація користувача, така як `agents.defaults.memorySearch.provider` і - `agents.defaults.memorySearch.fallback`, визначається відносно зареєстрованих id - цих адаптерів. + `agents.defaults.memorySearch.fallback`, визначається відносно зареєстрованих id цих + адаптерів. ### Події та життєвий цикл -| Method | Що він робить | -| -------------------------------------------- | -------------------------- | -| `api.on(hookName, handler, opts?)` | Типізований hook життєвого циклу | +| Метод | Що робить | +| ------------------------------------------- | ------------------------- | +| `api.on(hookName, handler, opts?)` | Типізований hook життєвого циклу | | `api.onConversationBindingResolved(handler)` | Зворотний виклик прив’язки conversation | ### Семантика рішень hook-ів -- `before_tool_call`: повернення `{ block: true }` є термінальним. Щойно будь-який обробник встановлює це значення, обробники з нижчим пріоритетом пропускаються. +- `before_tool_call`: повернення `{ block: true }` є термінальним. Щойно будь-який handler встановлює це значення, handler-и з нижчим пріоритетом пропускаються. - `before_tool_call`: повернення `{ block: false }` вважається відсутністю рішення (так само, як і пропуск `block`), а не перевизначенням. -- `before_install`: повернення `{ block: true }` є термінальним. Щойно будь-який обробник встановлює це значення, обробники з нижчим пріоритетом пропускаються. +- `before_install`: повернення `{ block: true }` є термінальним. Щойно будь-який handler встановлює це значення, handler-и з нижчим пріоритетом пропускаються. - `before_install`: повернення `{ block: false }` вважається відсутністю рішення (так само, як і пропуск `block`), а не перевизначенням. -- `reply_dispatch`: повернення `{ handled: true, ... }` є термінальним. Щойно будь-який обробник бере dispatch на себе, обробники з нижчим пріоритетом і стандартний шлях dispatch моделі пропускаються. -- `message_sending`: повернення `{ cancel: true }` є термінальним. Щойно будь-який обробник встановлює це значення, обробники з нижчим пріоритетом пропускаються. +- `reply_dispatch`: повернення `{ handled: true, ... }` є термінальним. Щойно будь-який handler заявляє про dispatch, handler-и з нижчим пріоритетом і стандартний шлях dispatch моделі пропускаються. +- `message_sending`: повернення `{ cancel: true }` є термінальним. Щойно будь-який handler встановлює це значення, handler-и з нижчим пріоритетом пропускаються. - `message_sending`: повернення `{ cancel: false }` вважається відсутністю рішення (так само, як і пропуск `cancel`), а не перевизначенням. ### Поля об’єкта API -| Field | Type | Опис | +| Поле | Тип | Опис | | ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------- | | `api.id` | `string` | ID plugin-а | | `api.name` | `string` | Відображувана назва | | `api.version` | `string?` | Версія plugin-а (необов’язково) | | `api.description` | `string?` | Опис plugin-а (необов’язково) | | `api.source` | `string` | Шлях до джерела plugin-а | -| `api.rootDir` | `string?` | Кореневий каталог plugin-а (необов’язково) | -| `api.config` | `OpenClawConfig` | Поточний snapshot конфігурації (активний snapshot runtime в пам’яті, коли доступний) | -| `api.pluginConfig` | `Record` | Конфігурація, специфічна для plugin-а, з `plugins.entries..config` | +| `api.rootDir` | `string?` | Коренева директорія plugin-а (необов’язково) | +| `api.config` | `OpenClawConfig` | Поточний snapshot конфігурації (активний snapshot runtime у пам’яті, якщо доступний) | +| `api.pluginConfig` | `Record` | Специфічна для plugin-а конфігурація з `plugins.entries..config` | | `api.runtime` | `PluginRuntime` | [Допоміжні засоби runtime](/uk/plugins/sdk-runtime) | | `api.logger` | `PluginLogger` | Logger з областю видимості (`debug`, `info`, `warn`, `error`) | | `api.registrationMode` | `PluginRegistrationMode` | Поточний режим завантаження; `"setup-runtime"` — це полегшене вікно запуску/налаштування до повного entry | | `api.resolvePath(input)` | `(string) => string` | Визначення шляху відносно кореня plugin-а | -## Угода щодо внутрішніх модулів +## Внутрішня угода щодо модулів Усередині вашого plugin-а використовуйте локальні barrel-файли для внутрішніх імпортів: ``` my-plugin/ api.ts # Публічні експорти для зовнішніх споживачів - runtime-api.ts # Експорти runtime лише для внутрішнього використання + runtime-api.ts # Лише внутрішні експорти runtime index.ts # Точка входу plugin-а - setup-entry.ts # Полегшений entry лише для налаштування (необов’язково) + setup-entry.ts # Полегшена точка входу лише для налаштування (необов’язково) ``` @@ -492,37 +494,37 @@ my-plugin/ `./runtime-api.ts`. Шлях SDK — це лише зовнішній контракт. -Facade-loaded публічні поверхні вбудованих plugin-ів (`api.ts`, `runtime-api.ts`, -`index.ts`, `setup-entry.ts` та подібні публічні entry-файли) тепер надають перевагу -активному snapshot конфігурації runtime, коли OpenClaw уже запущено. Якщо snapshot runtime -ще не існує, вони повертаються до конфігураційного файла, визначеного на диску. +Публічні поверхні вбудованих plugin-ів, завантажувані через facade (`api.ts`, `runtime-api.ts`, +`index.ts`, `setup-entry.ts` та подібні публічні entry-файли), тепер віддають перевагу +активному snapshot конфігурації runtime, коли OpenClaw уже запущений. Якщо snapshot +runtime ще не існує, вони повертаються до визначеного файла конфігурації на диску. -Provider plugin-и також можуть експонувати вузький локальний barrel контракту plugin-а, коли -допоміжний засіб навмисно є специфічним для provider-а й поки що не належить до загального -підшляху SDK. Поточний вбудований приклад: provider Anthropic зберігає свої допоміжні -засоби потоку Claude у власному публічному seam `api.ts` / `contract-api.ts` замість -просування логіки beta-header Anthropic і `service_tier` у загальний контракт -`plugin-sdk/*`. +Plugin-и provider-ів також можуть надавати вузький локальний barrel контракту plugin-а, коли +допоміжний засіб навмисно є специфічним для provider-а і ще не належить до +узагальненого підшляху SDK. Поточний вбудований приклад: provider Anthropic зберігає свої +допоміжні засоби потоку Claude у власному публічному шарі `api.ts` / `contract-api.ts` замість +просування логіки beta-header Anthropic і `service_tier` до узагальненого +контракту `plugin-sdk/*`. Інші поточні вбудовані приклади: -- `@openclaw/openai-provider`: `api.ts` експортує будівники provider-ів, - допоміжні засоби model за замовчуванням і будівники provider-ів realtime -- `@openclaw/openrouter-provider`: `api.ts` експортує будівник provider-а, а також +- `@openclaw/openai-provider`: `api.ts` експортує builder-и provider-а, + допоміжні засоби моделей за замовчуванням і builder-и provider-а realtime +- `@openclaw/openrouter-provider`: `api.ts` експортує builder provider-а, а також допоміжні засоби onboarding/config Production-код extension також має уникати імпортів `openclaw/plugin-sdk/`. - Якщо допоміжний засіб справді є спільним, підніміть його до нейтрального підшляху SDK, + Якщо допоміжний засіб справді є спільним, просуньте його до нейтрального підшляху SDK, такого як `openclaw/plugin-sdk/speech`, `.../provider-model-shared` або іншої - поверхні, орієнтованої на можливості, замість того щоб жорстко зв’язувати два plugin-и між собою. + поверхні, орієнтованої на capability, замість того щоб зв’язувати два plugin-и між собою. ## Пов’язане -- [Точки входу](/uk/plugins/sdk-entrypoints) — параметри `definePluginEntry` і `defineChannelPluginEntry` -- [Допоміжні засоби runtime](/uk/plugins/sdk-runtime) — повний довідник простору імен `api.runtime` -- [Налаштування та конфігурація](/uk/plugins/sdk-setup) — пакування, маніфести, схеми конфігурації -- [Тестування](/uk/plugins/sdk-testing) — утиліти тестування та правила lint -- [Міграція SDK](/uk/plugins/sdk-migration) — міграція із застарілих поверхонь -- [Внутрішня будова plugin-ів](/uk/plugins/architecture) — поглиблена архітектура та модель можливостей +- [Entry Points](/uk/plugins/sdk-entrypoints) — параметри `definePluginEntry` і `defineChannelPluginEntry` +- [Runtime Helpers](/uk/plugins/sdk-runtime) — повний довідник простору імен `api.runtime` +- [Setup and Config](/uk/plugins/sdk-setup) — пакування, маніфести, схеми конфігурації +- [Testing](/uk/plugins/sdk-testing) — утиліти тестування та правила lint +- [SDK Migration](/uk/plugins/sdk-migration) — міграція із застарілих поверхонь +- [Plugin Internals](/uk/plugins/architecture) — детальна архітектура та модель capability diff --git a/docs/uk/plugins/skill-workshop.md b/docs/uk/plugins/skill-workshop.md new file mode 100644 index 000000000..b0ad2a8e3 --- /dev/null +++ b/docs/uk/plugins/skill-workshop.md @@ -0,0 +1,737 @@ +--- +read_when: + - Ви хочете, щоб агенти перетворювали виправлення або багаторазово використовувані процедури на Skills робочого простору + - Ви налаштовуєте пам’ять процедурних Skills + - Ви налагоджуєте поведінку інструмента skill_workshop + - Ви вирішуєте, чи вмикати автоматичне створення Skills +summary: Експериментальне фіксування багаторазово використовуваних процедур як навичок робочого простору з перевіркою, схваленням, карантином і гарячим оновленням Skills +title: Plugin Skill Workshop +x-i18n: + generated_at: "2026-04-21T20:38:18Z" + model: gpt-5.4 + provider: openai + source_hash: 62dcb3e1a71999bfc39a95dc3d0984d3446c8a58f7d91a914dfc7256b4e79601 + source_path: plugins/skill-workshop.md + workflow: 15 +--- + +# Plugin Skill Workshop + +Skill Workshop — **експериментальний**. Він вимкнений за замовчуванням, його +евристики фіксування та запити для рецензента можуть змінюватися між випусками, а автоматичні +записи слід використовувати лише в довірених робочих просторах після попереднього перегляду +виводу в режимі очікування схвалення. + +Skill Workshop — це процедурна пам’ять для Skills робочого простору. Він дає змогу агенту перетворювати +багаторазово використовувані робочі процеси, виправлення від користувача, важко здобуті рішення та повторювані проблеми +на файли `SKILL.md` у каталозі: + +```text +/skills//SKILL.md +``` + +Це відрізняється від довготривалої пам’яті: + +- **Memory** зберігає факти, уподобання, сутності та минулий контекст. +- **Skills** зберігають багаторазово використовувані процедури, яких агент має дотримуватися в майбутніх завданнях. +- **Skill Workshop** — це міст від корисного ходу до довговічної навички робочого простору + із перевірками безпеки та необов’язковим схваленням. + +Skill Workshop корисний, коли агент вивчає процедуру, таку як: + +- як перевіряти анімовані GIF-ресурси із зовнішніх джерел +- як замінювати ресурси зі знімками екрана та перевіряти розміри +- як запускати специфічний для репозиторію QA-сценарій +- як налагоджувати повторюваний збій provider +- як виправляти застарілу локальну примітку робочого процесу + +Він не призначений для: + +- фактів на кшталт «користувачеві подобається синій» +- широкої автобіографічної пам’яті +- архівування сирих транскриптів +- секретів, облікових даних або прихованого тексту запитів +- одноразових інструкцій, які не повторюватимуться + +## Стан за замовчуванням + +Вбудований plugin є **експериментальним** і **вимкненим за замовчуванням**, якщо його +явно не ввімкнено в `plugins.entries.skill-workshop`. + +Маніфест plugin не встановлює `enabledByDefault: true`. Значення `enabled: true` +за замовчуванням усередині схеми конфігурації plugin застосовується лише після того, як запис plugin +уже було вибрано та завантажено. + +Експериментальний статус означає: + +- plugin достатньо підтримується для добровільного тестування та внутрішнього використання +- сховище пропозицій, пороги рецензування та евристики фіксування можуть розвиватися +- режим очікування схвалення є рекомендованим початковим режимом +- автоматичне застосування призначене для довірених персональних/робочих середовищ, а не для спільних або ворожих середовищ із великою кількістю вхідних даних + +## Увімкнення + +Мінімальна безпечна конфігурація: + +```json5 +{ + plugins: { + entries: { + "skill-workshop": { + enabled: true, + config: { + autoCapture: true, + approvalPolicy: "pending", + reviewMode: "hybrid", + }, + }, + }, + }, +} +``` + +За такої конфігурації: + +- інструмент `skill_workshop` доступний +- явні багаторазово використовувані виправлення ставляться в чергу як пропозиції, що очікують схвалення +- проходи рецензента на основі порогів можуть пропонувати оновлення Skills +- жоден файл Skill не записується, доки пропозицію, що очікує схвалення, не буде застосовано + +Використовуйте автоматичний запис лише в довірених робочих просторах: + +```json5 +{ + plugins: { + entries: { + "skill-workshop": { + enabled: true, + config: { + autoCapture: true, + approvalPolicy: "auto", + reviewMode: "hybrid", + }, + }, + }, + }, +} +``` + +`approvalPolicy: "auto"` усе одно використовує той самий сканер і шлях карантину. Він +не застосовує пропозиції з критичними результатами перевірки. + +## Конфігурація + +| Ключ | За замовчуванням | Діапазон / значення | Значення | +| -------------------- | ---------------- | -------------------------------------------- | -------------------------------------------------------------------- | +| `enabled` | `true` | boolean | Вмикає plugin після завантаження запису plugin. | +| `autoCapture` | `true` | boolean | Вмикає фіксування/рецензування після ходу на успішних ходах агента. | +| `approvalPolicy` | `"pending"` | `"pending"`, `"auto"` | Ставити пропозиції в чергу або автоматично записувати безпечні. | +| `reviewMode` | `"hybrid"` | `"off"`, `"heuristic"`, `"llm"`, `"hybrid"` | Вибирає явне фіксування виправлень, LLM-рецензента, обидва варіанти або жоден. | +| `reviewInterval` | `15` | `1..200` | Запускати рецензента після такої кількості успішних ходів. | +| `reviewMinToolCalls` | `8` | `1..500` | Запускати рецензента після такої кількості зафіксованих викликів інструментів. | +| `reviewTimeoutMs` | `45000` | `5000..180000` | Тайм-аут для вбудованого запуску рецензента. | +| `maxPending` | `50` | `1..200` | Максимум пропозицій у стані очікування/карантину на робочий простір. | +| `maxSkillBytes` | `40000` | `1024..200000` | Максимальний розмір згенерованого файлу Skill/допоміжного файла. | + +Рекомендовані профілі: + +```json5 +// Консервативний: лише явне використання інструмента, без автоматичного фіксування. +{ + autoCapture: false, + approvalPolicy: "pending", + reviewMode: "off", +} +``` + +```json5 +// Спочатку рецензування: фіксувати автоматично, але вимагати схвалення. +{ + autoCapture: true, + approvalPolicy: "pending", + reviewMode: "hybrid", +} +``` + +```json5 +// Довірена автоматизація: негайно записувати безпечні пропозиції. +{ + autoCapture: true, + approvalPolicy: "auto", + reviewMode: "hybrid", +} +``` + +```json5 +// Низька вартість: без виклику LLM-рецензента, лише явні фрази виправлень. +{ + autoCapture: true, + approvalPolicy: "pending", + reviewMode: "heuristic", +} +``` + +## Шляхи фіксування + +Skill Workshop має три шляхи фіксування. + +### Пропозиції інструмента + +Модель може напряму викликати `skill_workshop`, коли бачить багаторазово використовувану процедуру +або коли користувач просить її зберегти/оновити Skill. + +Це найбільш явний шлях, і він працює навіть із `autoCapture: false`. + +### Евристичне фіксування + +Коли `autoCapture` увімкнено, а `reviewMode` має значення `heuristic` або `hybrid`, plugin +сканує успішні ходи на наявність явних фраз виправлення від користувача: + +- `next time` +- `from now on` +- `remember to` +- `make sure to` +- `always ... use/check/verify/record/save/prefer` +- `prefer ... when/for/instead/use` +- `when asked` + +Евристика створює пропозицію на основі останньої відповідної інструкції користувача. Вона +використовує підказки теми для вибору назв Skills для поширених робочих процесів: + +- завдання з анімованими GIF -> `animated-gif-workflow` +- завдання зі знімками екрана або ресурсами -> `screenshot-asset-workflow` +- завдання QA або сценаріїв -> `qa-scenario-workflow` +- завдання з GitHub PR -> `github-pr-workflow` +- резервний варіант -> `learned-workflows` + +Евристичне фіксування навмисно вузьке. Воно призначене для чітких виправлень і +повторюваних приміток щодо процесу, а не для загального підсумовування транскриптів. + +### LLM-рецензент + +Коли `autoCapture` увімкнено, а `reviewMode` має значення `llm` або `hybrid`, plugin +запускає компактного вбудованого рецензента після досягнення порогів. + +Рецензент отримує: + +- текст нещодавнього транскрипту, обмежений останніми 12 000 символів +- до 12 наявних Skills робочого простору +- до 2 000 символів із кожного наявного Skill +- інструкції лише у форматі JSON + +Рецензент не має інструментів: + +- `disableTools: true` +- `toolsAllow: []` +- `disableMessageTool: true` + +Він може повернути: + +```json +{ "action": "none" } +``` + +або одну пропозицію Skill: + +```json +{ + "action": "create", + "skillName": "media-asset-qa", + "title": "Media Asset QA", + "reason": "Reusable animated media acceptance workflow", + "description": "Validate externally sourced animated media before product use.", + "body": "## Workflow\n\n- Verify true animation.\n- Record attribution.\n- Store a local approved copy.\n- Verify in product UI before final reply." +} +``` + +Він також може додати до наявного Skill: + +```json +{ + "action": "append", + "skillName": "qa-scenario-workflow", + "title": "QA Scenario Workflow", + "reason": "Animated media QA needs reusable checks", + "description": "QA scenario workflow.", + "section": "Workflow", + "body": "- For animated GIF tasks, verify frame count and attribution before passing." +} +``` + +Або замінити точний текст у наявному Skill: + +```json +{ + "action": "replace", + "skillName": "screenshot-asset-workflow", + "title": "Screenshot Asset Workflow", + "reason": "Old validation missed image optimization", + "oldText": "- Replace the screenshot asset.", + "newText": "- Replace the screenshot asset, preserve dimensions, optimize the PNG, and run the relevant validation gate." +} +``` + +Надавайте перевагу `append` або `replace`, коли вже існує відповідний Skill. Використовуйте `create` +лише тоді, коли жоден наявний Skill не підходить. + +## Життєвий цикл пропозиції + +Кожне згенероване оновлення стає пропозицією з такими полями: + +- `id` +- `createdAt` +- `updatedAt` +- `workspaceDir` +- необов’язковий `agentId` +- необов’язковий `sessionId` +- `skillName` +- `title` +- `reason` +- `source`: `tool`, `agent_end` або `reviewer` +- `status` +- `change` +- необов’язкові `scanFindings` +- необов’язкова `quarantineReason` + +Стани пропозиції: + +- `pending` — очікує схвалення +- `applied` — записана в `/skills` +- `rejected` — відхилена оператором/моделлю +- `quarantined` — заблокована через критичні результати сканування + +Стан зберігається окремо для кожного робочого простору в каталозі стану Gateway: + +```text +/skill-workshop/.json +``` + +Пропозиції в стані очікування та карантину дедуплікуються за назвою Skill і payload +зміни. Сховище зберігає найновіші пропозиції в стані очікування/карантину в межах +`maxPending`. + +## Довідка з інструмента + +Plugin реєструє один інструмент агента: + +```text +skill_workshop +``` + +### `status` + +Підрахувати пропозиції за станом для активного робочого простору. + +```json +{ "action": "status" } +``` + +Форма результату: + +```json +{ + "workspaceDir": "/path/to/workspace", + "pending": 1, + "quarantined": 0, + "applied": 3, + "rejected": 0 +} +``` + +### `list_pending` + +Показати пропозиції, що очікують схвалення. + +```json +{ "action": "list_pending" } +``` + +Щоб показати інший стан: + +```json +{ "action": "list_pending", "status": "applied" } +``` + +Допустимі значення `status`: + +- `pending` +- `applied` +- `rejected` +- `quarantined` + +### `list_quarantine` + +Показати пропозиції в карантині. + +```json +{ "action": "list_quarantine" } +``` + +Використовуйте це, коли здається, що автоматичне фіксування нічого не робить, а в журналах згадується +`skill-workshop: quarantined `. + +### `inspect` + +Отримати пропозицію за id. + +```json +{ + "action": "inspect", + "id": "proposal-id" +} +``` + +### `suggest` + +Створити пропозицію. Із `approvalPolicy: "pending"` це за замовчуванням ставить її в чергу. + +```json +{ + "action": "suggest", + "skillName": "animated-gif-workflow", + "title": "Animated GIF Workflow", + "reason": "User established reusable GIF validation rules.", + "description": "Validate animated GIF assets before using them.", + "body": "## Workflow\n\n- Verify the URL resolves to image/gif.\n- Confirm it has multiple frames.\n- Record attribution and license.\n- Avoid hotlinking when a local asset is needed." +} +``` + +Примусово виконати безпечний запис: + +```json +{ + "action": "suggest", + "apply": true, + "skillName": "animated-gif-workflow", + "description": "Validate animated GIF assets before using them.", + "body": "## Workflow\n\n- Verify true animation.\n- Record attribution." +} +``` + +Примусово залишити в стані очікування навіть за `approvalPolicy: "auto"`: + +```json +{ + "action": "suggest", + "apply": false, + "skillName": "screenshot-asset-workflow", + "description": "Screenshot replacement workflow.", + "body": "## Workflow\n\n- Verify dimensions.\n- Optimize the PNG.\n- Run the relevant gate." +} +``` + +Додати до розділу: + +```json +{ + "action": "suggest", + "skillName": "qa-scenario-workflow", + "section": "Workflow", + "description": "QA scenario workflow.", + "body": "- For media QA, verify generated assets render and pass final assertions." +} +``` + +Замінити точний текст: + +```json +{ + "action": "suggest", + "skillName": "github-pr-workflow", + "oldText": "- Check the PR.", + "newText": "- Check unresolved review threads, CI status, linked issues, and changed files before deciding." +} +``` + +### `apply` + +Застосувати пропозицію, що очікує схвалення. + +```json +{ + "action": "apply", + "id": "proposal-id" +} +``` + +`apply` відмовляється застосовувати пропозиції в карантині: + +```text +quarantined proposal cannot be applied +``` + +### `reject` + +Позначити пропозицію як відхилену. + +```json +{ + "action": "reject", + "id": "proposal-id" +} +``` + +### `write_support_file` + +Записати допоміжний файл усередині каталогу наявного або запропонованого Skill. + +Дозволені каталоги підтримки верхнього рівня: + +- `references/` +- `templates/` +- `scripts/` +- `assets/` + +Приклад: + +```json +{ + "action": "write_support_file", + "skillName": "release-workflow", + "relativePath": "references/checklist.md", + "body": "# Release Checklist\n\n- Run release docs.\n- Verify changelog.\n" +} +``` + +Файли підтримки мають область робочого простору, проходять перевірку шляху, обмежуються за розміром байтів через +`maxSkillBytes`, скануються та записуються атомарно. + +## Запис Skills + +Skill Workshop записує лише в: + +```text +/skills// +``` + +Назви Skills нормалізуються: + +- переводяться в нижній регістр +- послідовності символів, що не належать до `[a-z0-9_-]`, замінюються на `-` +- початкові/кінцеві неалфавітно-цифрові символи видаляються +- максимальна довжина — 80 символів +- остаточна назва має відповідати шаблону `[a-z0-9][a-z0-9_-]{1,79}` + +Для `create`: + +- якщо Skill не існує, Skill Workshop записує новий `SKILL.md` +- якщо він уже існує, Skill Workshop додає вміст до `## Workflow` + +Для `append`: + +- якщо Skill існує, Skill Workshop додає вміст до запитаного розділу +- якщо його не існує, Skill Workshop створює мінімальний Skill, а потім додає вміст + +Для `replace`: + +- Skill уже має існувати +- `oldText` має бути присутнім у точному вигляді +- замінюється лише перший точний збіг + +Усі записи є атомарними та негайно оновлюють знімок Skills у пам’яті, тому +новий або оновлений Skill може стати видимим без перезапуску Gateway. + +## Модель безпеки + +Skill Workshop має сканер безпеки для згенерованого вмісту `SKILL.md` і файлів +підтримки. + +Критичні результати переводять пропозиції в карантин: + +| Ідентифікатор правила | Блокує вміст, який... | +| -------------------------------------- | -------------------------------------------------------------------- | +| `prompt-injection-ignore-instructions` | наказує агенту ігнорувати попередні/вищі інструкції | +| `prompt-injection-system` | посилається на системні запити, повідомлення розробника або приховані інструкції | +| `prompt-injection-tool` | заохочує обходити дозвіл/схвалення інструмента | +| `shell-pipe-to-shell` | містить `curl`/`wget`, передані через pipe у `sh`, `bash` або `zsh` | +| `secret-exfiltration` | виглядає як надсилання даних env/process env мережею | + +Попереджувальні результати зберігаються, але самі по собі не блокують: + +| Ідентифікатор правила | Попереджає про... | +| --------------------- | --------------------------------- | +| `destructive-delete` | широкі команди у стилі `rm -rf` | +| `unsafe-permissions` | використання дозволів у стилі `chmod 777` | + +Пропозиції в карантині: + +- зберігають `scanFindings` +- зберігають `quarantineReason` +- відображаються в `list_quarantine` +- не можуть бути застосовані через `apply` + +Щоб відновитися після пропозиції в карантині, створіть нову безпечну пропозицію без +небезпечного вмісту. Не редагуйте JSON сховища вручну. + +## Рекомендації щодо запитів + +Коли ввімкнений, Skill Workshop додає короткий розділ запиту, який інструктує агента +використовувати `skill_workshop` для довговічної процедурної пам’яті. + +Рекомендації наголошують на: + +- процедурах, а не фактах/уподобаннях +- виправленнях від користувача +- неочевидних успішних процедурах +- повторюваних проблемах +- виправленні застарілих/надто коротких/неправильних Skills через append/replace +- збереженні багаторазово використовуваної процедури після довгих циклів інструментів або складних виправлень +- короткому наказовому тексті Skill +- відсутності дампів транскриптів + +Текст режиму запису змінюється залежно від `approvalPolicy`: + +- режим pending: ставити пропозиції в чергу; застосовувати лише після явного схвалення +- режим auto: застосовувати безпечні оновлення Skills робочого простору, коли вони явно багаторазово використовувані + +## Вартість і поведінка під час виконання + +Евристичне фіксування не викликає модель. + +LLM-рецензування використовує вбудований запуск на активній/стандартній моделі агента. Воно +залежить від порогів, тому за замовчуванням не запускається на кожному ході. + +Рецензент: + +- використовує той самий налаштований контекст provider/model, коли він доступний +- інакше повертається до стандартних значень агента під час виконання +- має `reviewTimeoutMs` +- використовує легкий bootstrap-контекст +- не має інструментів +- нічого не записує напряму +- може лише створити пропозицію, яка проходить звичайний сканер та + шлях схвалення/карантину + +Якщо рецензент завершується помилкою, перевищує час очікування або повертає недійсний JSON, plugin записує +попереджувальне/налагоджувальне повідомлення в журнал і пропускає цей прохід рецензування. + +## Типові шаблони використання + +Використовуйте Skill Workshop, коли користувач каже: + +- «наступного разу роби X» +- «відтепер надавай перевагу Y» +- «обов’язково перевіряй Z» +- «збережи це як робочий процес» +- «це зайняло багато часу; запам’ятай процес» +- «онови локальний Skill для цього» + +Хороший текст Skill: + +```markdown +## Workflow + +- Перевірте, що URL GIF веде до `image/gif`. +- Підтвердьте, що файл має кілька кадрів. +- Зафіксуйте URL джерела, ліцензію та атрибуцію. +- Збережіть локальну копію, якщо ресурс постачатиметься разом із продуктом. +- Перевірте, що локальний ресурс відображається в цільовому UI, перш ніж давати остаточну відповідь. +``` + +Поганий текст Skill: + +```markdown +The user asked about a GIF and I searched two websites. Then one was blocked by +Cloudflare. The final answer said to check attribution. +``` + +Причини, чому погану версію не слід зберігати: + +- має форму транскрипту +- не є наказовою +- містить шумні одноразові подробиці +- не пояснює наступному агенту, що робити + +## Налагодження + +Перевірте, чи завантажено plugin: + +```bash +openclaw plugins list --enabled +``` + +Перевірте кількість пропозицій із контексту агента/інструмента: + +```json +{ "action": "status" } +``` + +Перегляньте пропозиції, що очікують схвалення: + +```json +{ "action": "list_pending" } +``` + +Перегляньте пропозиції в карантині: + +```json +{ "action": "list_quarantine" } +``` + +Поширені симптоми: + +| Симптом | Імовірна причина | Перевірка | +| ------------------------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------- | +| Інструмент недоступний | Запис plugin не ввімкнений | `plugins.entries.skill-workshop.enabled` і `openclaw plugins list` | +| Автоматична пропозиція не з’являється | `autoCapture: false`, `reviewMode: "off"` або пороги не досягнуто | Конфігурація, стан пропозицій, журнали Gateway | +| Евристика не зафіксувала | Формулювання користувача не відповідало шаблонам виправлень | Використайте явний `skill_workshop.suggest` або ввімкніть LLM-рецензента | +| Рецензент не створив пропозицію | Рецензент повернув `none`, недійсний JSON або перевищив час очікування | Журнали Gateway, `reviewTimeoutMs`, пороги | +| Пропозиція не застосовується | `approvalPolicy: "pending"` | `list_pending`, потім `apply` | +| Пропозиція зникла з pending | Було повторно використано дублікат пропозиції, спрацювало обрізання max pending або її застосовано/відхилено/переведено в карантин | `status`, `list_pending` з фільтрами status, `list_quarantine` | +| Файл Skill існує, але модель його пропускає | Знімок Skills не оновився або gating Skills виключає його | стан `openclaw skills` і придатність Skill робочого простору | + +Відповідні журнали: + +- `skill-workshop: queued ` +- `skill-workshop: applied ` +- `skill-workshop: quarantined ` +- `skill-workshop: heuristic capture skipped: ...` +- `skill-workshop: reviewer skipped: ...` +- `skill-workshop: reviewer found no update` + +## QA-сценарії + +QA-сценарії з прив’язкою до репозиторію: + +- `qa/scenarios/plugins/skill-workshop-animated-gif-autocreate.md` +- `qa/scenarios/plugins/skill-workshop-pending-approval.md` +- `qa/scenarios/plugins/skill-workshop-reviewer-autonomous.md` + +Запустіть детерміноване покриття: + +```bash +pnpm openclaw qa suite \ + --scenario skill-workshop-animated-gif-autocreate \ + --scenario skill-workshop-pending-approval \ + --concurrency 1 +``` + +Запустіть покриття рецензента: + +```bash +pnpm openclaw qa suite \ + --scenario skill-workshop-reviewer-autonomous \ + --concurrency 1 +``` + +Сценарій рецензента навмисно винесений окремо, оскільки він вмикає +`reviewMode: "llm"` і перевіряє вбудований прохід рецензента. + +## Коли не слід вмикати Auto Apply + +Уникайте `approvalPolicy: "auto"`, коли: + +- робочий простір містить чутливі процедури +- агент працює з недовіреним вхідним вмістом +- Skills спільно використовуються широкою командою +- ви все ще налаштовуєте запити або правила сканера +- модель часто обробляє ворожий вміст із web/email + +Спочатку використовуйте режим pending. Перемикайтеся на режим auto лише після перегляду того, які +Skills агент пропонує в цьому робочому просторі. + +## Пов’язана документація + +- [Skills](/uk/tools/skills) +- [Plugins](/uk/tools/plugin) +- [Testing](/uk/reference/test) diff --git a/docs/uk/tools/skills.md b/docs/uk/tools/skills.md index e57e93791..10fad0d9e 100644 --- a/docs/uk/tools/skills.md +++ b/docs/uk/tools/skills.md @@ -1,57 +1,64 @@ --- read_when: - Додавання або змінення Skills - - Змінення правил гейтінгу або завантаження Skills -summary: 'Skills: керовані чи робочого простору, правила гейтінгу та налаштування config/env' + - Змінення правил gate або завантаження для Skills +summary: 'Skills: керовані проти робочого простору, правила gate і прив’язка config/env' title: Skills x-i18n: - generated_at: "2026-04-10T12:46:26Z" + generated_at: "2026-04-21T20:38:21Z" model: gpt-5.4 provider: openai - source_hash: b1eaf130966950b6eb24f859d9a77ecbf81c6cb80deaaa6a3a79d2c16d83115d + source_hash: c2ff6a3a92bc3c1c3892620a00e2eb01c73364bc6388a3513943defa46e49749 source_path: tools/skills.md workflow: 15 --- # Skills (OpenClaw) -OpenClaw використовує папки skill, **сумісні з [AgentSkills](https://agentskills.io)**, щоб навчати агента користуватися інструментами. Кожен skill — це каталог, що містить `SKILL.md` із YAML frontmatter та інструкціями. OpenClaw завантажує **вбудовані skills** разом з необов’язковими локальними перевизначеннями та фільтрує їх під час завантаження на основі середовища, конфігурації та наявності бінарних файлів. +OpenClaw використовує папки Skills, **сумісні з [AgentSkills](https://agentskills.io)**, щоб навчати агента користуватися інструментами. Кожен Skill — це директорія, що містить `SKILL.md` із YAML frontmatter та інструкціями. OpenClaw завантажує **вбудовані Skills** разом з необов’язковими локальними перевизначеннями та фільтрує їх під час завантаження на основі середовища, config і наявності бінарних файлів. ## Розташування та пріоритет -OpenClaw завантажує skills із таких джерел: +OpenClaw завантажує Skills із таких джерел: -1. **Додаткові папки skills**: налаштовуються через `skills.load.extraDirs` -2. **Вбудовані skills**: постачаються разом з інсталяцією (npm package або OpenClaw.app) -3. **Керовані/локальні skills**: `~/.openclaw/skills` -4. **Особисті agent skills**: `~/.agents/skills` -5. **Project agent skills**: `/.agents/skills` +1. **Додаткові папки Skills**: налаштовуються через `skills.load.extraDirs` +2. **Вбудовані Skills**: постачаються разом з інсталяцією (npm package або OpenClaw.app) +3. **Керовані/локальні Skills**: `~/.openclaw/skills` +4. **Персональні Skills агента**: `~/.agents/skills` +5. **Project agent Skills**: `/.agents/skills` 6. **Skills робочого простору**: `/skills` -Якщо назва skill конфліктує, пріоритет такий: +Якщо імена Skills конфліктують, пріоритет такий: -`/skills` (найвищий) → `/.agents/skills` → `~/.agents/skills` → `~/.openclaw/skills` → вбудовані skills → `skills.load.extraDirs` (найнижчий) +`/skills` (найвищий) → `/.agents/skills` → `~/.agents/skills` → `~/.openclaw/skills` → вбудовані Skills → `skills.load.extraDirs` (найнижчий) -## Skills для окремого агента та спільні skills +## Skills для окремого агента та спільні Skills -У конфігураціях **multi-agent** кожен агент має власний робочий простір. Це означає: +У конфігураціях **з кількома агентами** кожен агент має власний робочий простір. Це означає: -- **Skills для окремого агента** розміщуються в `/skills` лише для цього агента. -- **Project agent skills** розміщуються в `/.agents/skills` і застосовуються до цього робочого простору перед звичайною папкою `skills/` робочого простору. -- **Особисті agent skills** розміщуються в `~/.agents/skills` і застосовуються в усіх робочих просторах на цій машині. -- **Спільні skills** розміщуються в `~/.openclaw/skills` (керовані/локальні) і видимі **всім агентам** на цій самій машині. -- **Спільні папки** також можна додати через `skills.load.extraDirs` (найнижчий пріоритет), якщо ви хочете мати спільний набір skills, який використовується кількома агентами. +- **Skills окремого агента** розміщуються в `/skills` лише для цього агента. +- **Project agent Skills** розміщуються в `/.agents/skills` і застосовуються до + цього робочого простору перед звичайною папкою `skills/` робочого простору. +- **Персональні Skills агента** розміщуються в `~/.agents/skills` і застосовуються в усіх + робочих просторах на цій машині. +- **Спільні Skills** розміщуються в `~/.openclaw/skills` (керовані/локальні) і видимі + **всім агентам** на цій самій машині. +- **Спільні папки** також можна додати через `skills.load.extraDirs` (найнижчий + пріоритет), якщо ви хочете мати спільний набір Skills, який використовується кількома агентами. -Якщо одна й та сама назва skill існує в кількох місцях, діє звичайний пріоритет: перемагає workspace, потім project agent skills, потім personal agent skills, потім managed/local, потім bundled, потім extra dirs. +Якщо те саме ім’я Skill існує більш ніж в одному місці, застосовується звичайний +пріоритет: перемагає робочий простір, потім Project agent Skills, потім персональні Skills агента, +потім керовані/локальні, потім вбудовані, потім додаткові директорії. -## Allowlist skills для агентів +## Списки дозволених Skills для агента -**Розташування** skill і **видимість** skill — це окремі механізми керування. +**Розташування** Skill і **видимість** Skill — це окремі механізми керування. -- Розташування/пріоритет визначає, яка копія skill з однаковою назвою перемагає. -- Allowlist агента визначає, які видимі skills агент фактично може використовувати. +- Розташування/пріоритет визначає, яка копія Skill з однаковою назвою перемагає. +- Списки дозволених Skills для агента визначають, які видимі Skills агент справді може використовувати. -Використовуйте `agents.defaults.skills` для спільної базової конфігурації, а потім перевизначайте для окремих агентів через `agents.list[].skills`: +Використовуйте `agents.defaults.skills` для спільної базової конфігурації, а потім перевизначайте для окремого агента через +`agents.list[].skills`: ```json5 { @@ -61,8 +68,8 @@ OpenClaw завантажує skills із таких джерел: }, list: [ { id: "writer" }, // успадковує github, weather - { id: "docs", skills: ["docs-search"] }, // замінює defaults - { id: "locked-down", skills: [] }, // без skills + { id: "docs", skills: ["docs-search"] }, // замінює значення за замовчуванням + { id: "locked-down", skills: [] }, // без Skills ], }, } @@ -70,55 +77,73 @@ OpenClaw завантажує skills із таких джерел: Правила: -- Пропустіть `agents.defaults.skills`, якщо за замовчуванням skills не мають бути обмежені. +- Пропустіть `agents.defaults.skills`, щоб за замовчуванням Skills не були обмежені. - Пропустіть `agents.list[].skills`, щоб успадкувати `agents.defaults.skills`. -- Установіть `agents.list[].skills: []`, щоб не дозволити жодних skills. -- Непорожній список `agents.list[].skills` є остаточним набором для цього агента; він не об’єднується з defaults. +- Установіть `agents.list[].skills: []`, щоб не дозволити жодних Skills. +- Непорожній список `agents.list[].skills` є фінальним набором для цього агента; він + не об’єднується зі значеннями за замовчуванням. -OpenClaw застосовує ефективний набір skills агента до побудови prompt, виявлення slash-command skill, синхронізації sandbox і snapshot skill. +OpenClaw застосовує ефективний набір Skills агента під час побудови prompt, виявлення slash-команд Skill, синхронізації sandbox і знімків Skills. -## Plugins + skills +## Plugin-ів + Skills -Plugins можуть постачати власні skills, вказуючи каталоги `skills` у -`openclaw.plugin.json` (шляхи відносно кореня plugin). Skills plugin завантажуються, -коли plugin увімкнено. Зараз ці каталоги об’єднуються в той самий шлях із -низьким пріоритетом, що й `skills.load.extraDirs`, тому однойменний bundled, -managed, agent або workspace skill перевизначає їх. -Ви можете обмежувати їх через `metadata.openclaw.requires.config` у записі -конфігурації plugin. Див. [Plugins](/uk/tools/plugin) для виявлення/конфігурації та [Tools](/uk/tools) для -поверхні інструментів, які пояснюють ці skills. +Plugin-и можуть постачати власні Skills, указуючи директорії `skills` у +`openclaw.plugin.json` (шляхи відносно кореня plugin-а). Skills plugin-а завантажуються, +коли plugin увімкнено. Наразі ці директорії зливаються в той самий шлях +низького пріоритету, що й `skills.load.extraDirs`, тож Skill з однаковим ім’ям із вбудованого, +керованого, агентського або робочого простору перевизначає їх. +Ви можете обмежити їх через `metadata.openclaw.requires.config` у записі config +plugin-а. Див. [Plugins](/uk/tools/plugin) щодо виявлення/config та [Tools](/uk/tools) щодо +поверхні інструментів, якої навчають ці Skills. + +## Skill Workshop + +Необов’язковий експериментальний plugin Skill Workshop може створювати або оновлювати Skills робочого простору +з повторно використовуваних процедур, виявлених під час роботи агента. Його вимкнено за замовчуванням, і його потрібно явно ввімкнути через +`plugins.entries.skill-workshop`. + +Skill Workshop записує лише в `/skills`, сканує згенерований вміст, +підтримує очікування підтвердження або автоматичний безпечний запис, поміщає небезпечні +пропозиції на карантин і оновлює знімок Skills після успішного запису, щоб нові +Skills могли стати доступними без перезапуску Gateway. + +Використовуйте його, коли хочете, щоб такі виправлення, як «наступного разу перевіряй атрибуцію GIF» або +складно здобуті робочі процеси, як-от контрольні списки медіа-QA, ставали +стійкими процедурними інструкціями. Починайте з режиму очікування підтвердження; використовуйте автоматичний запис лише в довірених робочих просторах після перегляду його пропозицій. Повний посібник: +[Skill Workshop Plugin](/uk/plugins/skill-workshop). ## ClawHub (інсталяція + синхронізація) -ClawHub — це публічний реєстр skills для OpenClaw. Переглянути його можна на -[https://clawhub.ai](https://clawhub.ai). Використовуйте рідні команди `openclaw skills` -для пошуку/інсталяції/оновлення skills або окремий CLI `clawhub`, якщо вам -потрібні робочі процеси публікації/синхронізації. +ClawHub — це публічний реєстр Skills для OpenClaw. Перегляд доступний на +[https://clawhub.ai](https://clawhub.ai). Використовуйте нативні команди `openclaw skills` +для виявлення/інсталяції/оновлення Skills або окремий CLI `clawhub`, коли +вам потрібні робочі процеси публікації/синхронізації. Повний посібник: [ClawHub](/uk/tools/clawhub). Поширені сценарії: -- Інсталювати skill у ваш робочий простір: +- Інсталювати Skill у ваш робочий простір: - `openclaw skills install ` -- Оновити всі інстальовані skills: +- Оновити всі інстальовані Skills: - `openclaw skills update --all` - Синхронізувати (сканування + публікація оновлень): - `clawhub sync --all` -Рідна команда `openclaw skills install` інсталює у каталог `skills/` активного робочого простору. Окремий CLI `clawhub` також інсталює у `./skills` у вашому +Нативна команда `openclaw skills install` інсталює в активну директорію `skills/` +робочого простору. Окремий CLI `clawhub` також інсталює в `./skills` у вашому поточному робочому каталозі (або використовує налаштований робочий простір OpenClaw як резервний варіант). -Під час наступної сесії OpenClaw розпізнає це як `/skills`. +OpenClaw підхопить це як `/skills` під час наступної сесії. ## Примітки щодо безпеки -- Ставтеся до сторонніх skills як до **ненадійного коду**. Читайте їх перед увімкненням. -- Для ненадійних вхідних даних і ризикованих інструментів надавайте перевагу запуску в sandbox. Див. [Sandboxing](/uk/gateway/sandboxing). -- Виявлення skills у workspace та extra-dir приймає лише корені skill і файли `SKILL.md`, чий визначений `realpath` залишається всередині налаштованого кореня. -- Інсталяції залежностей skills через gateway (`skills.install`, onboarding і UI налаштувань Skills) запускають вбудований сканер небезпечного коду перед виконанням метаданих інсталятора. Знахідки `critical` блокуються за замовчуванням, якщо викликач явно не встановить dangerous override; підозрілі знахідки, як і раніше, лише попереджають. -- `openclaw skills install ` — це інше: команда завантажує папку skill з ClawHub у робочий простір і не використовує шлях метаданих інсталятора, описаний вище. -- `skills.entries.*.env` і `skills.entries.*.apiKey` ін’єктують секрети в процес **host** - для цього ходу агента (не в sandbox). Не допускайте потрапляння секретів у prompts і логи. -- Для ширшої моделі загроз і контрольних списків див. [Security](/uk/gateway/security). +- Вважайте сторонні Skills **ненадійним кодом**. Читайте їх перед увімкненням. +- Для ненадійних входів і ризикованих інструментів надавайте перевагу sandbox-запускам. Див. [Sandboxing](/uk/gateway/sandboxing). +- Виявлення Skills у робочому просторі та додаткових директоріях приймає лише корені Skills і файли `SKILL.md`, чий обчислений realpath залишається всередині налаштованого кореня. +- Інсталяції залежностей Skill через Gateway (`skills.install`, onboarding і UI налаштувань Skills) запускають вбудований сканер небезпечного коду перед виконанням метаданих інсталятора. Знахідки рівня `critical` блокуються за замовчуванням, якщо викликач явно не встановлює перевизначення небезпеки; підозрілі знахідки все ще лише попереджають. +- `openclaw skills install ` відрізняється: ця команда завантажує папку Skill з ClawHub до робочого простору і не використовує описаний вище шлях метаданих інсталятора. +- `skills.entries.*.env` і `skills.entries.*.apiKey` інжектують секрети в **host**-процес + для цього ходу агента (не в sandbox). Не допускайте секрети в prompt-и й логи. +- Ширшу модель загроз і контрольні списки див. в [Security](/uk/gateway/security). ## Формат (сумісний з AgentSkills + Pi) @@ -133,24 +158,24 @@ description: Generate or edit images via a provider-backed image workflow Примітки: -- Ми дотримуємося специфікації AgentSkills щодо структури та призначення. +- Ми дотримуємося специфікації AgentSkills щодо структури/призначення. - Парсер, який використовує вбудований агент, підтримує лише **однорядкові** ключі frontmatter. -- `metadata` має бути **однорядковим JSON object**. -- Використовуйте `{baseDir}` в інструкціях, щоб посилатися на шлях до папки skill. +- `metadata` має бути **однорядковим JSON-об’єктом**. +- Використовуйте `{baseDir}` в інструкціях, щоб посилатися на шлях до папки Skill. - Необов’язкові ключі frontmatter: - - `homepage` — URL, що відображається як “Website” в macOS Skills UI (також підтримується через `metadata.openclaw.homepage`). - - `user-invocable` — `true|false` (типове значення: `true`). Якщо `true`, skill доступний як slash command користувача. - - `disable-model-invocation` — `true|false` (типове значення: `false`). Якщо `true`, skill виключається з model prompt (але все ще доступний через виклик користувачем). - - `command-dispatch` — `tool` (необов’язково). Якщо встановлено `tool`, slash command оминає model і напряму передається інструменту. - - `command-tool` — назва інструменту, який потрібно викликати, якщо встановлено `command-dispatch: tool`. - - `command-arg-mode` — `raw` (типове значення). Для dispatch інструмента передає рядок сирих аргументів інструменту (без розбору на рівні core). + - `homepage` — URL, який відображається як “Website” у macOS UI Skills (також підтримується через `metadata.openclaw.homepage`). + - `user-invocable` — `true|false` (типове значення: `true`). Якщо `true`, Skill доступний як slash-команда користувача. + - `disable-model-invocation` — `true|false` (типове значення: `false`). Якщо `true`, Skill виключається з prompt моделі (але все ще доступний через виклик користувачем). + - `command-dispatch` — `tool` (необов’язково). Якщо встановлено `tool`, slash-команда оминає модель і напряму диспетчеризується до інструмента. + - `command-tool` — назва інструмента, який потрібно викликати, коли встановлено `command-dispatch: tool`. + - `command-arg-mode` — `raw` (типове значення). Для диспетчеризації до інструмента пересилає сирий рядок аргументів до інструмента (без парсингу в ядрі). Інструмент викликається з параметрами: `{ command: "", commandName: "", skillName: "" }`. -## Гейтінг (фільтри під час завантаження) +## Gate (фільтри під час завантаження) -OpenClaw **фільтрує skills під час завантаження** за допомогою `metadata` (однорядковий JSON): +OpenClaw **фільтрує Skills під час завантаження** за допомогою `metadata` (однорядковий JSON): ```markdown --- @@ -169,25 +194,25 @@ metadata: Поля в `metadata.openclaw`: -- `always: true` — завжди включати skill (пропустити інші умови). -- `emoji` — необов’язковий emoji, який використовується в macOS Skills UI. -- `homepage` — необов’язковий URL, що відображається як “Website” в macOS Skills UI. -- `os` — необов’язковий список платформ (`darwin`, `linux`, `win32`). Якщо встановлено, skill доступний лише на цих ОС. -- `requires.bins` — список; кожен має існувати в `PATH`. -- `requires.anyBins` — список; принаймні один має існувати в `PATH`. -- `requires.env` — список; змінна середовища має існувати **або** бути надана в config. +- `always: true` — завжди включати Skill (пропустити інші gate). +- `emoji` — необов’язковий emoji, який використовується в macOS UI Skills. +- `homepage` — необов’язковий URL, який відображається як “Website” у macOS UI Skills. +- `os` — необов’язковий список платформ (`darwin`, `linux`, `win32`). Якщо встановлено, Skill доступний лише в цих ОС. +- `requires.bins` — список; кожен елемент має існувати в `PATH`. +- `requires.anyBins` — список; у `PATH` має існувати принаймні один елемент. +- `requires.env` — список; змінна середовища має існувати **або** бути наданою в config. - `requires.config` — список шляхів `openclaw.json`, які мають бути truthy. - `primaryEnv` — назва змінної середовища, пов’язаної з `skills.entries..apiKey`. -- `install` — необов’язковий масив специфікацій інсталятора, який використовує macOS Skills UI (brew/node/go/uv/download). +- `install` — необов’язковий масив специфікацій інсталятора, який використовує macOS UI Skills (brew/node/go/uv/download). Примітка щодо sandboxing: -- `requires.bins` перевіряється на **host** під час завантаження skill. +- `requires.bins` перевіряється на **host** під час завантаження Skill. - Якщо агент працює в sandbox, бінарний файл також має існувати **всередині контейнера**. Інсталюйте його через `agents.defaults.sandbox.docker.setupCommand` (або через власний образ). `setupCommand` запускається один раз після створення контейнера. - Для інсталяції пакетів також потрібні вихід у мережу, записувана root FS і користувач root у sandbox. - Приклад: skill `summarize` (`skills/summarize/SKILL.md`) потребує `summarize` CLI + Інсталяція package також вимагає мережевого виходу, записуваної кореневої FS і root-користувача в sandbox. + Наприклад, Skill `summarize` (`skills/summarize/SKILL.md`) потребує CLI `summarize` у контейнері sandbox, щоб працювати там. Приклад інсталятора: @@ -219,27 +244,27 @@ metadata: Примітки: -- Якщо вказано кілька інсталяторів, gateway вибирає **один** бажаний варіант (brew, якщо доступний, інакше node). -- Якщо всі інсталятори мають тип `download`, OpenClaw показує кожен запис, щоб ви могли бачити доступні артефакти. +- Якщо вказано кілька інсталяторів, Gateway вибирає **один** бажаний варіант (brew, якщо доступний, інакше node). +- Якщо всі інсталятори мають тип `download`, OpenClaw перелічує кожен запис, щоб ви могли бачити доступні артефакти. - Специфікації інсталятора можуть містити `os: ["darwin"|"linux"|"win32"]`, щоб фільтрувати варіанти за платформою. -- Node-інсталяції враховують `skills.install.nodeManager` у `openclaw.json` (типово: npm; варіанти: npm/pnpm/yarn/bun). - Це впливає лише на **інсталяції skills**; середовище виконання Gateway, як і раніше, має бути Node +- Інсталяції через node враховують `skills.install.nodeManager` в `openclaw.json` (типове значення: npm; варіанти: npm/pnpm/yarn/bun). + Це впливає лише на **інсталяції Skills**; runtime Gateway усе одно має бути Node (Bun не рекомендується для WhatsApp/Telegram). -- Вибір інсталятора через gateway залежить від пріоритетів, а не лише від node: +- Вибір інсталятора через Gateway базується на пріоритетах, а не лише на node: коли специфікації інсталяції змішують різні типи, OpenClaw надає перевагу Homebrew, якщо увімкнено `skills.install.preferBrew` і існує `brew`, потім `uv`, потім - налаштований node manager, а далі інші резервні варіанти, як-от `go` або `download`. + налаштований node manager, потім інші резервні варіанти, такі як `go` або `download`. - Якщо кожна специфікація інсталяції має тип `download`, OpenClaw показує всі варіанти завантаження - замість зведення до одного бажаного інсталятора. -- Go-інсталяції: якщо `go` відсутній, а `brew` доступний, gateway спочатку інсталює Go через Homebrew і за можливості встановлює `GOBIN` у `bin` Homebrew. -- Download-інсталяції: `url` (обов’язково), `archive` (`tar.gz` | `tar.bz2` | `zip`), `extract` (типово: автоматично, якщо виявлено archive), `stripComponents`, `targetDir` (типово: `~/.openclaw/tools/`). + замість згортання до одного бажаного інсталятора. +- Інсталяції через Go: якщо `go` відсутній, а `brew` доступний, Gateway спочатку інсталює Go через Homebrew і за можливості встановлює `GOBIN` на `bin` від Homebrew. +- Інсталяції через download: `url` (обов’язково), `archive` (`tar.gz` | `tar.bz2` | `zip`), `extract` (типове значення: auto при виявленні архіву), `stripComponents`, `targetDir` (типове значення: `~/.openclaw/tools/`). -Якщо `metadata.openclaw` відсутній, skill завжди вважається допустимим (якщо -його не вимкнено в config і якщо його не блокує `skills.allowBundled` для вбудованих skills). +Якщо `metadata.openclaw` відсутній, Skill завжди доступний (якщо тільки +його не вимкнено в config або не заблоковано через `skills.allowBundled` для вбудованих Skills). ## Перевизначення config (`~/.openclaw/openclaw.json`) -Вбудовані/керовані skills можна вмикати або вимикати та передавати їм значення env: +Вбудовані/керовані Skills можна вмикати або вимикати та надавати їм значення env: ```json5 { @@ -247,7 +272,7 @@ metadata: entries: { "image-lab": { enabled: true, - apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" }, // або plaintext string + apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" }, // або рядок plaintext env: { GEMINI_API_KEY: "GEMINI_KEY_HERE", }, @@ -263,68 +288,69 @@ metadata: } ``` -Примітка: якщо назва skill містить дефіси, візьміть ключ у лапки (JSON5 дозволяє ключі в лапках). +Примітка: якщо назва Skill містить дефіси, візьміть ключ у лапки (JSON5 дозволяє ключі в лапках). -Якщо вам потрібна стандартна генерація/редагування зображень безпосередньо в OpenClaw, використовуйте core-інструмент -`image_generate` разом з `agents.defaults.imageGenerationModel`, а не -вбудований skill. Наведені тут приклади skill призначені для користувацьких або сторонніх робочих процесів. +Якщо вам потрібне стандартне генерування/редагування зображень усередині самого OpenClaw, використовуйте основний +інструмент `image_generate` з `agents.defaults.imageGenerationModel` замість +вбудованого Skill. Приклади Skills тут наведені для користувацьких або сторонніх робочих процесів. -Для нативного аналізу зображень використовуйте інструмент `image` разом з `agents.defaults.imageModel`. -Для нативної генерації/редагування зображень використовуйте `image_generate` разом з +Для нативного аналізу зображень використовуйте інструмент `image` з `agents.defaults.imageModel`. +Для нативного генерування/редагування зображень використовуйте `image_generate` з `agents.defaults.imageGenerationModel`. Якщо ви вибираєте `openai/*`, `google/*`, -`fal/*` або іншу модель зображень, прив’язану до конкретного провайдера, також додайте auth/API -key цього провайдера. +`fal/*` або іншу специфічну для провайдера модель зображення, також додайте auth/API +ключ цього провайдера. -Ключі config за замовчуванням відповідають **назві skill**. Якщо skill визначає +Ключі config за замовчуванням відповідають **назві Skill**. Якщо Skill визначає `metadata.openclaw.skillKey`, використовуйте цей ключ у `skills.entries`. Правила: -- `enabled: false` вимикає skill, навіть якщо він вбудований/інстальований. -- `env`: ін’єктується **лише якщо** змінна ще не встановлена в процесі. -- `apiKey`: зручний варіант для skills, які оголошують `metadata.openclaw.primaryEnv`. - Підтримує plaintext string або об’єкт SecretRef (`{ source, provider, id }`). -- `config`: необов’язковий набір для користувацьких полів конкретного skill; користувацькі ключі мають розміщуватися тут. -- `allowBundled`: необов’язковий allowlist лише для **вбудованих** skills. Якщо його задано, допустимими є лише - вбудовані skills зі списку (керовані/skills робочого простору не зачіпаються). +- `enabled: false` вимикає Skill, навіть якщо він вбудований/інстальований. +- `env`: інжектується **лише якщо** змінна ще не встановлена в процесі. +- `apiKey`: зручний механізм для Skills, які оголошують `metadata.openclaw.primaryEnv`. + Підтримує plaintext-рядок або об’єкт SecretRef (`{ source, provider, id }`). +- `config`: необов’язковий контейнер для користувацьких полів окремого Skill; користувацькі ключі мають міститися тут. +- `allowBundled`: необов’язковий allowlist лише для **вбудованих** Skills. Якщо встановлено, доступними є лише + вбудовані Skills зі списку (керовані/робочого простору Skills не зачіпаються). -## Ін’єкція середовища (для кожного запуску агента) +## Інжекція середовища (для кожного запуску агента) -Коли починається запуск агента, OpenClaw: +Коли запускається агент, OpenClaw: -1. Зчитує метадані skill. +1. Читає метадані Skill. 2. Застосовує будь-які `skills.entries..env` або `skills.entries..apiKey` до `process.env`. -3. Будує системний prompt з **допустимими** skills. +3. Будує системний prompt із **доступними** Skills. 4. Відновлює початкове середовище після завершення запуску. -Це **обмежено запуском агента**, а не є глобальним середовищем shell. +Це **обмежується запуском агента**, а не глобальним shell-середовищем. Для вбудованого backend `claude-cli` OpenClaw також матеріалізує той самий -знімок допустимих skills як тимчасовий плагін Claude Code і передає його через -`--plugin-dir`. Тоді Claude Code може використовувати власний вбудований resolver skill, тоді як -OpenClaw усе ще керує пріоритетом, allowlist для окремих агентів, гейтінгом і -ін’єкцією env/API key через `skills.entries.*`. Інші CLI backend використовують лише каталог prompt. +доступний знімок як тимчасовий plugin Claude Code і передає його через +`--plugin-dir`. Тоді Claude Code може використовувати власний нативний резолвер Skills, тоді як +OpenClaw усе ще володіє пріоритетом, allowlist-ами для окремих агентів, gate-ами та +інжекцією env/API key через `skills.entries.*`. Інші CLI backend-и використовують лише каталог +prompt-ів. ## Знімок сесії (продуктивність) -OpenClaw створює знімок допустимих skills **коли починається сесія** і повторно використовує цей список для наступних ходів у межах тієї самої сесії. Зміни в skills або config набувають чинності під час наступної нової сесії. +OpenClaw робить знімок доступних Skills **під час початку сесії** і повторно використовує цей список для наступних ходів у межах тієї самої сесії. Зміни в Skills або config набирають чинності в наступній новій сесії. -Skills також можуть оновлюватися посеред сесії, коли ввімкнено watcher skills або коли з’являється новий допустимий віддалений вузол (див. нижче). Думайте про це як про **гаряче перезавантаження**: оновлений список буде підхоплено під час наступного ходу агента. +Skills також можуть оновлюватися в середині сесії, коли ввімкнено watcher Skills або коли з’являється новий доступний віддалений Node (див. нижче). Думайте про це як про **гаряче перезавантаження**: оновлений список підхоплюється на наступному ході агента. -Якщо ефективний allowlist skills агента змінюється для цієї сесії, OpenClaw -оновлює знімок, щоб видимі skills залишалися узгодженими з поточним +Якщо для цієї сесії змінюється ефективний allowlist Skills агента, OpenClaw +оновлює знімок, щоб видимі Skills залишалися узгодженими з поточним агентом. -## Віддалені вузли macOS (Linux gateway) +## Віддалені macOS Node-и (Linux Gateway) -Якщо Gateway запущено на Linux, але підключено **вузол macOS** **з дозволеним `system.run`** (параметр безпеки Exec approvals не встановлено в `deny`), OpenClaw може вважати допустимими skills лише для macOS, якщо потрібні бінарні файли присутні на цьому вузлі. Агент має виконувати такі skills через інструмент `exec` з `host=node`. +Якщо Gateway працює на Linux, але **macOS Node** підключений **з дозволеним `system.run`** (безпека Exec approvals не встановлена в `deny`), OpenClaw може вважати Skills лише для macOS доступними, коли потрібні бінарні файли присутні на цьому Node. Агент має виконувати такі Skills через інструмент `exec` з `host=node`. -Це спирається на те, що вузол повідомляє про підтримку команд, а також на перевірку бінарних файлів через `system.run`. Якщо вузол macOS пізніше переходить в офлайн, skills залишаються видимими; виклики можуть завершуватися помилкою, доки вузол знову не підключиться. +Це спирається на те, що Node повідомляє про підтримку команд і на перевірку бінарних файлів через `system.run`. Якщо macOS Node пізніше відключиться, Skills залишаться видимими; виклики можуть завершуватися помилкою, доки Node не підключиться знову. -## Watcher skills (автооновлення) +## Watcher Skills (автооновлення) -За замовчуванням OpenClaw відстежує папки skills і оновлює знімок skills, коли змінюються файли `SKILL.md`. Це налаштовується в `skills.load`: +За замовчуванням OpenClaw відстежує папки Skills і збільшує знімок Skills, коли змінюються файли `SKILL.md`. Налаштовується це в `skills.load`: ```json5 { @@ -337,12 +363,12 @@ Skills також можуть оновлюватися посеред сесі } ``` -## Вплив на токени (список skills) +## Вплив на токени (список Skills) -Коли skills допустимі, OpenClaw ін’єктує компактний XML-список доступних skills у системний prompt (через `formatSkillsForPrompt` у `pi-coding-agent`). Вартість детермінована: +Коли Skills доступні, OpenClaw інжектує компактний XML-список доступних Skills у системний prompt (через `formatSkillsForPrompt` у `pi-coding-agent`). Вартість є детермінованою: -- **Базові накладні витрати (лише коли ≥1 skill):** 195 символів. -- **Для кожного skill:** 97 символів + довжина XML-екранованих значень ``, `` і ``. +- **Базові накладні витрати (лише коли ≥1 Skill):** 195 символів. +- **На один Skill:** 97 символів + довжина значень ``, `` і `` після XML-екранування. Формула (символи): @@ -353,20 +379,20 @@ total = 195 + Σ (97 + len(name_escaped) + len(description_escaped) + len(locati Примітки: - XML-екранування розширює `& < > " '` до сутностей (`&`, `<` тощо), збільшуючи довжину. -- Кількість токенів залежить від tokenizer моделі. Груба оцінка в стилі OpenAI — приблизно 4 символи/токен, тож **97 символів ≈ 24 токени** на skill плюс фактична довжина ваших полів. +- Кількість токенів залежить від tokenizer моделі. Груба оцінка у стилі OpenAI — ~4 символи/токен, тому **97 символів ≈ 24 токени** на Skill плюс фактичні довжини ваших полів. -## Життєвий цикл керованих skills +## Життєвий цикл керованих Skills -OpenClaw постачається з базовим набором skills як **вбудовані skills** у складі +OpenClaw постачає базовий набір Skills як **вбудовані Skills** у складі інсталяції (npm package або OpenClaw.app). `~/.openclaw/skills` існує для локальних -перевизначень (наприклад, щоб зафіксувати/пропатчити skill без зміни вбудованої -копії). Skills робочого простору належать користувачу й перевизначають обидва варіанти при конфліктах назв. +перевизначень (наприклад, щоб зафіксувати/пропатчити Skill без зміни вбудованої +копії). Skills робочого простору належать користувачу та перевизначають обидва варіанти в разі конфліктів імен. ## Довідник config -Див. [Skills config](/uk/tools/skills-config), щоб переглянути повну схему конфігурації. +Повну схему конфігурації див. у [Skills config](/uk/tools/skills-config). -## Шукаєте більше skills? +## Шукаєте більше Skills? Перегляньте [https://clawhub.ai](https://clawhub.ai). @@ -374,7 +400,7 @@ OpenClaw постачається з базовим набором skills як * ## Пов’язане -- [Creating Skills](/uk/tools/creating-skills) — створення користувацьких skills -- [Skills Config](/uk/tools/skills-config) — довідник із конфігурації skills -- [Slash Commands](/uk/tools/slash-commands) — усі доступні slash commands -- [Plugins](/uk/tools/plugin) — огляд системи plugin +- [Створення Skills](/uk/tools/creating-skills) — створення користувацьких Skills +- [Skills Config](/uk/tools/skills-config) — довідник конфігурації Skills +- [Slash Commands](/uk/tools/slash-commands) — усі доступні slash-команди +- [Plugins](/uk/tools/plugin) — огляд системи plugin-ів diff --git a/docs/uk/tools/web.md b/docs/uk/tools/web.md index c4158b872..c110c6488 100644 --- a/docs/uk/tools/web.md +++ b/docs/uk/tools/web.md @@ -1,50 +1,51 @@ --- read_when: - - Ви хочете увімкнути або налаштувати web_search - - Ви хочете увімкнути або налаштувати x_search - - Вам потрібно вибрати постачальника пошуку - - Ви хочете зрозуміти авто-виявлення та резервне перемикання між постачальниками + - Ви хочете ввімкнути або налаштувати web_search + - Ви хочете ввімкнути або налаштувати x_search + - Вам потрібно вибрати провайдера пошуку + - Ви хочете зрозуміти автовизначення і fallback провайдера sidebarTitle: Web Search -summary: web_search, x_search та web_fetch — пошук у вебі, пошук дописів у X або отримання вмісту сторінки +summary: web_search, x_search і web_fetch — пошук у вебі, пошук дописів у X або отримання вмісту сторінки title: Вебпошук x-i18n: - generated_at: "2026-04-21T01:06:34Z" + generated_at: "2026-04-21T20:38:29Z" model: gpt-5.4 provider: openai - source_hash: 9e88a891ce28a5fe1baf4b9ce8565c59ba2d2695c63d77af232edd7f3fd2cd8a + source_hash: ec2517d660465f850b1cfdd255fbf512dc5c828b1ef22e3b24cec6aab097ebd5 source_path: tools/web.md workflow: 15 --- # Вебпошук -Інструмент `web_search` виконує пошук у вебі за допомогою налаштованого вами постачальника та +Інструмент `web_search` виконує пошук у вебі за допомогою налаштованого вами провайдера і повертає результати. Результати кешуються за запитом на 15 хвилин (це можна налаштувати). OpenClaw також містить `x_search` для дописів у X (раніше Twitter) і -`web_fetch` для полегшеного отримання URL. На цьому етапі `web_fetch` лишається -локальним, тоді як `web_search` і `x_search` можуть використовувати xAI Responses під капотом. +`web_fetch` для легкого отримання URL. На цьому етапі `web_fetch` залишається +локальним, тоді як `web_search` і `x_search` можуть під капотом використовувати xAI Responses. - `web_search` — це полегшений HTTP-інструмент, а не автоматизація браузера. Для - сайтів із активним використанням JS або для входу в акаунт використовуйте [Web Browser](/uk/tools/browser). Для + `web_search` — це легкий HTTP-інструмент, а не автоматизація браузера. Для + сайтів із важким JS або входом в обліковий запис використовуйте [Web Browser](/uk/tools/browser). Для отримання конкретного URL використовуйте [Web Fetch](/uk/tools/web-fetch). ## Швидкий старт - - Виберіть постачальника та виконайте всі потрібні кроки налаштування. Деякі постачальники - не потребують ключа, тоді як інші використовують API-ключі. Подробиці дивіться на сторінках постачальників нижче. + + Виберіть провайдера і виконайте всі необхідні кроки налаштування. Деякі провайдери + не потребують ключів, тоді як інші використовують API-ключі. Докладніше + дивіться на сторінках провайдерів нижче. ```bash openclaw configure --section web ``` - Це збереже постачальника та всі потрібні облікові дані. Ви також можете встановити змінну середовища - (наприклад, `BRAVE_API_KEY`) і пропустити цей крок для - постачальників, що працюють через API. + Це збереже провайдера та всі потрібні облікові дані. Ви також можете встановити env + var (наприклад, `BRAVE_API_KEY`) і пропустити цей крок для провайдерів, + що працюють через API. Тепер агент може викликати `web_search`: @@ -62,14 +63,14 @@ OpenClaw також містить `x_search` для дописів у X (ран -## Вибір постачальника +## Вибір провайдера - Структуровані результати зі сніпетами. Підтримує режим `llm-context`, фільтри країни/мови. Доступний безкоштовний тариф. + Структуровані результати зі сніпетами. Підтримує режим `llm-context`, фільтри країни/мови. Є безкоштовний тариф. - Резервний варіант без ключа. API-ключ не потрібен. Неофіційна інтеграція на основі HTML. + Fallback без ключа. API-ключ не потрібен. Неофіційна інтеграція на основі HTML. Нейронний + ключовий пошук із витягуванням вмісту (підсвічування, текст, підсумки). @@ -78,13 +79,13 @@ OpenClaw також містить `x_search` для дописів у X (ран Структуровані результати. Найкраще поєднується з `firecrawl_search` і `firecrawl_scrape` для глибокого витягування. - Відповіді, синтезовані ШІ, із посиланнями через Google Search grounding. + Відповіді, синтезовані ШІ, з цитуваннями через Google Search grounding. - Відповіді, синтезовані ШІ, із посиланнями через xAI web grounding. + Відповіді, синтезовані ШІ, з цитуваннями через xAI web grounding. - Відповіді, синтезовані ШІ, із посиланнями через вебпошук Moonshot. + Відповіді, синтезовані ШІ, з цитуваннями через Moonshot web search. Структуровані результати через API пошуку MiniMax Coding Plan. @@ -96,41 +97,41 @@ OpenClaw також містить `x_search` для дописів у X (ран Структуровані результати з керуванням витягуванням вмісту та фільтрацією доменів. - Самостійно розгорнутий метапошук. API-ключ не потрібен. Агрегує Google, Bing, DuckDuckGo та інші системи. + Самохостинговий метапошук. API-ключ не потрібен. Агрегує Google, Bing, DuckDuckGo та інші. - Структуровані результати з глибиною пошуку, фільтрацією за темою та `tavily_extract` для витягування URL. + Структуровані результати з глибиною пошуку, фільтрацією тем і `tavily_extract` для витягування URL. -### Порівняння постачальників +### Порівняння провайдерів -| Постачальник | Стиль результатів | Фільтри | API-ключ | +| Провайдер | Стиль результатів | Фільтри | API-ключ | | ----------------------------------------- | -------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------- | | [Brave](/uk/tools/brave-search) | Структуровані сніпети | Країна, мова, час, режим `llm-context` | `BRAVE_API_KEY` | -| [DuckDuckGo](/uk/tools/duckduckgo-search) | Структуровані сніпети | -- | Немає (без ключа) | +| [DuckDuckGo](/uk/tools/duckduckgo-search) | Структуровані сніпети | -- | None (без ключа) | | [Exa](/uk/tools/exa-search) | Структуровані + витягнуті | Нейронний/ключовий режим, дата, витягування вмісту | `EXA_API_KEY` | | [Firecrawl](/uk/tools/firecrawl) | Структуровані сніпети | Через інструмент `firecrawl_search` | `FIRECRAWL_API_KEY` | -| [Gemini](/uk/tools/gemini-search) | Синтезовані ШІ + посилання | -- | `GEMINI_API_KEY` | -| [Grok](/uk/tools/grok-search) | Синтезовані ШІ + посилання | -- | `XAI_API_KEY` | -| [Kimi](/uk/tools/kimi-search) | Синтезовані ШІ + посилання | -- | `KIMI_API_KEY` / `MOONSHOT_API_KEY` | +| [Gemini](/uk/tools/gemini-search) | Синтезовані ШІ + цитування | -- | `GEMINI_API_KEY` | +| [Grok](/uk/tools/grok-search) | Синтезовані ШІ + цитування | -- | `XAI_API_KEY` | +| [Kimi](/uk/tools/kimi-search) | Синтезовані ШІ + цитування | -- | `KIMI_API_KEY` / `MOONSHOT_API_KEY` | | [MiniMax Search](/uk/tools/minimax-search) | Структуровані сніпети | Регіон (`global` / `cn`) | `MINIMAX_CODE_PLAN_KEY` / `MINIMAX_CODING_API_KEY` | -| [Ollama Web Search](/uk/tools/ollama-search) | Структуровані сніпети | -- | Немає за замовчуванням; потрібен `ollama signin`, можна повторно використати bearer auth постачальника Ollama | +| [Ollama Web Search](/uk/tools/ollama-search) | Структуровані сніпети | -- | None типово; потрібен `ollama signin`, можна повторно використати bearer auth провайдера Ollama | | [Perplexity](/uk/tools/perplexity-search) | Структуровані сніпети | Країна, мова, час, домени, ліміти вмісту | `PERPLEXITY_API_KEY` / `OPENROUTER_API_KEY` | -| [SearXNG](/uk/tools/searxng-search) | Структуровані сніпети | Категорії, мова | Немає (самостійно розгорнутий) | +| [SearXNG](/uk/tools/searxng-search) | Структуровані сніпети | Категорії, мова | None (самохостинг) | | [Tavily](/uk/tools/tavily) | Структуровані сніпети | Через інструмент `tavily_search` | `TAVILY_API_KEY` | -## Автовиявлення +## Автовизначення -## Власний вебпошук Codex +## Нативний вебпошук Codex -Моделі з підтримкою Codex за бажанням можуть використовувати власний інструмент Responses `web_search` постачальника замість керованої функції `web_search` OpenClaw. +Моделі з підтримкою Codex за бажанням можуть використовувати нативний інструмент Responses `web_search` від провайдера замість керованої функції `web_search` OpenClaw. - Налаштовується в `tools.web.search.openaiCodex` -- Активується лише для моделей із підтримкою Codex (`openai-codex/*` або постачальників, які використовують `api: "openai-codex-responses"`) +- Активується лише для моделей із підтримкою Codex (`openai-codex/*` або провайдерів, що використовують `api: "openai-codex-responses"`) - Керований `web_search` і далі застосовується до моделей без підтримки Codex -- `mode: "cached"` — це стандартне та рекомендоване значення -- `tools.web.search.enabled: false` вимикає і керований, і власний пошук +- `mode: "cached"` — типове та рекомендоване налаштування +- `tools.web.search.enabled: false` вимикає як керований, так і нативний пошук ```json5 { @@ -155,17 +156,17 @@ OpenClaw також містить `x_search` для дописів у X (ран } ``` -Якщо власний пошук Codex увімкнено, але поточна модель не підтримує Codex, OpenClaw зберігає звичайну поведінку керованого `web_search`. +Якщо нативний пошук Codex увімкнено, але поточна модель не підтримує Codex, OpenClaw зберігає звичайну поведінку керованого `web_search`. ## Налаштування вебпошуку -Списки постачальників у документації та сценаріях налаштування впорядковано за абеткою. Автовиявлення використовує +Списки провайдерів у документації та потоках налаштування впорядковано за абеткою. Автовизначення використовує окремий порядок пріоритету. -Якщо `provider` не задано, OpenClaw перевіряє постачальників у такому порядку й використовує -першого готового: +Якщо `provider` не задано, OpenClaw перевіряє провайдерів у такому порядку і використовує +першого, який готовий до роботи: -Спочатку постачальники з API: +Спочатку провайдери на основі API: 1. **Brave** -- `BRAVE_API_KEY` або `plugins.entries.brave.config.webSearch.apiKey` (порядок 10) 2. **MiniMax Search** -- `MINIMAX_CODE_PLAN_KEY` / `MINIMAX_CODING_API_KEY` або `plugins.entries.minimax.config.webSearch.apiKey` (порядок 15) @@ -177,19 +178,24 @@ OpenClaw також містить `x_search` для дописів у X (ран 8. **Exa** -- `EXA_API_KEY` або `plugins.entries.exa.config.webSearch.apiKey` (порядок 65) 9. **Tavily** -- `TAVILY_API_KEY` або `plugins.entries.tavily.config.webSearch.apiKey` (порядок 70) -Після цього — резервні варіанти без ключа: +Після цього — fallback без ключа: -10. **DuckDuckGo** -- HTML-резервний варіант без ключа, без акаунта чи API-ключа (порядок 100) -11. **Ollama Web Search** -- резервний варіант без ключа через ваш налаштований хост Ollama; вимагає, щоб Ollama був доступний і щоб ви виконали `ollama signin`, також може повторно використати bearer auth постачальника Ollama, якщо хост цього потребує (порядок 110) +10. **DuckDuckGo** -- HTML fallback без ключа, без облікового запису чи API-ключа (порядок 100) +11. **Ollama Web Search** -- fallback без ключа через ваш налаштований хост Ollama; вимагає, щоб Ollama був доступний і вхід було виконано через `ollama signin`, а також може повторно використовувати bearer auth провайдера Ollama, якщо хост його потребує (порядок 110) 12. **SearXNG** -- `SEARXNG_BASE_URL` або `plugins.entries.searxng.config.webSearch.baseUrl` (порядок 200) -Якщо не виявлено жодного постачальника, використовується Brave (ви отримаєте помилку -про відсутній ключ із підказкою налаштувати його). +Якщо жодного провайдера не виявлено, використовується fallback до Brave (ви отримаєте помилку +про відсутній ключ із пропозицією налаштувати його). - Усі поля ключів постачальників підтримують об’єкти SecretRef. У режимі автовиявлення - OpenClaw розв’язує лише ключ вибраного постачальника — SecretRef для невибраних - постачальників лишаються неактивними. + Усі поля ключів провайдерів підтримують об’єкти SecretRef. SecretRef із областю plugin + у `plugins.entries..config.webSearch.apiKey` розв’язуються для + вбудованих провайдерів Exa, Firecrawl, Gemini, Grok, Kimi, Perplexity і Tavily + незалежно від того, чи провайдера вибрано явно через `tools.web.search.provider`, чи + через автовизначення. У режимі автовизначення OpenClaw розв’язує лише ключ + вибраного провайдера — SecretRef невибраних провайдерів залишаються неактивними, тож ви можете + тримати налаштованими кількох провайдерів без витрат на розв’язання для тих, + яких ви не використовуєте. ## Конфігурація @@ -200,7 +206,7 @@ OpenClaw також містить `x_search` для дописів у X (ран web: { search: { enabled: true, // типово: true - provider: "brave", // або не вказуйте для автовиявлення + provider: "brave", // або пропустіть для автовизначення maxResults: 5, timeoutSeconds: 30, cacheTtlMinutes: 15, @@ -210,33 +216,33 @@ OpenClaw також містить `x_search` для дописів у X (ран } ``` -Конфігурація, специфічна для постачальника (API-ключі, базові URL, режими), розміщується в -`plugins.entries..config.webSearch.*`. Приклади дивіться на сторінках постачальників. +Специфічна для провайдера конфігурація (API-ключі, base URL, режими) міститься в +`plugins.entries..config.webSearch.*`. Приклади дивіться на сторінках провайдерів. -Вибір резервного постачальника для `web_fetch` налаштовується окремо: +Вибір fallback-провайдера для `web_fetch` налаштовується окремо: - виберіть його через `tools.web.fetch.provider` -- або не вказуйте це поле, і OpenClaw автоматично виявить першого готового постачальника - `web_fetch` серед доступних облікових даних -- наразі вбудований постачальник `web_fetch` — це Firecrawl, налаштований у +- або пропустіть це поле і дозвольте OpenClaw автоматично визначити першого готового провайдера `web_fetch` + з доступних облікових даних +- на сьогодні вбудований провайдер `web_fetch` — це Firecrawl, який налаштовується в `plugins.entries.firecrawl.config.webFetch.*` Коли ви вибираєте **Kimi** під час `openclaw onboard` або `openclaw configure --section web`, OpenClaw також може запитати: - регіон API Moonshot (`https://api.moonshot.ai/v1` або `https://api.moonshot.cn/v1`) -- типову модель Kimi для вебпошуку (типове значення — `kimi-k2.6`) +- типову модель вебпошуку Kimi (типово `kimi-k2.6`) Для `x_search` налаштуйте `plugins.entries.xai.config.xSearch.*`. Він використовує -той самий резервний варіант `XAI_API_KEY`, що й вебпошук Grok. -Застарілу конфігурацію `tools.web.x_search.*` автоматично мігрує `openclaw doctor --fix`. +той самий fallback `XAI_API_KEY`, що й вебпошук Grok. +Застаріла конфігурація `tools.web.x_search.*` автоматично мігрується через `openclaw doctor --fix`. Коли ви вибираєте Grok під час `openclaw onboard` або `openclaw configure --section web`, -OpenClaw також може запропонувати необов’язкове налаштування `x_search` з тим самим ключем. -Це окремий наступний крок у межах сценарію Grok, а не окремий вибір постачальника -вебпошуку верхнього рівня. Якщо ви виберете іншого постачальника, OpenClaw не +OpenClaw також може запропонувати додаткове налаштування `x_search` з тим самим ключем. +Це окремий подальший крок усередині шляху Grok, а не окремий вибір провайдера +вебпошуку верхнього рівня. Якщо ви виберете іншого провайдера, OpenClaw не показуватиме запит для `x_search`. -### Зберігання API-ключів +### Збереження API-ключів @@ -260,41 +266,41 @@ OpenClaw також може запропонувати необов’язко - Установіть змінну середовища постачальника в середовищі процесу Gateway: + Встановіть env var провайдера в середовищі процесу Gateway: ```bash export BRAVE_API_KEY="YOUR_KEY" ``` - Для встановлення Gateway додайте її до `~/.openclaw/.env`. - Див. [Змінні середовища](/uk/help/faq#env-vars-and-env-loading). + Для встановлення Gateway додайте її в `~/.openclaw/.env`. + Див. [Env vars](/uk/help/faq#env-vars-and-env-loading). ## Параметри інструмента -| Параметр | Опис | -| --------------------- | ------------------------------------------------------------- | -| `query` | Пошуковий запит (обов’язковий) | -| `count` | Кількість результатів для повернення (1-10, типово: 5) | -| `country` | 2-літерний код країни ISO (наприклад, "US", "DE") | -| `language` | Код мови ISO 639-1 (наприклад, "en", "de") | -| `search_lang` | Код мови пошуку (лише для Brave) | -| `freshness` | Фільтр часу: `day`, `week`, `month` або `year` | -| `date_after` | Результати після цієї дати (YYYY-MM-DD) | -| `date_before` | Результати до цієї дати (YYYY-MM-DD) | -| `ui_lang` | Код мови інтерфейсу (лише для Brave) | -| `domain_filter` | Масив дозволених/заборонених доменів (лише для Perplexity) | -| `max_tokens` | Загальний бюджет вмісту, типово 25000 (лише для Perplexity) | -| `max_tokens_per_page` | Ліміт токенів на сторінку, типово 2048 (лише для Perplexity) | +| Параметр | Опис | +| -------------------- | -------------------------------------------------------- | +| `query` | Пошуковий запит (обов’язковий) | +| `count` | Кількість результатів для повернення (1-10, типово: 5) | +| `country` | 2-літерний код країни ISO (наприклад, "US", "DE") | +| `language` | Код мови ISO 639-1 (наприклад, "en", "de") | +| `search_lang` | Код мови пошуку (лише Brave) | +| `freshness` | Фільтр часу: `day`, `week`, `month` або `year` | +| `date_after` | Результати після цієї дати (YYYY-MM-DD) | +| `date_before` | Результати до цієї дати (YYYY-MM-DD) | +| `ui_lang` | Код мови UI (лише Brave) | +| `domain_filter` | Масив allowlist/denylist доменів (лише Perplexity) | +| `max_tokens` | Загальний бюджет вмісту, типово 25000 (лише Perplexity) | +| `max_tokens_per_page`| Ліміт токенів на сторінку, типово 2048 (лише Perplexity) | - Не всі параметри працюють з усіма постачальниками. Режим `llm-context` у Brave + Не всі параметри працюють з усіма провайдерами. Режим Brave `llm-context` не приймає `ui_lang`, `freshness`, `date_after` і `date_before`. - Gemini, Grok і Kimi повертають одну синтезовану ШІ відповідь із посиланнями. Вони - приймають `count` для сумісності спільного інструмента, але це не змінює - форму відповіді з grounding. + Gemini, Grok і Kimi повертають одну синтезовану ШІ відповідь із цитуваннями. Вони + приймають `count` для сумісності зі спільним інструментом, але це не змінює + форму grounded-відповіді. Perplexity поводиться так само, коли ви використовуєте шлях сумісності Sonar/OpenRouter (`plugins.entries.perplexity.config.webSearch.baseUrl` / `model` або `OPENROUTER_API_KEY`). @@ -306,17 +312,17 @@ OpenClaw також може запропонувати необов’язко ## x_search -`x_search` виконує запити до дописів у X (раніше Twitter) за допомогою xAI і повертає -синтезовані ШІ відповіді з посиланнями. Він приймає запити природною мовою та +`x_search` виконує запити до дописів X (раніше Twitter) за допомогою xAI і повертає +синтезовані ШІ відповіді з цитуваннями. Він приймає запити природною мовою та необов’язкові структуровані фільтри. OpenClaw вмикає вбудований інструмент xAI `x_search` лише для запиту, який обслуговує цей виклик інструмента. - У документації xAI зазначено, що `x_search` підтримує пошук за ключовими словами, семантичний пошук, пошук користувачів + xAI документує `x_search` як інструмент, що підтримує пошук за ключовими словами, семантичний пошук, пошук користувачів і отримання тредів. Для статистики взаємодії окремого допису, як-от репости, - відповіді, закладки або перегляди, краще використовувати цільовий пошук за точним URL допису - або ID статусу. Широкі пошуки за ключовими словами можуть знайти потрібний допис, але повернути - менш повні метадані для окремого допису. Хороший підхід такий: спочатку знайдіть допис, потім + відповіді, закладки або перегляди, віддавайте перевагу цільовому пошуку за точним URL допису + або ID статусу. Широкі пошуки за ключовими словами можуть знайти потрібний допис, але повертати менш + повні метадані для окремого допису. Хороший шаблон такий: спочатку знайдіть допис, потім виконайте другий запит `x_search`, зосереджений саме на цьому дописі. @@ -348,15 +354,15 @@ OpenClaw також може запропонувати необов’язко ### Параметри x_search -| Параметр | Опис | -| ---------------------------- | ------------------------------------------------------------ | -| `query` | Пошуковий запит (обов’язковий) | -| `allowed_x_handles` | Обмежити результати конкретними X-акаунтами | -| `excluded_x_handles` | Виключити конкретні X-акаунти | -| `from_date` | Включати лише дописи на цю дату або пізніше (YYYY-MM-DD) | -| `to_date` | Включати лише дописи на цю дату або раніше (YYYY-MM-DD) | +| Параметр | Опис | +| -------------------------- | ---------------------------------------------------------- | +| `query` | Пошуковий запит (обов’язковий) | +| `allowed_x_handles` | Обмежити результати конкретними handle у X | +| `excluded_x_handles` | Виключити конкретні handle у X | +| `from_date` | Включати лише дописи на цю дату або пізніше (YYYY-MM-DD) | +| `to_date` | Включати лише дописи на цю дату або раніше (YYYY-MM-DD) | | `enable_image_understanding` | Дозволити xAI аналізувати зображення, прикріплені до відповідних дописів | -| `enable_video_understanding` | Дозволити xAI аналізувати відео, прикріплені до відповідних дописів | +| `enable_video_understanding` | Дозволити xAI аналізувати відео, прикріплені до відповідних дописів | ### Приклад x_search @@ -369,7 +375,7 @@ await x_search({ ``` ```javascript -// Per-post stats: use the exact status URL or status ID when possible +// Статистика окремого допису: за можливості використовуйте точний URL статусу або ID статусу await x_search({ query: "https://x.com/huntharo/status/1905678901234567890", }); @@ -378,23 +384,23 @@ await x_search({ ## Приклади ```javascript -// Basic search +// Базовий пошук await web_search({ query: "OpenClaw plugin SDK" }); -// German-specific search +// Пошук, орієнтований на Німеччину await web_search({ query: "TV online schauen", country: "DE", language: "de" }); -// Recent results (past week) +// Свіжі результати (за минулий тиждень) await web_search({ query: "AI developments", freshness: "week" }); -// Date range +// Діапазон дат await web_search({ query: "climate research", date_after: "2024-01-01", date_before: "2024-06-30", }); -// Domain filtering (Perplexity only) +// Фільтрація доменів (лише Perplexity) await web_search({ query: "product reviews", domain_filter: ["-reddit.com", "-pinterest.com"], @@ -403,7 +409,7 @@ await web_search({ ## Профілі інструментів -Якщо ви використовуєте профілі інструментів або списки дозволів, додайте `web_search`, `x_search` або `group:web`: +Якщо ви використовуєте профілі інструментів або allowlist, додайте `web_search`, `x_search` або `group:web`: ```json5 { @@ -414,9 +420,9 @@ await web_search({ } ``` -## Пов’язані матеріали +## Пов’язане -- [Web Fetch](/uk/tools/web-fetch) -- отримання URL і витягування придатного для читання вмісту -- [Web Browser](/uk/tools/browser) -- повна автоматизація браузера для сайтів із активним використанням JS -- [Grok Search](/uk/tools/grok-search) -- Grok як постачальник `web_search` +- [Web Fetch](/uk/tools/web-fetch) -- отримати URL і витягнути придатний для читання вміст +- [Web Browser](/uk/tools/browser) -- повна автоматизація браузера для сайтів із важким JS +- [Grok Search](/uk/tools/grok-search) -- Grok як провайдер `web_search` - [Ollama Web Search](/uk/tools/ollama-search) -- вебпошук без ключа через ваш хост Ollama