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; теперь размещённые поверхности плагинов объявляются через 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, в котором согласовывается диапазон версий протокола.