Gateway
Протокол мосту
Навіщо він існував
- Межа безпеки: надавав доступ до невеликого списку дозволених операцій замість усієї поверхні API Gateway.
- Сполучення та ідентичність вузла: допуском вузлів керував Gateway, і він був прив’язаний до окремого токена кожного вузла.
- Зручність виявлення: вузли могли виявляти Gateway через Bonjour у локальній мережі або підключатися безпосередньо через tailnet.
- Локальний WS: повна площина керування WS залишалася локальною, якщо її не тунелювали через SSH.
Транспорт
- TCP, один об’єкт JSON у кожному рядку (JSONL).
- Необов’язковий TLS (
bridge.tls.enabled: true). - Стандартним портом прослуховувача був
18790.
Коли TLS було ввімкнено, TXT-записи виявлення містили bridgeTls=1, а також bridgeTlsSha256 як несекретну підказку. TXT-записи Bonjour/mDNS не автентифікуються; клієнти не могли вважати оголошений відбиток достовірно закріпленим без іншої перевірки через незалежний канал.
Рукостискання та сполучення
- Клієнт надсилає
helloз метаданими вузла та токеном (якщо сполучення вже виконано). - Якщо сполучення не виконано, Gateway відповідає
error(NOT_PAIRED/UNAUTHORIZED). - Клієнт надсилає
pair-request. - Gateway очікує схвалення, а потім надсилає
pair-okіhello-ok.
Раніше hello-ok повертав serverName; тепер поверхні розміщених Plugin оголошуються через pluginSurfaceUrls у поточному протоколі Gateway (Canvas/A2UI використовує pluginSurfaceUrls.canvas).
Кадри
Від клієнта до Gateway:
req/res: RPC Gateway з обмеженою областю дії (чат, сеанси, конфігурація, стан, активація голосом, skills.bins).event: сигнали вузла (транскрипція голосу, запит агента, підписка на чат, життєвий цикл виконання).
Від Gateway до клієнта:
invoke/invoke-res: команди вузла (canvas.*,camera.*,screen.record,location.get,sms.send).event: оновлення чату для сеансів із підпискою.ping/pong: підтримання з’єднання.
Перевірка списку дозволених операцій була реалізована в src/gateway/server-bridge.ts (видалено).
Події життєвого циклу виконання
Вузли надсилали exec.finished, щоб повідомляти про завершену активність system.run, яку Gateway зіставляв із системними подіями (застарілі вузли також могли надсилати exec.started). exec.denied позначав відхилену спробу system.run як остаточну відмову без додавання системної події до черги чи активації роботи агента.
Поля корисного навантаження (усі необов’язкові, якщо не зазначено інше):
| Поле | Примітки |
|---|---|
sessionKey |
Обов’язкове. Сеанс агента для кореляції подій і, для exec.finished, доставлення системної події. |
runId |
Унікальний ідентифікатор виконання для групування. |
command |
Необроблений або відформатований рядок команди. |
exitCode, timedOut, output |
Відомості про завершення (лише для завершеного виконання). |
reason |
Причина відмови (лише для відхиленого виконання). |
Історичне використання tailnet
- Прив’язка мосту до IP-адреси tailnet:
bridge.bind: "tailnet"у~/.openclaw/openclaw.json(лише історична довідка;bridge.*більше не є чинною конфігурацією). - Клієнти підключалися за іменем MagicDNS або IP-адресою tailnet.
- Bonjour не працює між мережами; в іншому разі був потрібен глобальний DNS-SD або задані вручну хост і порт.
Керування версіями
Міст неявно використовував версію v1 без узгодження мінімальної та максимальної версій. Поточні клієнти вузлів і операторів використовують WebSocket-протокол Gateway, який узгоджує діапазон версій протоколу.