mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 11:25:50 -06:00
148 lines
6.4 KiB
Markdown
148 lines
6.4 KiB
Markdown
# `@openclaw/gateway-client`
|
|
|
|
Reference WebSocket client for the OpenClaw Gateway protocol. It provides the
|
|
connection state machine used by OpenClaw's own Node and browser clients:
|
|
challenge-based authentication, typed protocol frames, request correlation,
|
|
timeouts, reconnect backoff, device-token handling, and event delivery.
|
|
|
|
The current wire protocol is version 4. General clients must advertise exactly v4 with
|
|
`minProtocol: 4` and `maxProtocol: 4`. See the
|
|
[Gateway protocol specification](https://docs.openclaw.ai/gateway/protocol) for
|
|
the complete handshake, authentication, role, scope, and method contracts.
|
|
Exact node identities (`role: "node"` plus `mode: "node"`) and probe clients
|
|
can use v3. The built-in node host starts with an exact v4 envelope, then retries
|
|
an exact v3 envelope after a v3 Gateway rejects v4. If that legacy probe reaches
|
|
an upgraded v4 Gateway, the client reconnects with the full v4 envelope before
|
|
reporting readiness. Other exact node identities default to `[3, 4]`. Explicit
|
|
bounds override these defaults; `[3, 4]` on the built-in node host selects the
|
|
same bounded negotiation.
|
|
|
|
## Versioning
|
|
|
|
Package versions follow the OpenClaw calendar release train: `YYYY.M.PATCH`,
|
|
including the OpenClaw prerelease suffix when applicable. The package version is
|
|
separate from the Gateway's current wire protocol number reported in `hello-ok`.
|
|
|
|
## Install
|
|
|
|
```bash
|
|
npm install @openclaw/gateway-client @openclaw/gateway-protocol
|
|
```
|
|
|
|
Node consumers use the `ws` transport included as a runtime dependency. Browser
|
|
consumers provide their platform WebSocket through the browser-safe protocol
|
|
client surface.
|
|
|
|
## Entry points
|
|
|
|
- `@openclaw/gateway-client` exports the Node `GatewayClient`, device-auth
|
|
helpers, readiness helpers, and timeout utilities.
|
|
- `@openclaw/gateway-client/browser` exports the browser-safe protocol client,
|
|
browser device-auth lifecycle, reconnect policy, and lightweight protocol
|
|
constants. Its module graph does not import Node built-ins or `ws`.
|
|
- `@openclaw/gateway-client/readiness` exports helpers that delay client startup
|
|
until the event loop can process Gateway IO.
|
|
- `@openclaw/gateway-client/timeouts` exports timeout constants and safe timer
|
|
resolution helpers.
|
|
- `@openclaw/gateway-client/websocket-data` converts every Node `ws` raw-data
|
|
shape to UTF-8 text.
|
|
|
|
## Node quickstart
|
|
|
|
```ts
|
|
import { GatewayClient } from "@openclaw/gateway-client";
|
|
import { PROTOCOL_VERSION } from "@openclaw/gateway-protocol/version";
|
|
|
|
const connected = Promise.withResolvers<void>();
|
|
const client = new GatewayClient({
|
|
url: "ws://127.0.0.1:18789",
|
|
token: process.env.OPENCLAW_GATEWAY_TOKEN,
|
|
minProtocol: PROTOCOL_VERSION, // v4
|
|
maxProtocol: PROTOCOL_VERSION, // v4
|
|
onHelloOk: () => connected.resolve(),
|
|
onConnectError: (error) => connected.reject(error),
|
|
onEvent: (event) => {
|
|
console.log(event.event, event.payload);
|
|
},
|
|
});
|
|
|
|
client.start();
|
|
await connected.promise;
|
|
|
|
const status = await client.request("status", {});
|
|
console.log(status);
|
|
|
|
client.stop();
|
|
```
|
|
|
|
The client waits for the Gateway's `connect.challenge` event before sending its
|
|
`connect` request. It includes the challenge nonce in device authentication and
|
|
does not fall back to a pre-challenge handshake. `onHelloOk` fires only after the
|
|
Gateway accepts a compatible connection, so requests should wait for that callback.
|
|
|
|
For remote connections, use `wss://`. Plaintext `ws://` is allowed by default
|
|
only for loopback addresses. Authentication material and Gateway traffic must
|
|
not cross an untrusted network without transport security.
|
|
|
|
## Browser clients
|
|
|
|
Import `@openclaw/gateway-client/browser` when the host owns the WebSocket
|
|
adapter and device-key storage. The browser entry includes
|
|
`GatewayProtocolClient` and `GatewayBrowserDeviceAuthLifecycle`; it deliberately
|
|
omits the Node transport, TLS fingerprint handling, and private-network address
|
|
policy.
|
|
|
|
The host is responsible for:
|
|
|
|
- creating a `GatewayProtocolSocket` adapter around the browser WebSocket;
|
|
- loading and storing browser device identity and issued device tokens;
|
|
- signing the challenge-bound device payload;
|
|
- using the Gateway challenge `ts` as the device proof's `signedAt` value;
|
|
- supplying the client identity, role, scopes, and authentication selection;
|
|
- choosing close and reconnect behavior for product-specific errors.
|
|
|
|
The shared protocol client still owns frame parsing, request correlation,
|
|
challenge ordering, timeout cleanup, sequence-gap detection, and reconnect
|
|
scheduling.
|
|
|
|
## Defaults and reconnect behavior
|
|
|
|
The Node client starts with a 30 second request timeout, a 15 second
|
|
connect-challenge timeout, and exponential reconnect delays from 1 second to 30
|
|
seconds with a multiplier of 2. Server-provided startup retry hints may override
|
|
the next delay.
|
|
|
|
The canonical defaults table and the server policy fields that can replace
|
|
pre-handshake values are documented in the
|
|
[Gateway protocol specification](https://docs.openclaw.ai/gateway/protocol#client-constants).
|
|
|
|
Use the `./timeouts` entry point when a host must align readiness or watchdog
|
|
budgets with these defaults. Use the `./readiness` entry point when startup must
|
|
wait for an event-loop probe before opening the socket.
|
|
|
|
## Bundled internals
|
|
|
|
The retry supervisor and the small `@openclaw/net-policy/ip` implementation are
|
|
inlined into the published JavaScript and declarations. They are implementation
|
|
details, not public exports or supported API surfaces. `ipaddr.js` remains an
|
|
external dependency because the inlined IP helpers use its public runtime and
|
|
types.
|
|
|
|
`ws`, `@openclaw/gateway-protocol`, and `ipaddr.js` remain external in the
|
|
published distribution. Consumers should import protocol types and constants
|
|
from `@openclaw/gateway-protocol`, not from bundled implementation paths.
|
|
|
|
## Contract notes
|
|
|
|
- The client is inert at module import and construction time. `start()` opens
|
|
the socket; `stop()` closes it and rejects pending requests.
|
|
- A request uses `request(method, params)` after `hello-ok`. Passing
|
|
`timeoutMs: null` creates an intentionally unbounded request.
|
|
- Finite request deadlines reject with `GatewayProtocolRequestTimeoutError`,
|
|
whose `CLIENT_TIMEOUT` code, method, deadline, and send-boundary flag remain
|
|
distinct from authoritative Gateway response errors.
|
|
- Device identity persistence, signing, proxy routing, TLS formatting, and
|
|
logging stay host-owned through `GatewayClientHostDeps`.
|
|
- Protocol changes are additive first. Incompatible changes require an explicit
|
|
wire-version decision and coordinated server/client follow-through.
|