chore(i18n): refresh uk translations
This commit is contained in:
parent
6afcb87db8
commit
52997a2e05
@ -1,41 +1,39 @@
|
||||
---
|
||||
read_when:
|
||||
- Зміна маршрутизації каналу або поведінки вхідних повідомлень
|
||||
- Зміна маршрутизації каналів або поведінки вхідних повідомлень
|
||||
summary: Правила маршрутизації для кожного каналу (WhatsApp, Telegram, Discord, Slack) і спільний контекст
|
||||
title: Маршрутизація каналу
|
||||
title: Маршрутизація каналів
|
||||
x-i18n:
|
||||
generated_at: "2026-04-22T22:50:17Z"
|
||||
generated_at: "2026-04-23T00:49:05Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 3296ab8428cb815d0cc297d0c6e7479c5554ec45e1d90eef89a68833f5979d8d
|
||||
source_hash: e7d437d85d5edd3a0157fd683c6ec63d5d7e905e3e6bdce9a3ba11ddab97d3c2
|
||||
source_path: channels/channel-routing.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Канали та маршрутизація
|
||||
|
||||
OpenClaw маршрутизує відповіді **назад до каналу, звідки надійшло повідомлення**. Модель не вибирає канал; маршрутизація є детермінованою та керується конфігурацією хоста.
|
||||
OpenClaw маршрутизує відповіді **назад у той канал, звідки надійшло повідомлення**. Модель не вибирає канал; маршрутизація є детермінованою та контролюється конфігурацією хоста.
|
||||
|
||||
## Ключові терміни
|
||||
|
||||
- **Канал**: `telegram`, `whatsapp`, `discord`, `irc`, `googlechat`, `slack`, `signal`, `imessage`, `line`, а також канали розширень. `webchat` — це внутрішній канал інтерфейсу WebChat і не є налаштовуваним вихідним каналом.
|
||||
- **AccountId**: екземпляр облікового запису для каналу (якщо підтримується).
|
||||
- Необов’язковий обліковий запис каналу за замовчуванням: `channels.<channel>.defaultAccount` визначає, який обліковий запис використовується, коли вихідний шлях не вказує `accountId`.
|
||||
- У конфігураціях із кількома обліковими записами встановіть явне значення за замовчуванням (`defaultAccount` або `accounts.default`), коли налаштовано два або більше облікових записів. Без цього резервна маршрутизація може вибрати перший нормалізований ідентифікатор облікового запису.
|
||||
- **AgentId**: ізольоване робоче середовище + сховище сесій («мозок»).
|
||||
- **SessionKey**: ключ бакета, який використовується для зберігання контексту та керування конкурентністю.
|
||||
- **AccountId**: екземпляр облікового запису для певного каналу (якщо підтримується).
|
||||
- Необов’язковий типовий обліковий запис каналу: `channels.<channel>.defaultAccount` визначає, який обліковий запис використовується, коли вихідний шлях не вказує `accountId`.
|
||||
- У конфігураціях із кількома обліковими записами задайте явний типовий обліковий запис (`defaultAccount` або `accounts.default`), якщо налаштовано два або більше облікових записів. Без цього резервна маршрутизація може вибрати перший нормалізований ID облікового запису.
|
||||
- **AgentId**: ізольований робочий простір + сховище сесій («brain»).
|
||||
- **SessionKey**: ключ сегмента, який використовується для збереження контексту та керування паралелізмом.
|
||||
|
||||
## Форми ключів сесій (приклади)
|
||||
## Форми ключів сесії (приклади)
|
||||
|
||||
Більшість прямих повідомлень зводяться до **основної** сесії агента:
|
||||
За замовчуванням прямі повідомлення згортаються в **основну** сесію агента:
|
||||
|
||||
- `agent:<agentId>:<mainKey>` (за замовчуванням: `agent:main:main`)
|
||||
- `agent:<agentId>:<mainKey>` (типово: `agent:main:main`)
|
||||
|
||||
Прямі повідомлення Telegram-бота ізолюються за обліковим записом бота та відправником, навіть коли `session.dmScope` дорівнює `main`, щоб рішення щодо sandbox і політики інструментів могли розрізняти DM, що походять із каналу, від основної сесії агента:
|
||||
Навіть коли історія розмови в прямих повідомленнях спільна з main, політика sandbox та інструментів використовує похідний ключ середовища виконання direct-chat для кожного облікового запису для зовнішніх DM, щоб повідомлення, що надійшли з каналу, не розглядалися як локальні запуски main-сесії.
|
||||
|
||||
- `agent:<agentId>:telegram:<accountId>:direct:<senderId>`
|
||||
|
||||
Групи й канали залишаються ізольованими для кожного каналу:
|
||||
Групи та канали залишаються ізольованими для кожного каналу:
|
||||
|
||||
- Групи: `agent:<agentId>:<channel>:group:<id>`
|
||||
- Канали/кімнати: `agent:<agentId>:<channel>:channel:<id>`
|
||||
@ -52,16 +50,14 @@ OpenClaw маршрутизує відповіді **назад до канал
|
||||
|
||||
## Закріплення маршруту основних DM
|
||||
|
||||
Коли `session.dmScope` дорівнює `main`, прямі повідомлення можуть використовувати одну спільну основну сесію.
|
||||
Щоб запобігти перезапису `lastRoute` сесії прямими повідомленнями від не-власника,
|
||||
OpenClaw визначає закріпленого власника з `allowFrom`, якщо виконуються всі такі умови:
|
||||
Коли `session.dmScope` має значення `main`, прямі повідомлення можуть використовувати одну спільну основну сесію.
|
||||
Щоб `lastRoute` сесії не перезаписувався DM від не-власників, OpenClaw визначає закріпленого власника з `allowFrom`, якщо виконуються всі такі умови:
|
||||
|
||||
- `allowFrom` містить рівно один запис без wildcard.
|
||||
- Запис можна нормалізувати до конкретного ID відправника для цього каналу.
|
||||
- Відправник вхідного DM не збігається з цим закріпленим власником.
|
||||
|
||||
У разі такої невідповідності OpenClaw усе одно записує метадані вхідної сесії, але
|
||||
пропускає оновлення `lastRoute` основної сесії.
|
||||
У разі такої невідповідності OpenClaw усе одно записує метадані вхідної сесії, але пропускає оновлення `lastRoute` основної сесії.
|
||||
|
||||
## Правила маршрутизації (як вибирається агент)
|
||||
|
||||
@ -69,20 +65,20 @@ OpenClaw визначає закріпленого власника з `allowFro
|
||||
|
||||
1. **Точний збіг peer** (`bindings` з `peer.kind` + `peer.id`).
|
||||
2. **Збіг батьківського peer** (успадкування потоку).
|
||||
3. **Збіг guild + ролей** (Discord) через `guildId` + `roles`.
|
||||
3. **Збіг guild + roles** (Discord) через `guildId` + `roles`.
|
||||
4. **Збіг guild** (Discord) через `guildId`.
|
||||
5. **Збіг team** (Slack) через `teamId`.
|
||||
6. **Збіг облікового запису** (`accountId` у каналі).
|
||||
7. **Збіг каналу** (будь-який обліковий запис у цьому каналі, `accountId: "*"`).
|
||||
8. **Агент за замовчуванням** (`agents.list[].default`, інакше перший запис у списку, резервно — `main`).
|
||||
8. **Типовий агент** (`agents.list[].default`, інакше перший запис у списку, резервно — `main`).
|
||||
|
||||
Коли binding містить кілька полів збігу (`peer`, `guildId`, `teamId`, `roles`), **усі надані поля мають збігатися**, щоб цей binding було застосовано.
|
||||
Коли binding містить кілька полів збігу (`peer`, `guildId`, `teamId`, `roles`), **усі надані поля мають збігатися**, щоб цей binding застосувався.
|
||||
|
||||
Вибраний агент визначає, яке робоче середовище та сховище сесій використовуються.
|
||||
Вибраний агент визначає, який робочий простір і яке сховище сесій використовуються.
|
||||
|
||||
## Групи широкомовлення (запуск кількох агентів)
|
||||
## Групи трансляції (запуск кількох агентів)
|
||||
|
||||
Групи широкомовлення дають змогу запускати **кількох агентів** для одного й того самого peer **коли OpenClaw зазвичай відповідав би** (наприклад, у групах WhatsApp після згадки/активаційного фільтра).
|
||||
Групи трансляції дають змогу запускати **кількох агентів** для того самого peer, **коли OpenClaw зазвичай відповідає** (наприклад, у групах WhatsApp після проходження згадки/активації).
|
||||
|
||||
Конфігурація:
|
||||
|
||||
@ -96,19 +92,19 @@ OpenClaw визначає закріпленого власника з `allowFro
|
||||
}
|
||||
```
|
||||
|
||||
Див.: [Групи широкомовлення](/uk/channels/broadcast-groups).
|
||||
Див.: [Групи трансляції](/uk/channels/broadcast-groups).
|
||||
|
||||
## Огляд конфігурації
|
||||
|
||||
- `agents.list`: іменовані визначення агентів (робоче середовище, модель тощо).
|
||||
- `bindings`: зіставляє вхідні канали/облікові записи/peer з агентами.
|
||||
- `agents.list`: іменовані визначення агентів (робочий простір, модель тощо).
|
||||
- `bindings`: зіставлення вхідних каналів/облікових записів/peer з агентами.
|
||||
|
||||
Приклад:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [{ id: "support", name: "Підтримка", workspace: "~/.openclaw/workspace-support" }],
|
||||
list: [{ id: "support", name: "Support", workspace: "~/.openclaw/workspace-support" }],
|
||||
},
|
||||
bindings: [
|
||||
{ match: { channel: "slack", teamId: "T123" }, agentId: "support" },
|
||||
@ -119,23 +115,18 @@ OpenClaw визначає закріпленого власника з `allowFro
|
||||
|
||||
## Зберігання сесій
|
||||
|
||||
Сховища сесій розміщуються в каталозі стану (за замовчуванням `~/.openclaw`):
|
||||
Сховища сесій розміщуються в каталозі стану (типово `~/.openclaw`):
|
||||
|
||||
- `~/.openclaw/agents/<agentId>/sessions/sessions.json`
|
||||
- JSONL-транскрипти зберігаються поруч зі сховищем
|
||||
- Поруч зі сховищем розміщуються JSONL-транскрипти
|
||||
|
||||
Ви можете перевизначити шлях до сховища через `session.store` і шаблонізацію `{agentId}`.
|
||||
|
||||
Gateway та ACP під час виявлення сесій також сканують дискові сховища агентів під
|
||||
коренем `agents/` за замовчуванням і під коренями `session.store` з шаблонами. Виявлені
|
||||
сховища мають залишатися в межах цього обчисленого кореня агента й використовувати звичайний
|
||||
файл `sessions.json`. Символічні посилання та шляхи поза коренем ігноруються.
|
||||
Виявлення сесій Gateway і ACP також сканує дискові сховища агентів під типовим коренем `agents/` і під коренями `session.store` з шаблонами. Виявлені сховища мають залишатися всередині відповідного кореня агента після розв’язання шляху та використовувати звичайний файл `sessions.json`. Символічні посилання та шляхи поза коренем ігноруються.
|
||||
|
||||
## Поведінка WebChat
|
||||
|
||||
WebChat прив’язується до **вибраного агента** і за замовчуванням використовує
|
||||
основну сесію агента. Завдяки цьому WebChat дає змогу бачити міжканальний контекст
|
||||
для цього агента в одному місці.
|
||||
WebChat приєднується до **вибраного агента** і типово використовує основну сесію агента. Завдяки цьому WebChat дає змогу бачити міжканальний контекст для цього агента в одному місці.
|
||||
|
||||
## Контекст відповіді
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,68 +1,70 @@
|
||||
---
|
||||
read_when:
|
||||
- Діагностика підключення каналів або стану gateway
|
||||
- Розуміння команд CLI для перевірки стану та їх параметрів
|
||||
summary: Команди перевірки стану та моніторинг стану gateway
|
||||
- Діагностика підключення каналу або стану Gateway
|
||||
- Розуміння CLI-команд перевірки стану та їхніх параметрів
|
||||
summary: Команди перевірки стану та моніторинг стану Gateway
|
||||
title: Перевірки стану
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T18:03:16Z"
|
||||
generated_at: "2026-04-23T00:49:06Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: b8824bca34c4d1139f043481c75f0a65d83e54008898c34cf69c6f98fd04e819
|
||||
source_hash: 5ddcbe6fa913c5ba889f78cb417124c96b562cf8939410b1d6f66042dfb51a9f
|
||||
source_path: gateway/health.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Перевірки стану (CLI)
|
||||
|
||||
Короткий посібник, як перевірити підключення каналів без здогадок.
|
||||
Короткий посібник, як перевірити підключення каналу без здогадок.
|
||||
|
||||
## Швидкі перевірки
|
||||
|
||||
- `openclaw status` — локальний підсумок: доступність/режим gateway, підказка про оновлення, давність автентифікації підключених каналів, сесії та нещодавня активність.
|
||||
- `openclaw status` — локальне зведення: доступність/режим Gateway, підказка щодо оновлення, вік автентифікації пов’язаного каналу, сесії та нещодавня активність.
|
||||
- `openclaw status --all` — повна локальна діагностика (лише читання, кольоровий вивід, безпечно вставляти для налагодження).
|
||||
- `openclaw status --deep` — звертається до запущеного gateway для живої перевірки стану (`health` з `probe:true`), включно з перевірками каналів для кожного облікового запису, якщо це підтримується.
|
||||
- `openclaw health` — звертається до запущеного gateway за знімком його стану (лише WS; CLI не відкриває прямі сокети каналів).
|
||||
- `openclaw health --verbose` — примусово запускає живу перевірку стану і виводить відомості про підключення gateway.
|
||||
- `openclaw status --deep` — запитує у запущеного Gateway живу перевірку стану (`health` з `probe:true`), зокрема перевірки каналів для кожного облікового запису, якщо це підтримується.
|
||||
- `openclaw health` — запитує у запущеного Gateway знімок його стану (лише WS; без прямих сокетів каналів із CLI).
|
||||
- `openclaw health --verbose` — примусово запускає живу перевірку стану та виводить деталі підключення Gateway.
|
||||
- `openclaw health --json` — машинозчитуваний вивід знімка стану.
|
||||
- Надішліть `/status` як окреме повідомлення у WhatsApp/WebChat, щоб отримати відповідь зі станом без запуску агента.
|
||||
- Журнали: виконайте tail для `/tmp/openclaw/openclaw-*.log` і відфільтруйте `web-heartbeat`, `web-reconnect`, `web-auto-reply`, `web-inbound`.
|
||||
- Надішліть `/status` як окреме повідомлення у WhatsApp/WebChat, щоб отримати відповідь зі станом без виклику агента.
|
||||
- Логи: переглядайте `/tmp/openclaw/openclaw-*.log` і фільтруйте за `web-heartbeat`, `web-reconnect`, `web-auto-reply`, `web-inbound`.
|
||||
|
||||
## Глибока діагностика
|
||||
## Поглиблена діагностика
|
||||
|
||||
- Облікові дані на диску: `ls -l ~/.openclaw/credentials/whatsapp/<accountId>/creds.json` (`mtime` має бути нещодавнім).
|
||||
- Сховище сесій: `ls -l ~/.openclaw/agents/<agentId>/sessions/sessions.json` (шлях можна перевизначити в конфігурації). Кількість і нещодавні отримувачі відображаються через `status`.
|
||||
- Повторне прив’язування: `openclaw channels logout && openclaw channels login --verbose`, коли в журналах з’являються коди стану 409–515 або `loggedOut`. (Примітка: після сполучення потік входу через QR автоматично перезапускається один раз для статусу 515.)
|
||||
- Сховище сесій: `ls -l ~/.openclaw/agents/<agentId>/sessions/sessions.json` (шлях можна перевизначити в конфігурації). Кількість і нещодавні одержувачі відображаються через `status`.
|
||||
- Повторне пов’язування: `openclaw channels logout && openclaw channels login --verbose`, якщо в логах з’являються коди стану 409–515 або `loggedOut`. (Примітка: після прив’язки потік входу через QR автоматично перезапускається один раз для статусу 515.)
|
||||
- Діагностика увімкнена за замовчуванням. Gateway записує операційні факти, якщо не встановлено `diagnostics.enabled: false`. Події пам’яті записують кількість байтів RSS/heap, тиск порога та тиск зростання. Події надто великих навантажень записують, що було відхилено, обрізано або розбито на частини, а також розміри й ліміти, якщо вони доступні. Вони не записують текст повідомлення, вміст вкладень, тіло Webhook, необроблене тіло запиту чи відповіді, токени, cookies або секретні значення. Той самий Heartbeat запускає обмежений засіб запису стабільності, доступний через `openclaw gateway stability` або Gateway RPC `diagnostics.stability`. Фатальні завершення Gateway, тайм-аути завершення роботи та збої запуску під час перезапуску зберігають останній знімок цього записувача в `~/.openclaw/logs/stability/`, якщо події існують; перегляньте найновіший збережений пакет за допомогою `openclaw gateway stability --bundle latest`.
|
||||
- Для звітів про помилки виконайте `openclaw gateway diagnostics export` і додайте згенерований zip-файл. Експорт об’єднує підсумок у Markdown, найновіший пакет стабільності, очищені метадані логів, очищені знімки стану/здоров’я Gateway і форму конфігурації. Він призначений для поширення: текст чату, тіла Webhook, виводи інструментів, облікові дані, cookies, ідентифікатори облікових записів/повідомлень і секретні значення пропускаються або редагуються.
|
||||
|
||||
## Конфігурація монітора стану
|
||||
|
||||
- `gateway.channelHealthCheckMinutes`: як часто gateway перевіряє стан каналів. Типове значення: `5`. Установіть `0`, щоб глобально вимкнути перезапуски монітора стану.
|
||||
- `gateway.channelStaleEventThresholdMinutes`: як довго підключений канал може залишатися без подій, перш ніж монітор стану вважатиме його застарілим і перезапустить. Типове значення: `30`. Зберігайте це значення більшим або рівним `gateway.channelHealthCheckMinutes`.
|
||||
- `gateway.channelMaxRestartsPerHour`: ковзне обмеження на одну годину для перезапусків монітора стану на канал/обліковий запис. Типове значення: `10`.
|
||||
- `channels.<provider>.healthMonitor.enabled`: вимкнути перезапуски монітора стану для конкретного каналу, залишивши глобальний моніторинг увімкненим.
|
||||
- `gateway.channelHealthCheckMinutes`: як часто Gateway перевіряє стан каналу. Типове значення: `5`. Встановіть `0`, щоб глобально вимкнути перезапуски монітора стану.
|
||||
- `gateway.channelStaleEventThresholdMinutes`: як довго підключений канал може залишатися неактивним, перш ніж монітор стану вважатиме його застарілим і перезапустить. Типове значення: `30`. Тримайте це значення більшим або рівним `gateway.channelHealthCheckMinutes`.
|
||||
- `gateway.channelMaxRestartsPerHour`: ковзне обмеження на одну годину для перезапусків монітором стану на канал/обліковий запис. Типове значення: `10`.
|
||||
- `channels.<provider>.healthMonitor.enabled`: вимикає перезапуски монітора стану для конкретного каналу, залишаючи глобальний моніторинг увімкненим.
|
||||
- `channels.<provider>.accounts.<accountId>.healthMonitor.enabled`: перевизначення для кількох облікових записів, яке має пріоритет над налаштуванням на рівні каналу.
|
||||
- Ці перевизначення для окремих каналів застосовуються до вбудованих моніторів каналів, які наразі їх підтримують: Discord, Google Chat, iMessage, Microsoft Teams, Signal, Slack, Telegram і WhatsApp.
|
||||
- Ці перевизначення на рівні каналу застосовуються до вбудованих моніторів каналів, які наразі їх підтримують: Discord, Google Chat, iMessage, Microsoft Teams, Signal, Slack, Telegram і WhatsApp.
|
||||
|
||||
## Якщо щось не працює
|
||||
## Коли щось не працює
|
||||
|
||||
- `logged out` або статус 409–515 → виконайте повторне прив’язування через `openclaw channels logout`, потім `openclaw channels login`.
|
||||
- Gateway недоступний → запустіть його: `openclaw gateway --port 18789` (використовуйте `--force`, якщо порт зайнятий).
|
||||
- Немає вхідних повідомлень → переконайтеся, що підключений телефон онлайн і відправника дозволено (`channels.whatsapp.allowFrom`); для групових чатів переконайтеся, що список дозволу + правила згадування налаштовано правильно (`channels.whatsapp.groups`, `agents.list[].groupChat.mentionPatterns`).
|
||||
- `logged out` або статус 409–515 → виконайте повторне пов’язування через `openclaw channels logout`, а потім `openclaw channels login`.
|
||||
- Gateway недоступний → запустіть його: `openclaw gateway --port 18789` (використайте `--force`, якщо порт зайнятий).
|
||||
- Немає вхідних повідомлень → переконайтеся, що пов’язаний телефон онлайн і відправника дозволено (`channels.whatsapp.allowFrom`); для групових чатів переконайтеся, що правила allowlist і згадок збігаються (`channels.whatsapp.groups`, `agents.list[].groupChat.mentionPatterns`).
|
||||
|
||||
## Окрема команда "health"
|
||||
|
||||
`openclaw health` звертається до запущеного gateway за знімком його стану (CLI не відкриває прямі сокети
|
||||
каналів). Типово вона може повертати свіжий кешований знімок gateway; після цього
|
||||
gateway оновлює цей кеш у фоновому режимі. `openclaw health --verbose` натомість примусово
|
||||
запускає живу перевірку. Команда повідомляє про вік підключених creds/auth, якщо доступно,
|
||||
підсумки перевірок по каналах, підсумок сховища сесій і тривалість перевірки. Вона завершується
|
||||
з ненульовим кодом, якщо gateway недоступний або перевірка не вдалася/перевищила час очікування.
|
||||
`openclaw health` запитує у запущеного Gateway знімок його стану (без прямих сокетів
|
||||
каналів із CLI). За замовчуванням вона може повертати свіжий кешований знімок Gateway; після цього
|
||||
Gateway оновлює цей кеш у фоновому режимі. `openclaw health --verbose` натомість примусово виконує
|
||||
живу перевірку. Команда повідомляє про пов’язані облікові дані/вік автентифікації, якщо доступно,
|
||||
зведення перевірок для кожного каналу, зведення сховища сесій і тривалість перевірки. Вона завершується з ненульовим кодом,
|
||||
якщо Gateway недоступний або перевірка не вдалася/перевищила час очікування.
|
||||
|
||||
Параметри:
|
||||
|
||||
- `--json`: машинозчитуваний JSON-вивід
|
||||
- `--timeout <ms>`: перевизначити типове значення тайм-ауту перевірки 10 с
|
||||
- `--verbose`: примусово запустити живу перевірку і вивести відомості про підключення gateway
|
||||
- `--timeout <ms>`: перевизначає типовий тайм-аут перевірки 10 с
|
||||
- `--verbose`: примусово запускає живу перевірку й виводить деталі підключення Gateway
|
||||
- `--debug`: псевдонім для `--verbose`
|
||||
|
||||
Знімок стану включає: `ok` (boolean), `ts` (часова позначка), `durationMs` (час перевірки), стан для кожного каналу, доступність агентів і підсумок сховища сесій.
|
||||
Знімок стану містить: `ok` (boolean), `ts` (часова позначка), `durationMs` (час перевірки), стан для кожного каналу, доступність агента та зведення сховища сесій.
|
||||
|
||||
@ -1,34 +1,40 @@
|
||||
---
|
||||
read_when:
|
||||
- Реалізація або оновлення клієнтів Gateway WS
|
||||
- Реалізація або оновлення клієнтів шлюзу WS
|
||||
- Налагодження невідповідностей протоколу або збоїв підключення
|
||||
- Повторне генерування схем/моделей протоколу
|
||||
- Повторне генерування схеми/моделей протоколу
|
||||
summary: 'Протокол Gateway WebSocket: рукостискання, кадри, версіонування'
|
||||
title: Протокол Gateway
|
||||
x-i18n:
|
||||
generated_at: "2026-04-21T20:16:17Z"
|
||||
generated_at: "2026-04-23T00:49:07Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 6efa76f5f0faa6c10a8515b0cf457233e48551e3484a605dffaf6459ddff9231
|
||||
source_hash: 9d4ea65fbe31962ed8ece04a645cfe5aaff9fee8b5f89bc896b461cd45567634
|
||||
source_path: gateway/protocol.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Протокол Gateway (WebSocket)
|
||||
|
||||
Протокол Gateway WS — це **єдина контрольна площина + транспорт вузлів** для
|
||||
OpenClaw. Усі клієнти (CLI, веб-інтерфейс, програма macOS, вузли iOS/Android, headless
|
||||
вузли) підключаються через WebSocket і оголошують свою **роль** + **область
|
||||
доступу** під час рукостискання.
|
||||
Протокол Gateway WS — це **єдина контрольна площина + транспорт Node** для
|
||||
OpenClaw. Усі клієнти (CLI, веб-інтерфейс, застосунок macOS, Node iOS/Android, headless
|
||||
Node) підключаються через WebSocket і оголошують свою **роль** + **область видимості** під час рукостискання.
|
||||
|
||||
## Транспорт
|
||||
|
||||
- WebSocket, текстові кадри з корисним навантаженням JSON.
|
||||
- WebSocket, текстові кадри з JSON-корисним навантаженням.
|
||||
- Перший кадр **має** бути запитом `connect`.
|
||||
- Кадри до підключення обмежені 64 KiB. Після успішного рукостискання клієнти
|
||||
повинні дотримуватися обмежень `hello-ok.policy.maxPayload` і
|
||||
`hello-ok.policy.maxBufferedBytes`. Коли діагностику ввімкнено,
|
||||
надто великі вхідні кадри й повільні вихідні буфери генерують події `payload.large`
|
||||
до того, як Gateway закриє з’єднання або відкине відповідний кадр. Ці події зберігають
|
||||
розміри, обмеження, поверхні та безпечні коди причин. Вони не зберігають тіло повідомлення,
|
||||
вміст вкладень, тіло необробленого кадру, токени, cookie або секретні значення.
|
||||
|
||||
## Рукостискання (connect)
|
||||
|
||||
Gateway → Клієнт (виклик перед підключенням):
|
||||
Gateway → клієнт (виклик до підключення):
|
||||
|
||||
```json
|
||||
{
|
||||
@ -73,7 +79,7 @@ Gateway → Клієнт (виклик перед підключенням):
|
||||
}
|
||||
```
|
||||
|
||||
Gateway → Клієнт:
|
||||
Gateway → клієнт:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -95,13 +101,13 @@ Gateway → Клієнт:
|
||||
}
|
||||
```
|
||||
|
||||
`server`, `features`, `snapshot` і `policy` усі є обов’язковими за схемою
|
||||
`server`, `features`, `snapshot` і `policy` — усі обов’язкові за схемою
|
||||
(`src/gateway/protocol/schema/frames.ts`). `canvasHostUrl` є необов’язковим. `auth`
|
||||
повідомляє про погоджені роль/області доступу, коли вони доступні, а також включає `deviceToken`,
|
||||
коли gateway його видає.
|
||||
повідомляє про узгоджені роль/області видимості, коли вони доступні, і містить `deviceToken`,
|
||||
коли Gateway його видає.
|
||||
|
||||
Коли токен пристрою не видається, `hello-ok.auth` все одно може повідомляти про
|
||||
погоджені дозволи:
|
||||
Коли токен пристрою не видається, `hello-ok.auth` усе одно може повідомляти про узгоджені
|
||||
дозволи:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -112,7 +118,7 @@ Gateway → Клієнт:
|
||||
}
|
||||
```
|
||||
|
||||
Коли токен пристрою видається, `hello-ok` також включає:
|
||||
Коли токен пристрою видається, `hello-ok` також містить:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -124,8 +130,8 @@ Gateway → Клієнт:
|
||||
}
|
||||
```
|
||||
|
||||
Під час довіреної передачі bootstrap `hello-ok.auth` також може включати додаткові
|
||||
записи ролей з обмеженнями в `deviceTokens`:
|
||||
Під час trusted bootstrap handoff `hello-ok.auth` також може містити додаткові
|
||||
обмежені записи ролей у `deviceTokens`:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -144,15 +150,14 @@ Gateway → Клієнт:
|
||||
}
|
||||
```
|
||||
|
||||
Для вбудованого bootstrap-потоку node/operator основний токен вузла залишається
|
||||
`scopes: []`, а будь-який переданий токен оператора залишається обмеженим списком
|
||||
дозволених bootstrap-областей оператора (`operator.approvals`, `operator.read`,
|
||||
`operator.talk.secrets`, `operator.write`). Перевірки bootstrap-областей доступу
|
||||
залишаються прив’язаними до префікса ролі: записи оператора задовольняють лише
|
||||
запити оператора, а ролям, які не є оператором, усе одно потрібні області доступу
|
||||
під власним префіксом ролі.
|
||||
Для вбудованого потоку bootstrap node/operator основний токен node лишається
|
||||
`scopes: []`, а будь-який переданий токен operator лишається обмеженим списком дозволів
|
||||
bootstrap operator (`operator.approvals`, `operator.read`,
|
||||
`operator.talk.secrets`, `operator.write`). Перевірки областей видимості bootstrap лишаються
|
||||
прив’язаними до префікса ролі: записи operator задовольняють лише запити operator, а ролі, що не є operator,
|
||||
усе одно потребують областей видимості під власним префіксом ролі.
|
||||
|
||||
### Приклад node
|
||||
### Приклад Node
|
||||
|
||||
```json
|
||||
{
|
||||
@ -187,7 +192,7 @@ Gateway → Клієнт:
|
||||
}
|
||||
```
|
||||
|
||||
## Форматування кадрів
|
||||
## Кадрування
|
||||
|
||||
- **Запит**: `{type:"req", id, method, params}`
|
||||
- **Відповідь**: `{type:"res", id, ok, payload|error}`
|
||||
@ -195,16 +200,16 @@ Gateway → Клієнт:
|
||||
|
||||
Методи з побічними ефектами вимагають **ключі ідемпотентності** (див. схему).
|
||||
|
||||
## Ролі + області доступу
|
||||
## Ролі + області видимості
|
||||
|
||||
### Ролі
|
||||
|
||||
- `operator` = клієнт контрольної площини (CLI/UI/автоматизація).
|
||||
- `node` = хост можливостей (camera/screen/canvas/system.run).
|
||||
|
||||
### Області доступу (operator)
|
||||
### Області видимості (operator)
|
||||
|
||||
Поширені області доступу:
|
||||
Поширені області видимості:
|
||||
|
||||
- `operator.read`
|
||||
- `operator.write`
|
||||
@ -216,150 +221,154 @@ Gateway → Клієнт:
|
||||
`talk.config` з `includeSecrets: true` вимагає `operator.talk.secrets`
|
||||
(або `operator.admin`).
|
||||
|
||||
Зареєстровані Plugin методи Gateway RPC можуть запитувати власну область доступу
|
||||
оператора, але зарезервовані префікси базового адміністрування (`config.*`, `exec.approvals.*`, `wizard.*`,
|
||||
Методи Gateway RPC, зареєстровані Plugin, можуть запитувати власну область видимості operator, але
|
||||
зарезервовані базові префікси адміністратора (`config.*`, `exec.approvals.*`, `wizard.*`,
|
||||
`update.*`) завжди зіставляються з `operator.admin`.
|
||||
|
||||
Область доступу методу — це лише перший рівень перевірки. Деякі slash-команди,
|
||||
до яких звертаються через `chat.send`, застосовують суворіші перевірки на рівні
|
||||
команди поверх цього. Наприклад, постійні записи
|
||||
`/config set` і `/config unset` вимагають `operator.admin`.
|
||||
Область видимості методу — лише перший бар’єр. Деякі slash-команди, доступні через
|
||||
`chat.send`, додатково застосовують суворіші перевірки на рівні команд. Наприклад, сталі
|
||||
записи `/config set` і `/config unset` вимагають `operator.admin`.
|
||||
|
||||
`node.pair.approve` також має додаткову перевірку області доступу під час
|
||||
схвалення поверх базової області доступу методу:
|
||||
`node.pair.approve` також має додаткову перевірку області видимості під час схвалення поверх
|
||||
базової області видимості методу:
|
||||
|
||||
- запити без команд: `operator.pairing`
|
||||
- запити з командами вузла, які не є exec: `operator.pairing` + `operator.write`
|
||||
- запити, що включають `system.run`, `system.run.prepare` або `system.which`:
|
||||
- запити без команди: `operator.pairing`
|
||||
- запити з командами node, що не належать до exec: `operator.pairing` + `operator.write`
|
||||
- запити, які містять `system.run`, `system.run.prepare` або `system.which`:
|
||||
`operator.pairing` + `operator.admin`
|
||||
|
||||
### Caps/commands/permissions (node)
|
||||
|
||||
Вузли оголошують заявлені можливості під час підключення:
|
||||
Node оголошують твердження про можливості під час підключення:
|
||||
|
||||
- `caps`: високорівневі категорії можливостей.
|
||||
- `commands`: список дозволених команд для invoke.
|
||||
- `permissions`: детальні перемикачі (наприклад, `screen.record`, `camera.capture`).
|
||||
|
||||
Gateway розглядає їх як **заяви** і застосовує списки дозволених значень на боці сервера.
|
||||
Gateway трактує це як **заявлені можливості** та забезпечує примусові списки дозволів на боці сервера.
|
||||
|
||||
## Presence
|
||||
|
||||
- `system-presence` повертає записи з ключами за ідентичністю пристрою.
|
||||
- Записи присутності включають `deviceId`, `roles` і `scopes`, щоб інтерфейси могли показувати один рядок на пристрій,
|
||||
навіть коли він підключається і як **operator**, і як **node**.
|
||||
- `system-presence` повертає записи, згруповані за ідентичністю пристрою.
|
||||
- Записи presence містять `deviceId`, `roles` і `scopes`, щоб UI міг показувати один рядок на пристрій,
|
||||
навіть коли він підключений і як **operator**, і як **node**.
|
||||
|
||||
## Обмеження областей доступу для широкомовних подій
|
||||
## Обмеження областей видимості для broadcast-подій
|
||||
|
||||
Широкомовні події WebSocket, які надсилає сервер, обмежуються за областями доступу, щоб сесії з лише pairing-доступом або лише node-сесії не отримували пасивно вміст сесії.
|
||||
Broadcast-події WebSocket, які сервер надсилає клієнтам, обмежуються областями видимості, щоб сесії лише з pairing-областю або сесії тільки для node не отримували пасивно вміст сесій.
|
||||
|
||||
- **Кадри chat, agent і результатів інструментів** (включно з потоковими подіями `agent` і результатами викликів інструментів) вимагають щонайменше `operator.read`. Сесії без `operator.read` повністю пропускають ці кадри.
|
||||
- **Широкомовні події `plugin.*`, визначені Plugin**, обмежуються `operator.write` або `operator.admin` залежно від того, як Plugin їх зареєстрував.
|
||||
- **Події стану та транспорту** (`heartbeat`, `presence`, `tick`, життєвий цикл connect/disconnect тощо) залишаються без обмежень, щоб стан транспорту залишався видимим для кожної автентифікованої сесії.
|
||||
- **Невідомі сімейства широкомовних подій** за замовчуванням обмежуються за областями доступу (fail-closed), якщо зареєстрований обробник явно не послаблює це.
|
||||
- **Кадри chat, agent і tool-result** (включно з потоковими подіями `agent` і результатами викликів інструментів) вимагають щонайменше `operator.read`. Сесії без `operator.read` повністю пропускають ці кадри.
|
||||
- **Broadcast-події `plugin.*`, визначені Plugin**, обмежуються `operator.write` або `operator.admin` залежно від того, як Plugin їх зареєстрував.
|
||||
- **Події стану й транспорту** (`heartbeat`, `presence`, `tick`, життєвий цикл connect/disconnect тощо) лишаються без обмежень, щоб стан транспорту залишався спостережуваним для кожної автентифікованої сесії.
|
||||
- **Невідомі сімейства broadcast-подій** за замовчуванням обмежуються областями видимості (fail-closed), якщо зареєстрований обробник явно не послаблює це правило.
|
||||
|
||||
Кожне клієнтське підключення зберігає власний номер послідовності для цього клієнта, щоб широкомовні повідомлення зберігали монотонний порядок на цьому сокеті, навіть коли різні клієнти бачать різні підмножини потоку подій, відфільтровані за областями доступу.
|
||||
Кожне клієнтське з’єднання підтримує власний номер послідовності для конкретного клієнта, тому broadcast-події зберігають монотонне впорядкування на цьому сокеті, навіть коли різні клієнти бачать різні підмножини потоку подій, відфільтровані за областями видимості.
|
||||
|
||||
## Поширені сімейства методів RPC
|
||||
## Поширені сімейства RPC-методів
|
||||
|
||||
Ця сторінка не є згенерованим повним дампом, але публічна поверхня WS ширша,
|
||||
ніж приклади рукостискання/автентифікації вище. Це основні сімейства методів,
|
||||
які Gateway надає сьогодні.
|
||||
ніж наведені вище приклади рукостискання/автентифікації. Це основні сімейства методів, які
|
||||
Gateway відкриває сьогодні.
|
||||
|
||||
`hello-ok.features.methods` — це консервативний список виявлення, побудований з
|
||||
`src/gateway/server-methods-list.ts` плюс експортів методів завантажених plugin/channel.
|
||||
Сприймайте його як виявлення можливостей, а не як згенерований дамп кожного допоміжного виклику,
|
||||
реалізованого в `src/gateway/server-methods/*.ts`.
|
||||
`hello-ok.features.methods` — це консервативний список виявлення можливостей, побудований із
|
||||
`src/gateway/server-methods-list.ts` плюс експорту методів завантажених plugin/channel.
|
||||
Сприймайте його як виявлення можливостей, а не як згенерований дамп усіх допоміжних викликів,
|
||||
реалізованих у `src/gateway/server-methods/*.ts`.
|
||||
|
||||
### Система та ідентичність
|
||||
|
||||
- `health` повертає кешований або щойно перевірений знімок стану gateway.
|
||||
- `status` повертає зведення gateway у стилі `/status`; чутливі поля
|
||||
включаються лише для операторських клієнтів з admin-областю доступу.
|
||||
- `gateway.identity.get` повертає ідентичність пристрою gateway, яка використовується в relay і
|
||||
потоках pairing.
|
||||
- `system-presence` повертає поточний знімок присутності для підключених
|
||||
- `health` повертає кешований або щойно перевірений знімок стану Gateway.
|
||||
- `diagnostics.stability` повертає нещодавній обмежений засіб запису діагностичної
|
||||
стабільності. Він зберігає операційні метадані, такі як назви подій, кількість, розміри в байтах,
|
||||
показники пам’яті, стан черги/сесії, назви channel/plugin і ідентифікатори сесій.
|
||||
Він не зберігає текст chat, тіла webhook, вивід інструментів, необроблені тіла запитів або
|
||||
відповідей, токени, cookie чи секретні значення. Потрібна область видимості operator read.
|
||||
- `status` повертає підсумок Gateway у стилі `/status`; чутливі поля
|
||||
включаються лише для клієнтів operator з областю видимості admin.
|
||||
- `gateway.identity.get` повертає ідентичність пристрою Gateway, що використовується в потоках relay і
|
||||
pairing.
|
||||
- `system-presence` повертає поточний знімок presence для підключених
|
||||
пристроїв operator/node.
|
||||
- `system-event` додає системну подію і може оновлювати/транслювати контекст
|
||||
присутності.
|
||||
- `system-event` додає системну подію та може оновлювати/транслювати контекст
|
||||
presence.
|
||||
- `last-heartbeat` повертає останню збережену подію Heartbeat.
|
||||
- `set-heartbeats` перемикає обробку Heartbeat на gateway.
|
||||
- `set-heartbeats` перемикає обробку Heartbeat на Gateway.
|
||||
|
||||
### Моделі та використання
|
||||
|
||||
- `models.list` повертає каталог моделей, дозволених у середовищі виконання.
|
||||
- `usage.status` повертає зведення вікон використання/залишкової квоти провайдерів.
|
||||
- `usage.cost` повертає зведення агрегованої вартості використання за діапазон дат.
|
||||
- `doctor.memory.status` повертає стан готовності vector-memory / embedding для
|
||||
- `models.list` повертає каталог моделей, дозволених у поточному середовищі виконання.
|
||||
- `usage.status` повертає зведення вікон використання/залишкових квот провайдера.
|
||||
- `usage.cost` повертає зведення агрегованих витрат використання за діапазон дат.
|
||||
- `doctor.memory.status` повертає готовність векторної пам’яті / вбудовувань для
|
||||
активного робочого простору агента за замовчуванням.
|
||||
- `sessions.usage` повертає зведення використання для кожної сесії.
|
||||
- `sessions.usage` повертає зведення використання за сесіями.
|
||||
- `sessions.usage.timeseries` повертає часовий ряд використання для однієї сесії.
|
||||
- `sessions.usage.logs` повертає записи журналу використання для однієї сесії.
|
||||
|
||||
### Канали та допоміжні засоби входу
|
||||
|
||||
- `channels.status` повертає зведення стану вбудованих і bundled каналів/plugin.
|
||||
- `channels.logout` виходить із конкретного каналу/облікового запису, якщо канал
|
||||
- `channels.status` повертає зведення стану вбудованих і bundled channel/plugin.
|
||||
- `channels.logout` виходить із конкретного channel/account, якщо channel
|
||||
підтримує вихід.
|
||||
- `web.login.start` запускає QR/web-потік входу для поточного QR-сумісного веб-
|
||||
провайдера каналу.
|
||||
- `web.login.wait` очікує завершення цього QR/web-потоку входу і запускає
|
||||
канал у разі успіху.
|
||||
- `push.test` надсилає тестовий APNs push до зареєстрованого вузла iOS.
|
||||
- `web.login.start` запускає потік входу QR/web для поточного web
|
||||
channel provider із підтримкою QR.
|
||||
- `web.login.wait` очікує завершення цього потоку входу QR/web і запускає
|
||||
channel у разі успіху.
|
||||
- `push.test` надсилає тестовий APNs push на зареєстрований Node iOS.
|
||||
- `voicewake.get` повертає збережені тригери слова активації.
|
||||
- `voicewake.set` оновлює тригери слова активації й транслює зміну.
|
||||
- `voicewake.set` оновлює тригери слова активації та транслює зміну.
|
||||
|
||||
### Повідомлення та журнали
|
||||
|
||||
- `send` — це прямий RPC вихідної доставки для цільових надсилань
|
||||
у канал/обліковий запис/гілку поза виконавцем чату.
|
||||
- `logs.tail` повертає tail налаштованого файлового журналу gateway з курсором/лімітом і
|
||||
керуванням максимальною кількістю байтів.
|
||||
- `send` — це прямий RPC доставки назовні для
|
||||
надсилання до channel/account/thread поза виконавцем chat.
|
||||
- `logs.tail` повертає хвіст налаштованого файлового журналу Gateway з керуванням курсором/лімітом і
|
||||
максимальним розміром у байтах.
|
||||
|
||||
### Talk і TTS
|
||||
|
||||
- `talk.config` повертає ефективне корисне навантаження конфігурації Talk; `includeSecrets`
|
||||
вимагає `operator.talk.secrets` (або `operator.admin`).
|
||||
- `talk.mode` встановлює/транслює поточний стан режиму Talk для клієнтів
|
||||
WebChat/Control UI.
|
||||
- `talk.speak` синтезує мовлення через активного провайдера мовлення Talk.
|
||||
- `talk.mode` установлює/транслює поточний стан режиму Talk для
|
||||
клієнтів WebChat/Control UI.
|
||||
- `talk.speak` синтезує мовлення через активного мовленнєвого провайдера Talk.
|
||||
- `tts.status` повертає стан увімкнення TTS, активного провайдера, резервних провайдерів
|
||||
і стан конфігурації провайдера.
|
||||
- `tts.providers` повертає видимий інвентар провайдерів TTS.
|
||||
- `tts.providers` повертає видимий перелік провайдерів TTS.
|
||||
- `tts.enable` і `tts.disable` перемикають стан налаштувань TTS.
|
||||
- `tts.setProvider` оновлює бажаного провайдера TTS.
|
||||
- `tts.convert` виконує одноразове перетворення тексту в мовлення.
|
||||
- `tts.convert` виконує одноразове перетворення тексту на мовлення.
|
||||
|
||||
### Secrets, config, update і wizard
|
||||
### Секрети, конфігурація, оновлення та майстер налаштування
|
||||
|
||||
- `secrets.reload` повторно визначає активні SecretRef і замінює стан секретів середовища виконання
|
||||
- `secrets.reload` повторно розв’язує активні SecretRefs і замінює стан секретів у середовищі виконання
|
||||
лише за повного успіху.
|
||||
- `secrets.resolve` визначає призначення секретів для цілі набору
|
||||
команд/цілей.
|
||||
- `secrets.resolve` розв’язує призначення секретів для цільових команд для конкретного
|
||||
набору command/target.
|
||||
- `config.get` повертає поточний знімок конфігурації та хеш.
|
||||
- `config.set` записує перевірене корисне навантаження конфігурації.
|
||||
- `config.patch` об’єднує часткове оновлення конфігурації.
|
||||
- `config.apply` перевіряє й замінює повне корисне навантаження конфігурації.
|
||||
- `config.schema` повертає корисне навантаження активної схеми конфігурації, яке використовують Control UI і
|
||||
інструменти CLI: схема, `uiHints`, версія і метадані генерації,
|
||||
включно з метаданими схем plugin + channel, коли середовище виконання може їх завантажити. Схема
|
||||
включає метадані полів `title` / `description`, отримані з тих самих міток
|
||||
і довідкового тексту, що використовує UI, включно з вкладеними object, wildcard, array-item
|
||||
і гілками композиції `anyOf` / `oneOf` / `allOf`, коли існує відповідна
|
||||
документація полів.
|
||||
- `config.schema.lookup` повертає корисне навантаження пошуку з областю шляху для одного шляху конфігурації:
|
||||
- `config.apply` перевіряє + замінює повне корисне навантаження конфігурації.
|
||||
- `config.schema` повертає корисне навантаження поточної схеми конфігурації, яке використовують Control UI і
|
||||
інструменти CLI: схема, `uiHints`, версія та метадані генерації, зокрема
|
||||
метадані схеми plugin + channel, коли середовище виконання може їх завантажити. Схема
|
||||
містить метадані полів `title` / `description`, похідні від тих самих міток
|
||||
і тексту довідки, які використовує UI, зокрема для вкладених об’єктів, wildcard,
|
||||
елементів масиву та гілок композиції `anyOf` / `oneOf` / `allOf`, коли існує
|
||||
відповідна документація для полів.
|
||||
- `config.schema.lookup` повертає корисне навантаження пошуку з обмеженням шляхом для одного шляху конфігурації:
|
||||
нормалізований шлях, неглибокий вузол схеми, зіставлену підказку + `hintPath` і
|
||||
зведення безпосередніх дочірніх елементів для детального перегляду UI/CLI.
|
||||
- Вузли схеми пошуку зберігають документацію для користувача та поширені поля перевірки:
|
||||
зведення безпосередніх дочірніх елементів для деталізації в UI/CLI.
|
||||
- Вузли схеми пошуку зберігають орієнтовану на користувача документацію та типові поля перевірки:
|
||||
`title`, `description`, `type`, `enum`, `const`, `format`, `pattern`,
|
||||
числові/рядкові/масивні/об’єктні межі й булеві прапорці, як-от
|
||||
числові/рядкові/масивні/об’єктні межі та булеві прапорці, такі як
|
||||
`additionalProperties`, `deprecated`, `readOnly`, `writeOnly`.
|
||||
- Зведення дочірніх елементів показують `key`, нормалізований `path`, `type`, `required`,
|
||||
`hasChildren`, а також зіставлені `hint` / `hintPath`.
|
||||
- `update.run` запускає потік оновлення gateway і планує перезапуск лише тоді,
|
||||
- `update.run` запускає потік оновлення Gateway і планує перезапуск лише тоді,
|
||||
коли саме оновлення було успішним.
|
||||
- `wizard.start`, `wizard.next`, `wizard.status` і `wizard.cancel` надають
|
||||
майстер налаштування через WS RPC.
|
||||
- `wizard.start`, `wizard.next`, `wizard.status` і `wizard.cancel` відкривають
|
||||
майстер налаштування onboarding через WS RPC.
|
||||
|
||||
### Наявні основні сімейства
|
||||
|
||||
@ -369,10 +378,10 @@ Gateway розглядає їх як **заяви** і застосовує сп
|
||||
- `agents.create`, `agents.update` і `agents.delete` керують записами агентів і
|
||||
прив’язкою робочого простору.
|
||||
- `agents.files.list`, `agents.files.get` і `agents.files.set` керують файлами
|
||||
bootstrap-робочого простору, доступними для агента.
|
||||
- `agent.identity.get` повертає ефективну ідентичність помічника для агента або
|
||||
bootstrap робочого простору, відкритими для агента.
|
||||
- `agent.identity.get` повертає фактичну ідентичність помічника для агента або
|
||||
сесії.
|
||||
- `agent.wait` очікує завершення запуску й повертає термінальний знімок, якщо
|
||||
- `agent.wait` очікує завершення запуску й повертає термінальний знімок, коли
|
||||
він доступний.
|
||||
|
||||
#### Керування сесіями
|
||||
@ -382,162 +391,163 @@ Gateway розглядає їх як **заяви** і застосовує сп
|
||||
змін сесії для поточного WS-клієнта.
|
||||
- `sessions.messages.subscribe` і `sessions.messages.unsubscribe` перемикають
|
||||
підписки на події транскрипту/повідомлень для однієї сесії.
|
||||
- `sessions.preview` повертає обмежені попередні перегляди транскрипту для
|
||||
конкретних ключів сесій.
|
||||
- `sessions.resolve` визначає або канонізує ціль сесії.
|
||||
- `sessions.preview` повертає обмежені попередні перегляди транскрипту для конкретних
|
||||
ключів сесій.
|
||||
- `sessions.resolve` розв’язує або канонізує ціль сесії.
|
||||
- `sessions.create` створює новий запис сесії.
|
||||
- `sessions.send` надсилає повідомлення в наявну сесію.
|
||||
- `sessions.steer` — це варіант переривання й перенаправлення для активної сесії.
|
||||
- `sessions.steer` — це варіант переривання й спрямування для активної сесії.
|
||||
- `sessions.abort` перериває активну роботу для сесії.
|
||||
- `sessions.patch` оновлює метадані/перевизначення сесії.
|
||||
- `sessions.reset`, `sessions.delete` і `sessions.compact` виконують
|
||||
обслуговування сесії.
|
||||
- `sessions.get` повертає повний збережений рядок сесії.
|
||||
- виконання чату, як і раніше, використовує `chat.history`, `chat.send`, `chat.abort` і
|
||||
- виконання chat, як і раніше, використовує `chat.history`, `chat.send`, `chat.abort` і
|
||||
`chat.inject`.
|
||||
- `chat.history` нормалізується для відображення для UI-клієнтів: вбудовані теги директив
|
||||
видаляються з видимого тексту, корисні навантаження XML викликів інструментів у форматі простого тексту (включно з
|
||||
- `chat.history` нормалізується для відображення клієнтам UI: вбудовані теги директив
|
||||
прибираються з видимого тексту, XML-корисні навантаження викликів інструментів у звичайному тексті (зокрема
|
||||
`<tool_call>...</tool_call>`, `<function_call>...</function_call>`,
|
||||
`<tool_calls>...</tool_calls>`, `<function_calls>...</function_calls>` і
|
||||
обрізаними блоками викликів інструментів), а також витеклі ASCII/повноширинні токени керування моделі
|
||||
видаляються, чисті рядки помічника з мовчазними токенами, такі як точні `NO_REPLY` /
|
||||
`no_reply`, пропускаються, а надмірно великі рядки можуть бути замінені заповнювачами.
|
||||
обрізані блоки викликів інструментів), а також витеклі ASCII/повноширинні керівні токени моделі
|
||||
прибираються, рядки помічника, що складаються лише з беззвучних токенів, такі як точні `NO_REPLY` /
|
||||
`no_reply`, опускаються, а надто великі рядки можуть замінюватися заповнювачами.
|
||||
|
||||
#### Pairing пристроїв і токени пристроїв
|
||||
|
||||
- `device.pair.list` повертає очікувальні й схвалені спарені пристрої.
|
||||
- `device.pair.list` повертає очікувальні та схвалені спарені пристрої.
|
||||
- `device.pair.approve`, `device.pair.reject` і `device.pair.remove` керують
|
||||
записами pairing пристроїв.
|
||||
- `device.token.rotate` ротує токен спареного пристрою в межах його схваленої ролі
|
||||
та меж областей доступу.
|
||||
- `device.token.rotate` обертає токен спареного пристрою в межах його схвалених
|
||||
ролі та областей видимості.
|
||||
- `device.token.revoke` відкликає токен спареного пристрою.
|
||||
|
||||
#### Pairing вузлів, invoke і відкладена робота
|
||||
#### Pairing Node, invoke і очікувальна робота
|
||||
|
||||
- `node.pair.request`, `node.pair.list`, `node.pair.approve`,
|
||||
`node.pair.reject` і `node.pair.verify` охоплюють pairing вузлів і bootstrap-перевірку.
|
||||
- `node.list` і `node.describe` повертають стан відомого/підключеного вузла.
|
||||
- `node.rename` оновлює мітку спареного вузла.
|
||||
- `node.invoke` пересилає команду підключеному вузлу.
|
||||
`node.pair.reject` і `node.pair.verify` охоплюють pairing Node і bootstrap
|
||||
verification.
|
||||
- `node.list` і `node.describe` повертають стан відомих/підключених Node.
|
||||
- `node.rename` оновлює мітку спареного Node.
|
||||
- `node.invoke` пересилає команду підключеному Node.
|
||||
- `node.invoke.result` повертає результат для запиту invoke.
|
||||
- `node.event` переносить події, що походять від вузла, назад у gateway.
|
||||
- `node.event` передає події, що походять від Node, назад у Gateway.
|
||||
- `node.canvas.capability.refresh` оновлює токени можливостей canvas з обмеженою областю дії.
|
||||
- `node.pending.pull` і `node.pending.ack` — це API черги підключеного вузла.
|
||||
- `node.pending.enqueue` і `node.pending.drain` керують стійкою відкладеною роботою
|
||||
для офлайн/відключених вузлів.
|
||||
- `node.pending.pull` і `node.pending.ack` — це API черги для підключених Node.
|
||||
- `node.pending.enqueue` і `node.pending.drain` керують стійкою очікувальною роботою
|
||||
для офлайн/відключених Node.
|
||||
|
||||
#### Сімейства approval
|
||||
#### Сімейства схвалень
|
||||
|
||||
- `exec.approval.request`, `exec.approval.get`, `exec.approval.list` і
|
||||
`exec.approval.resolve` охоплюють одноразові запити approval для exec плюс
|
||||
пошук/повторення очікувальних approval.
|
||||
- `exec.approval.waitDecision` очікує на одне очікувальне approval для exec і повертає
|
||||
остаточне рішення (або `null` у разі тайм-ауту).
|
||||
- `exec.approvals.get` і `exec.approvals.set` керують знімками політики
|
||||
approval exec у gateway.
|
||||
- `exec.approvals.node.get` і `exec.approvals.node.set` керують локальною для вузла політикою
|
||||
approval exec через команди relay вузла.
|
||||
`exec.approval.resolve` охоплюють одноразові запити на схвалення exec плюс
|
||||
пошук/повторення очікувальних схвалень.
|
||||
- `exec.approval.waitDecision` очікує рішення щодо одного очікувального схвалення exec і повертає
|
||||
фінальне рішення (або `null` у разі тайм-ауту).
|
||||
- `exec.approvals.get` і `exec.approvals.set` керують знімками політики схвалення exec
|
||||
Gateway.
|
||||
- `exec.approvals.node.get` і `exec.approvals.node.set` керують локальною для Node політикою exec
|
||||
approval через команди relay Node.
|
||||
- `plugin.approval.request`, `plugin.approval.list`,
|
||||
`plugin.approval.waitDecision` і `plugin.approval.resolve` охоплюють
|
||||
потоки approval, визначені Plugin.
|
||||
потоки схвалення, визначені Plugin.
|
||||
|
||||
#### Інші основні сімейства
|
||||
|
||||
- automation:
|
||||
- `wake` планує негайне або наступне на Heartbeat вбудовування тексту пробудження
|
||||
- `wake` планує негайне або на наступний Heartbeat введення тексту пробудження
|
||||
- `cron.list`, `cron.status`, `cron.add`, `cron.update`, `cron.remove`,
|
||||
`cron.run`, `cron.runs`
|
||||
- skills/tools: `commands.list`, `skills.*`, `tools.catalog`, `tools.effective`
|
||||
|
||||
### Поширені сімейства подій
|
||||
|
||||
- `chat`: оновлення UI-чату, такі як `chat.inject` та інші події чату
|
||||
лише для транскрипту.
|
||||
- `chat`: оновлення UI chat, такі як `chat.inject` та інші події chat,
|
||||
пов’язані лише з транскриптом.
|
||||
- `session.message` і `session.tool`: оновлення транскрипту/потоку подій для
|
||||
підписаної сесії.
|
||||
- `sessions.changed`: індекс сесії або метадані змінено.
|
||||
- `presence`: оновлення знімка системної присутності.
|
||||
сесії, на яку оформлено підписку.
|
||||
- `sessions.changed`: індекс сесій або метадані змінено.
|
||||
- `presence`: оновлення знімка системного presence.
|
||||
- `tick`: періодична подія keepalive / перевірки доступності.
|
||||
- `health`: оновлення знімка стану gateway.
|
||||
- `health`: оновлення знімка стану Gateway.
|
||||
- `heartbeat`: оновлення потоку подій Heartbeat.
|
||||
- `cron`: подія зміни запуску/завдання Cron.
|
||||
- `shutdown`: сповіщення про вимкнення gateway.
|
||||
- `node.pair.requested` / `node.pair.resolved`: життєвий цикл pairing вузла.
|
||||
- `node.invoke.request`: трансляція запиту invoke вузла.
|
||||
- `shutdown`: сповіщення про завершення роботи Gateway.
|
||||
- `node.pair.requested` / `node.pair.resolved`: життєвий цикл pairing Node.
|
||||
- `node.invoke.request`: broadcast запиту invoke для Node.
|
||||
- `device.pair.requested` / `device.pair.resolved`: життєвий цикл спареного пристрою.
|
||||
- `voicewake.changed`: конфігурацію тригерів слова активації змінено.
|
||||
- `voicewake.changed`: змінено конфігурацію тригера слова активації.
|
||||
- `exec.approval.requested` / `exec.approval.resolved`: життєвий цикл
|
||||
approval exec.
|
||||
схвалення exec.
|
||||
- `plugin.approval.requested` / `plugin.approval.resolved`: життєвий цикл
|
||||
approval Plugin.
|
||||
схвалення plugin.
|
||||
|
||||
### Допоміжні методи node
|
||||
### Допоміжні методи Node
|
||||
|
||||
- Вузли можуть викликати `skills.bins`, щоб отримати поточний список виконуваних файлів skill
|
||||
для перевірок auto-allow.
|
||||
- Node можуть викликати `skills.bins`, щоб отримати поточний список виконуваних файлів skill
|
||||
для перевірок автоматичного дозволу.
|
||||
|
||||
### Допоміжні методи operator
|
||||
|
||||
- Оператори можуть викликати `commands.list` (`operator.read`), щоб отримати інвентар команд середовища виконання для агента.
|
||||
- `agentId` необов’язковий; пропустіть його, щоб читати робочий простір агента за замовчуванням.
|
||||
- `scope` керує тим, яку поверхню націлює основний `name`:
|
||||
- Operator можуть викликати `commands.list` (`operator.read`), щоб отримати перелік команд середовища виконання для агента.
|
||||
- `agentId` необов’язковий; не вказуйте його, щоб читати робочий простір агента за замовчуванням.
|
||||
- `scope` керує тим, на яку поверхню націлений основний `name`:
|
||||
- `text` повертає основний текстовий токен команди без початкового `/`
|
||||
- `native` і стандартний шлях `both` повертають залежні від провайдера native-імена,
|
||||
- `native` і стандартний шлях `both` повертають орієнтовані на провайдера native-імена,
|
||||
коли вони доступні
|
||||
- `textAliases` містить точні slash-аліаси, такі як `/model` і `/m`.
|
||||
- `nativeName` містить залежну від провайдера native-назву команди, коли вона існує.
|
||||
- `provider` необов’язковий і впливає лише на native-іменування та доступність native-команд Plugin.
|
||||
- `nativeName` містить орієнтовану на провайдера native-назву команди, коли вона існує.
|
||||
- `provider` необов’язковий і впливає лише на native-іменування та доступність native-команд plugin.
|
||||
- `includeArgs=false` пропускає серіалізовані метадані аргументів у відповіді.
|
||||
- Оператори можуть викликати `tools.catalog` (`operator.read`), щоб отримати каталог інструментів середовища виконання для
|
||||
агента. Відповідь включає згруповані інструменти та метадані походження:
|
||||
- Operator можуть викликати `tools.catalog` (`operator.read`), щоб отримати каталог інструментів середовища виконання для
|
||||
агента. Відповідь містить згруповані інструменти та метадані походження:
|
||||
- `source`: `core` або `plugin`
|
||||
- `pluginId`: власник plugin, коли `source="plugin"`
|
||||
- `optional`: чи є інструмент plugin необов’язковим
|
||||
- Оператори можуть викликати `tools.effective` (`operator.read`), щоб отримати фактичний інвентар інструментів
|
||||
середовища виконання для сесії.
|
||||
- Operator можуть викликати `tools.effective` (`operator.read`), щоб отримати фактичний перелік інструментів середовища виконання
|
||||
для сесії.
|
||||
- `sessionKey` обов’язковий.
|
||||
- Gateway виводить довірений контекст середовища виконання із сесії на боці сервера замість прийняття
|
||||
auth або контексту доставки, наданих викликачем.
|
||||
- Відповідь має область дії сесії та відображає те, що активна розмова може використовувати прямо зараз,
|
||||
включно з інструментами core, plugin і channel.
|
||||
- Оператори можуть викликати `skills.status` (`operator.read`), щоб отримати видимий
|
||||
інвентар Skills для агента.
|
||||
- `agentId` необов’язковий; пропустіть його, щоб читати робочий простір агента за замовчуванням.
|
||||
- Відповідь включає придатність, відсутні вимоги, перевірки конфігурації та
|
||||
санітизовані параметри встановлення без розкриття необроблених значень секретів.
|
||||
- Оператори можуть викликати `skills.search` і `skills.detail` (`operator.read`) для
|
||||
- Gateway виводить довірений контекст середовища виконання із сесії на боці сервера, замість того щоб приймати
|
||||
наданий викликачем контекст автентифікації або доставки.
|
||||
- Відповідь має область дії сесії та відображає те, що активна розмова може використовувати просто зараз,
|
||||
зокрема core, plugin і channel tools.
|
||||
- Operator можуть викликати `skills.status` (`operator.read`), щоб отримати видимий
|
||||
перелік skills для агента.
|
||||
- `agentId` необов’язковий; не вказуйте його, щоб читати робочий простір агента за замовчуванням.
|
||||
- Відповідь містить відповідність вимогам, відсутні вимоги, перевірки конфігурації та
|
||||
санітизовані параметри встановлення без розкриття необроблених секретних значень.
|
||||
- Operator можуть викликати `skills.search` і `skills.detail` (`operator.read`) для
|
||||
метаданих виявлення ClawHub.
|
||||
- Оператори можуть викликати `skills.install` (`operator.admin`) у двох режимах:
|
||||
- Режим ClawHub: `{ source: "clawhub", slug, version?, force? }` встановлює
|
||||
теку skill у каталог `skills/` робочого простору агента за замовчуванням.
|
||||
- Режим встановлювача Gateway: `{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }`
|
||||
запускає оголошену дію `metadata.openclaw.install` на хості gateway.
|
||||
- Оператори можуть викликати `skills.update` (`operator.admin`) у двох режимах:
|
||||
- Operator можуть викликати `skills.install` (`operator.admin`) у двох режимах:
|
||||
- Режим ClawHub: `{ source: "clawhub", slug, version?, force? }` установлює
|
||||
папку skill у каталог `skills/` робочого простору агента за замовчуванням.
|
||||
- Режим інсталятора Gateway: `{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }`
|
||||
запускає оголошену дію `metadata.openclaw.install` на хості Gateway.
|
||||
- Operator можуть викликати `skills.update` (`operator.admin`) у двох режимах:
|
||||
- Режим ClawHub оновлює один відстежуваний slug або всі відстежувані встановлення ClawHub у
|
||||
робочому просторі агента за замовчуванням.
|
||||
- Режим Config вносить зміни до значень `skills.entries.<skillKey>`, таких як `enabled`,
|
||||
`apiKey` і `env`.
|
||||
|
||||
## Approval для exec
|
||||
## Схвалення exec
|
||||
|
||||
- Коли запит exec потребує approval, gateway транслює `exec.approval.requested`.
|
||||
- Клієнти operator вирішують це, викликаючи `exec.approval.resolve` (потрібна область доступу `operator.approvals`).
|
||||
- Для `host=node` `exec.approval.request` має включати `systemRunPlan` (канонічні `argv`/`cwd`/`rawCommand`/метадані сесії). Запити без `systemRunPlan` відхиляються.
|
||||
- Після approval переслані виклики `node.invoke system.run` повторно використовують цей канонічний
|
||||
- Коли запит exec потребує схвалення, Gateway транслює `exec.approval.requested`.
|
||||
- Клієнти operator виконують підтвердження, викликаючи `exec.approval.resolve` (потрібна область видимості `operator.approvals`).
|
||||
- Для `host=node` `exec.approval.request` має містити `systemRunPlan` (канонічні метадані `argv`/`cwd`/`rawCommand`/сесії). Запити без `systemRunPlan` відхиляються.
|
||||
- Після схвалення переслані виклики `node.invoke system.run` повторно використовують цей канонічний
|
||||
`systemRunPlan` як авторитетний контекст команди/cwd/сесії.
|
||||
- Якщо викликач змінює `command`, `rawCommand`, `cwd`, `agentId` або
|
||||
`sessionKey` між prepare і фінальним пересиланням схваленого `system.run`,
|
||||
gateway відхиляє запуск замість того, щоб довіряти зміненому корисному навантаженню.
|
||||
`sessionKey` між prepare і остаточним пересиланням схваленого `system.run`,
|
||||
Gateway відхиляє запуск замість того, щоб довіряти зміненому корисному навантаженню.
|
||||
|
||||
## Резервна доставка агента
|
||||
|
||||
- Запити `agent` можуть включати `deliver=true`, щоб запросити вихідну доставку.
|
||||
- `bestEffortDeliver=false` зберігає сувору поведінку: цілі доставки, які неможливо визначити або які є лише внутрішніми, повертають `INVALID_REQUEST`.
|
||||
- `bestEffortDeliver=true` дозволяє резервний перехід до виконання лише в сесії, коли неможливо визначити зовнішній маршрут доставки (наприклад, внутрішні/webchat сесії або неоднозначні конфігурації багатьох каналів).
|
||||
- Запити `agent` можуть містити `deliver=true`, щоб запросити вихідну доставку.
|
||||
- `bestEffortDeliver=false` зберігає сувору поведінку: нерозв’язані або лише внутрішні цілі доставки повертають `INVALID_REQUEST`.
|
||||
- `bestEffortDeliver=true` дозволяє резервне виконання лише в межах сесії, коли неможливо розв’язати зовнішній маршрут доставки (наприклад, для внутрішніх/webchat сесій або неоднозначних багатоканальних конфігурацій).
|
||||
|
||||
## Версіонування
|
||||
|
||||
- `PROTOCOL_VERSION` міститься в `src/gateway/protocol/schema/protocol-schemas.ts`.
|
||||
- `PROTOCOL_VERSION` розташовано в `src/gateway/protocol/schema/protocol-schemas.ts`.
|
||||
- Клієнти надсилають `minProtocol` + `maxProtocol`; сервер відхиляє невідповідності.
|
||||
- Схеми + моделі генеруються з визначень TypeBox:
|
||||
- `pnpm protocol:gen`
|
||||
@ -546,22 +556,22 @@ Gateway розглядає їх як **заяви** і застосовує сп
|
||||
|
||||
### Константи клієнта
|
||||
|
||||
Еталонний клієнт у `src/gateway/client.ts` використовує ці значення за замовчуванням. Значення
|
||||
стабільні в межах протоколу v3 і є очікуваною базовою лінією для сторонніх клієнтів.
|
||||
Еталонний клієнт у `src/gateway/client.ts` використовує ці значення за замовчуванням. Вони
|
||||
стабільні впродовж protocol v3 і є очікуваною базою для сторонніх клієнтів.
|
||||
|
||||
| Constant | Default | Source |
|
||||
| ----------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------- |
|
||||
| `PROTOCOL_VERSION` | `3` | `src/gateway/protocol/schema/protocol-schemas.ts` |
|
||||
| Тайм-аут запиту (на один RPC) | `30_000` ms | `src/gateway/client.ts` (`requestTimeoutMs`) |
|
||||
| Тайм-аут preauth / connect-challenge | `10_000` ms | `src/gateway/handshake-timeouts.ts` (clamp `250`–`10_000`) |
|
||||
| Початковий backoff повторного підключення | `1_000` ms | `src/gateway/client.ts` (`backoffMs`) |
|
||||
| Максимальний backoff повторного підключення | `30_000` ms | `src/gateway/client.ts` (`scheduleReconnect`) |
|
||||
| Обмеження швидкого повтору після закриття токена пристрою | `250` ms | `src/gateway/client.ts` |
|
||||
| Пільговий період force-stop перед `terminate()` | `250` ms | `FORCE_STOP_TERMINATE_GRACE_MS` |
|
||||
| Тайм-аут за замовчуванням для `stopAndWait()` | `1_000` ms | `STOP_AND_WAIT_TIMEOUT_MS` |
|
||||
| Стандартний інтервал tick (до `hello-ok`) | `30_000` ms | `src/gateway/client.ts` |
|
||||
| Закриття через тайм-аут tick | код `4000`, коли тиша перевищує `tickIntervalMs * 2` | `src/gateway/client.ts` |
|
||||
| `MAX_PAYLOAD_BYTES` | `25 * 1024 * 1024` (25 MB) | `src/gateway/server-constants.ts` |
|
||||
| Константа | Значення за замовчуванням | Джерело |
|
||||
| ------------------------------------------ | ----------------------------------------------------- | ---------------------------------------------------------- |
|
||||
| `PROTOCOL_VERSION` | `3` | `src/gateway/protocol/schema/protocol-schemas.ts` |
|
||||
| Тайм-аут запиту (на RPC) | `30_000` ms | `src/gateway/client.ts` (`requestTimeoutMs`) |
|
||||
| Тайм-аут preauth / connect-challenge | `10_000` ms | `src/gateway/handshake-timeouts.ts` (clamp `250`–`10_000`) |
|
||||
| Початковий backoff повторного підключення | `1_000` ms | `src/gateway/client.ts` (`backoffMs`) |
|
||||
| Максимальний backoff повторного підключення| `30_000` ms | `src/gateway/client.ts` (`scheduleReconnect`) |
|
||||
| Fast-retry clamp після закриття device-token | `250` ms | `src/gateway/client.ts` |
|
||||
| Пауза примусової зупинки перед `terminate()` | `250` ms | `FORCE_STOP_TERMINATE_GRACE_MS` |
|
||||
| Тайм-аут `stopAndWait()` за замовчуванням | `1_000` ms | `STOP_AND_WAIT_TIMEOUT_MS` |
|
||||
| Інтервал tick за замовчуванням (до `hello-ok`) | `30_000` ms | `src/gateway/client.ts` |
|
||||
| Закриття через тайм-аут tick | код `4000`, коли тиша перевищує `tickIntervalMs * 2` | `src/gateway/client.ts` |
|
||||
| `MAX_PAYLOAD_BYTES` | `25 * 1024 * 1024` (25 MB) | `src/gateway/server-constants.ts` |
|
||||
|
||||
Сервер оголошує фактичні `policy.tickIntervalMs`, `policy.maxPayload`
|
||||
і `policy.maxBufferedBytes` у `hello-ok`; клієнти повинні дотримуватися цих значень,
|
||||
@ -569,110 +579,110 @@ Gateway розглядає їх як **заяви** і застосовує сп
|
||||
|
||||
## Автентифікація
|
||||
|
||||
- Автентифікація gateway зі спільним секретом використовує `connect.params.auth.token` або
|
||||
`connect.params.auth.password` залежно від налаштованого режиму автентифікації.
|
||||
- Автентифікація Gateway за спільним секретом використовує `connect.params.auth.token` або
|
||||
`connect.params.auth.password`, залежно від налаштованого режиму автентифікації.
|
||||
- Режими з ідентичністю, такі як Tailscale Serve
|
||||
(`gateway.auth.allowTailscale: true`) або не-loopback
|
||||
`gateway.auth.mode: "trusted-proxy"`, проходять перевірку автентифікації connect на основі
|
||||
заголовків запиту замість `connect.params.auth.*`.
|
||||
- Приватний ingress `gateway.auth.mode: "none"` повністю пропускає автентифікацію connect зі спільним секретом; не відкривайте цей режим для публічного або недовіреного ingress.
|
||||
- Після pairing Gateway видає **токен пристрою** з областю дії, обмеженою роллю + областями доступу
|
||||
підключення. Він повертається в `hello-ok.auth.deviceToken`, і клієнт повинен
|
||||
зберігати його для майбутніх підключень.
|
||||
заголовків запиту, а не `connect.params.auth.*`.
|
||||
- Для private-ingress `gateway.auth.mode: "none"` повністю пропускає автентифікацію connect за спільним секретом; не відкривайте цей режим у публічному/недовіреному ingress.
|
||||
- Після pairing Gateway видає **токен пристрою** з областю дії, обмеженою роллю + областями видимості
|
||||
з’єднання. Він повертається в `hello-ok.auth.deviceToken` і має
|
||||
зберігатися клієнтом для наступних підключень.
|
||||
- Клієнти повинні зберігати основний `hello-ok.auth.deviceToken` після будь-якого
|
||||
успішного підключення.
|
||||
- Повторне підключення з цим **збереженим** токеном пристрою також має повторно використовувати
|
||||
збережений набір схвалених областей доступу для цього токена. Це зберігає доступ до
|
||||
читання/перевірки/статусу, який уже було надано, і запобігає непомітному звуженню
|
||||
повторних підключень до вужчої неявної області доступу лише для адміністрування.
|
||||
- Побудова auth для connect на боці клієнта (`selectConnectAuth` у
|
||||
збережений набір схвалених областей видимості для цього токена. Це зберігає вже наданий доступ
|
||||
до читання/перевірок/стану й уникає непомітного звуження повторних підключень до
|
||||
вужчої неявної області лише для admin.
|
||||
- Формування client-side connect auth (`selectConnectAuth` у
|
||||
`src/gateway/client.ts`):
|
||||
- `auth.password` є незалежним і завжди пересилається, якщо встановлено.
|
||||
- `auth.password` ортогональний і завжди пересилається, якщо встановлений.
|
||||
- `auth.token` заповнюється в такому порядку пріоритету: спочатку явний спільний токен,
|
||||
потім явний `deviceToken`, далі збережений токен для конкретного пристрою (з ключем за
|
||||
потім явний `deviceToken`, потім збережений токен для конкретного пристрою (з ключем за
|
||||
`deviceId` + `role`).
|
||||
- `auth.bootstrapToken` надсилається лише тоді, коли жоден із наведених вище варіантів не визначив
|
||||
`auth.token`. Спільний токен або будь-який визначений токен пристрою його пригнічує.
|
||||
- `auth.bootstrapToken` надсилається лише тоді, коли жоден із наведених вище варіантів не розв’язав
|
||||
`auth.token`. Спільний токен або будь-який розв’язаний токен пристрою його пригнічує.
|
||||
- Автопідвищення збереженого токена пристрою під час одноразової
|
||||
повторної спроби `AUTH_TOKEN_MISMATCH` обмежене **лише довіреними кінцевими точками** —
|
||||
спроби повтору `AUTH_TOKEN_MISMATCH` обмежене лише **довіреними кінцевими точками** —
|
||||
loopback або `wss://` із закріпленим `tlsFingerprint`. Публічний `wss://`
|
||||
без pinning не підходить.
|
||||
- Додаткові записи `hello-ok.auth.deviceTokens` — це токени передачі bootstrap.
|
||||
Зберігайте їх лише тоді, коли підключення використовувало bootstrap-auth через довірений транспорт,
|
||||
такий як `wss://` або loopback/local pairing.
|
||||
Зберігайте їх лише тоді, коли підключення використовувало bootstrap auth у довіреному транспорті,
|
||||
такому як `wss://` або loopback/local pairing.
|
||||
- Якщо клієнт надає **явний** `deviceToken` або явні `scopes`, цей
|
||||
набір областей доступу, запитаний викликачем, залишається авторитетним; кешовані області доступу
|
||||
набір областей видимості, запитаний викликачем, лишається авторитетним; кешовані області видимості
|
||||
повторно використовуються лише тоді, коли клієнт повторно використовує збережений токен для конкретного пристрою.
|
||||
- Токени пристроїв можна ротувати/відкликати через `device.token.rotate` і
|
||||
`device.token.revoke` (потрібна область доступу `operator.pairing`).
|
||||
- Видача/ротація токенів залишається обмеженою схваленим набором ролей, записаним у
|
||||
записі pairing цього пристрою; ротація токена не може розширити пристрій до
|
||||
ролі, яку схвалення pairing ніколи не надавало.
|
||||
- Для сесій токенів спарених пристроїв керування пристроями має власну область дії, якщо лише
|
||||
викликач також не має `operator.admin`: викликачі без адміністраторських прав можуть видаляти/відкликати/ротувати
|
||||
- Токени пристроїв можна обертати/відкликати через `device.token.rotate` і
|
||||
`device.token.revoke` (потрібна область видимості `operator.pairing`).
|
||||
- Видача/обертання токенів лишається обмеженою схваленим набором ролей, записаним у
|
||||
записі pairing цього пристрою; обертання токена не може розширити пристрій до
|
||||
ролі, яку ніколи не надав дозвіл pairing.
|
||||
- Для сесій з токеном спареного пристрою керування пристроєм має власну область дії, якщо тільки
|
||||
викликач також не має `operator.admin`: викликачі без admin можуть видаляти/відкликати/обертати
|
||||
лише **власний** запис пристрою.
|
||||
- `device.token.rotate` також перевіряє запитаний набір областей доступу оператора щодо
|
||||
поточних областей доступу сесії викликача. Викликачі без адміністраторських прав не можуть ротувати токен у
|
||||
ширший набір областей доступу оператора, ніж той, який вони вже мають.
|
||||
- Збої автентифікації включають `error.details.code` плюс підказки щодо відновлення:
|
||||
- `error.details.canRetryWithDeviceToken` (boolean)
|
||||
- `device.token.rotate` також перевіряє запитаний набір областей видимості operator щодо
|
||||
поточних областей видимості сесії викликача. Викликачі без admin не можуть обертати токен до
|
||||
ширшого набору областей видимості operator, ніж вони вже мають.
|
||||
- Збої автентифікації містять `error.details.code` плюс підказки щодо відновлення:
|
||||
- `error.details.canRetryWithDeviceToken` (булеве значення)
|
||||
- `error.details.recommendedNextStep` (`retry_with_device_token`, `update_auth_configuration`, `update_auth_credentials`, `wait_then_retry`, `review_auth_configuration`)
|
||||
- Поведінка клієнта для `AUTH_TOKEN_MISMATCH`:
|
||||
- Довірені клієнти можуть зробити одну обмежену повторну спробу з кешованим токеном для конкретного пристрою.
|
||||
- Якщо ця повторна спроба не вдається, клієнти повинні припинити цикли автоматичного повторного підключення і показати вказівки для дій оператора.
|
||||
- Довірені клієнти можуть виконати одну обмежену повторну спробу із кешованим токеном для конкретного пристрою.
|
||||
- Якщо ця повторна спроба не вдається, клієнти повинні зупинити цикли автоматичного повторного підключення та показати вказівки для дій operator.
|
||||
|
||||
## Ідентичність пристрою + pairing
|
||||
|
||||
- Вузли повинні включати стабільну ідентичність пристрою (`device.id`), похідну від
|
||||
відбитка keypair.
|
||||
- Node повинні містити стабільну ідентичність пристрою (`device.id`), похідну від
|
||||
відбитка ключової пари.
|
||||
- Gateway видає токени для кожного пристрою + ролі.
|
||||
- Для нових `device.id` потрібні схвалення pairing, якщо не ввімкнено локальне автоматичне схвалення.
|
||||
- Автоматичне схвалення pairing зосереджене на прямих локальних loopback-підключеннях.
|
||||
- OpenClaw також має вузький шлях backend/container-local self-connect для
|
||||
- OpenClaw також має вузький шлях самопідключення backend/container-local для
|
||||
довірених допоміжних потоків зі спільним секретом.
|
||||
- Підключення tailnet або LAN з того самого хоста все одно вважаються віддаленими для pairing і
|
||||
- Підключення tailnet або LAN на тому самому хості все одно вважаються віддаленими для pairing і
|
||||
потребують схвалення.
|
||||
- Усі WS-клієнти повинні включати ідентичність `device` під час `connect` (operator + node).
|
||||
- Усі WS-клієнти мають включати ідентичність `device` під час `connect` (operator + node).
|
||||
Control UI може пропускати її лише в таких режимах:
|
||||
- `gateway.controlUi.allowInsecureAuth=true` для сумісності з небезпечним HTTP лише на localhost.
|
||||
- успішна автентифікація operator Control UI через `gateway.auth.mode: "trusted-proxy"`.
|
||||
- `gateway.controlUi.dangerouslyDisableDeviceAuth=true` (аварійний варіант, критичне зниження безпеки).
|
||||
- Усі підключення повинні підписувати наданий сервером nonce `connect.challenge`.
|
||||
- `gateway.controlUi.dangerouslyDisableDeviceAuth=true` (аварійний режим, серйозне зниження безпеки).
|
||||
- Усі з’єднання мають підписувати nonce `connect.challenge`, наданий сервером.
|
||||
|
||||
### Діагностика міграції автентифікації пристрою
|
||||
|
||||
Для застарілих клієнтів, які досі використовують поведінку підпису до challenge, `connect` тепер повертає
|
||||
Для застарілих клієнтів, які все ще використовують поведінку підписування до challenge, `connect` тепер повертає
|
||||
коди деталей `DEVICE_AUTH_*` у `error.details.code` зі стабільним `error.details.reason`.
|
||||
|
||||
Поширені збої міграції:
|
||||
|
||||
| Message | details.code | details.reason | Meaning |
|
||||
| --------------------------- | -------------------------------- | ------------------------ | -------------------------------------------------- |
|
||||
| `device nonce required` | `DEVICE_AUTH_NONCE_REQUIRED` | `device-nonce-missing` | Клієнт пропустив `device.nonce` (або надіслав порожнє значення). |
|
||||
| `device nonce mismatch` | `DEVICE_AUTH_NONCE_MISMATCH` | `device-nonce-mismatch` | Клієнт підписав застарілим/неправильним nonce. |
|
||||
| `device signature invalid` | `DEVICE_AUTH_SIGNATURE_INVALID` | `device-signature` | Корисне навантаження підпису не відповідає корисному навантаженню v2. |
|
||||
| `device signature expired` | `DEVICE_AUTH_SIGNATURE_EXPIRED` | `device-signature-stale` | Підписана позначка часу поза межами дозволеного зсуву. |
|
||||
| `device identity mismatch` | `DEVICE_AUTH_DEVICE_ID_MISMATCH` | `device-id-mismatch` | `device.id` не відповідає відбитку публічного ключа. |
|
||||
| `device public key invalid` | `DEVICE_AUTH_PUBLIC_KEY_INVALID` | `device-public-key` | Формат публічного ключа/канонізація не пройшли перевірку. |
|
||||
| Повідомлення | details.code | details.reason | Значення |
|
||||
| ---------------------------- | -------------------------------- | ------------------------ | --------------------------------------------------- |
|
||||
| `device nonce required` | `DEVICE_AUTH_NONCE_REQUIRED` | `device-nonce-missing` | Клієнт пропустив `device.nonce` (або надіслав порожнє значення). |
|
||||
| `device nonce mismatch` | `DEVICE_AUTH_NONCE_MISMATCH` | `device-nonce-mismatch` | Клієнт підписав застарілим/неправильним nonce. |
|
||||
| `device signature invalid` | `DEVICE_AUTH_SIGNATURE_INVALID` | `device-signature` | Корисне навантаження підпису не відповідає корисному навантаженню v2. |
|
||||
| `device signature expired` | `DEVICE_AUTH_SIGNATURE_EXPIRED` | `device-signature-stale` | Часова мітка підпису поза межами дозволеного зсуву. |
|
||||
| `device identity mismatch` | `DEVICE_AUTH_DEVICE_ID_MISMATCH` | `device-id-mismatch` | `device.id` не відповідає відбитку публічного ключа. |
|
||||
| `device public key invalid` | `DEVICE_AUTH_PUBLIC_KEY_INVALID` | `device-public-key` | Збій формату/канонізації публічного ключа. |
|
||||
|
||||
Ціль міграції:
|
||||
|
||||
- Завжди чекайте на `connect.challenge`.
|
||||
- Підписуйте корисне навантаження v2, яке включає server nonce.
|
||||
- Завжди очікуйте `connect.challenge`.
|
||||
- Підписуйте корисне навантаження v2, яке містить серверний nonce.
|
||||
- Надсилайте той самий nonce у `connect.params.device.nonce`.
|
||||
- Бажане корисне навантаження підпису — `v3`, яке прив’язує `platform` і `deviceFamily`
|
||||
на додачу до полів device/client/role/scopes/token/nonce.
|
||||
- Застарілі підписи `v2` і далі приймаються для сумісності, але закріплення
|
||||
метаданих спарених пристроїв усе одно керує політикою команд під час повторного підключення.
|
||||
- Застарілі підписи `v2` і далі приймаються для сумісності, але pinning метаданих
|
||||
спареного пристрою все одно керує політикою команд під час повторного підключення.
|
||||
|
||||
## TLS + pinning
|
||||
|
||||
- TLS підтримується для WS-підключень.
|
||||
- Клієнти можуть за бажанням закріплювати відбиток сертифіката gateway (див. конфігурацію `gateway.tls`
|
||||
- Для WS-з’єднань підтримується TLS.
|
||||
- Клієнти можуть за бажанням закріпити відбиток сертифіката Gateway (див. конфігурацію `gateway.tls`
|
||||
плюс `gateway.remote.tlsFingerprint` або CLI `--tls-fingerprint`).
|
||||
|
||||
## Область дії
|
||||
|
||||
Цей протокол відкриває **повний API gateway** (status, channels, models, chat,
|
||||
agent, sessions, nodes, approvals тощо). Точна поверхня визначається
|
||||
схемами TypeBox у `src/gateway/protocol/schema.ts`.
|
||||
Цей протокол відкриває **повний API Gateway** (status, channels, models, chat,
|
||||
agent, sessions, nodes, approvals тощо). Точна поверхня визначається схемами
|
||||
TypeBox у `src/gateway/protocol/schema.ts`.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user