openclaw-client 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,34 +14,139 @@ yarn add openclaw-client
14
14
 
15
15
  ## Quick Start
16
16
 
17
+ Connect to a local OpenClaw instance:
18
+
17
19
  ```typescript
18
20
  import { OpenClawClient } from 'openclaw-client';
19
21
 
20
22
  const client = new OpenClawClient({
21
23
  gatewayUrl: 'ws://localhost:18789',
22
24
  token: 'your-token',
23
- clientId: 'gateway-client',
24
- mode: 'ui',
25
25
  });
26
26
 
27
- await client.connect();
27
+ const result = await client.connect();
28
+ console.log('Connected:', result.server.connId);
29
+
28
30
  const sessions = await client.listSessions();
31
+ client.disconnect();
32
+ ```
33
+
34
+ ## Device Identity
35
+
36
+ Built-in Ed25519 device signing — no manual crypto required. Provide a `DeviceIdentityStore` (and optionally a `DeviceTokenStore`) and the library handles keypair generation, persistence, v2 payload signing, and device token management.
37
+
38
+ > **Requires Node.js 20+** or Chrome 113+ / Safari 17+ / Firefox 130+ (Ed25519 via Web Crypto API). The library itself still works on Node 18+ when device identity is not used.
39
+
40
+ ### Browser Example
41
+
42
+ ```typescript
43
+ import { OpenClawClient } from 'openclaw-client';
44
+ import type { DeviceIdentityRecord, DeviceIdentityStore, DeviceTokenStore } from 'openclaw-client';
45
+
46
+ const identityStore: DeviceIdentityStore = {
47
+ async load() {
48
+ const raw = localStorage.getItem('oc-device-identity');
49
+ return raw ? JSON.parse(raw) : null;
50
+ },
51
+ async save(record: DeviceIdentityRecord) {
52
+ localStorage.setItem('oc-device-identity', JSON.stringify(record));
53
+ },
54
+ };
55
+
56
+ const tokenStore: DeviceTokenStore = {
57
+ async load() {
58
+ return localStorage.getItem('oc-device-token');
59
+ },
60
+ async save(token: string) {
61
+ localStorage.setItem('oc-device-token', token);
62
+ },
63
+ };
64
+
65
+ const client = new OpenClawClient({
66
+ gatewayUrl: 'wss://gateway.example.com',
67
+ token: 'initial-pairing-token',
68
+ deviceIdentity: identityStore,
69
+ deviceToken: tokenStore,
70
+ onPairingRequired: (required) => {
71
+ if (required) console.log('Approve this device on the gateway...');
72
+ else console.log('Device paired!');
73
+ },
74
+ });
75
+
76
+ await client.connect();
77
+ ```
78
+
79
+ ### Node.js Example
80
+
81
+ ```typescript
82
+ import { readFile, writeFile } from 'fs/promises';
83
+ import { OpenClawClient } from 'openclaw-client';
84
+ import type { DeviceIdentityStore, DeviceTokenStore } from 'openclaw-client';
85
+
86
+ const identityStore: DeviceIdentityStore = {
87
+ async load() {
88
+ try { return JSON.parse(await readFile('.oc-identity.json', 'utf8')); }
89
+ catch { return null; }
90
+ },
91
+ async save(record) {
92
+ await writeFile('.oc-identity.json', JSON.stringify(record));
93
+ },
94
+ };
95
+
96
+ const tokenStore: DeviceTokenStore = {
97
+ async load() {
98
+ try { return await readFile('.oc-token', 'utf8'); }
99
+ catch { return null; }
100
+ },
101
+ async save(token) {
102
+ await writeFile('.oc-token', token);
103
+ },
104
+ };
105
+
106
+ const client = new OpenClawClient({
107
+ gatewayUrl: 'ws://localhost:18789',
108
+ token: 'your-token',
109
+ deviceIdentity: identityStore,
110
+ deviceToken: tokenStore,
111
+ });
112
+
113
+ await client.connect();
29
114
  ```
30
115
 
31
- ## Features
116
+ ### Interaction with `connectParams`
32
117
 
33
- - **Type-safe** - Auto-generated TypeScript types from OpenClaw protocol schema
34
- - ✅ **Lightweight** - Minimal dependencies, works in Node.js 18+ and browsers
35
- - **Event handling** - Listen to real-time events from the Gateway
36
- - **Server-friendly** - Includes utilities for server-side usage (Next.js, etc.)
118
+ | `deviceIdentity` | `connectParams` | Behavior |
119
+ |---|---|---|
120
+ | set | static object | Both work device from manager, other fields (e.g. `caps`) merged from static object |
121
+ | set | function | `deviceIdentity` takes precedence function is **not** called |
122
+ | not set | function | Existing behavior — function receives challenge, returns params |
123
+ | not set | static/absent | Simple merge, no device logic |
37
124
 
38
- ## API
125
+ ## Auto-Reconnection
39
126
 
40
- ### `OpenClawClient`
127
+ Opt-in exponential backoff reconnection:
41
128
 
42
- Main WebSocket client for OpenClaw Gateway.
129
+ ```typescript
130
+ const client = new OpenClawClient({
131
+ gatewayUrl: 'wss://gateway.example.com',
132
+ token: 'your-token',
133
+ reconnect: {
134
+ enabled: true,
135
+ baseDelay: 1000, // default 1s
136
+ maxDelay: 30000, // default 30s
137
+ maxAttempts: 20, // default Infinity
138
+ },
139
+ onConnection: (connected) => {
140
+ console.log(connected ? 'Connected' : 'Disconnected');
141
+ },
142
+ });
43
143
 
44
- #### Configuration
144
+ await client.connect();
145
+ // If connection drops, client will automatically reconnect
146
+ // Calling client.disconnect() stops reconnection
147
+ ```
148
+
149
+ ## Configuration Reference
45
150
 
46
151
  ```typescript
47
152
  interface OpenClawClientConfig {
@@ -51,139 +156,171 @@ interface OpenClawClientConfig {
51
156
  clientVersion?: string; // Client version (default: '1.0.0')
52
157
  platform?: string; // Platform name (default: 'web')
53
158
  mode?: string; // Client mode (default: 'ui')
54
- connectTimeoutMs?: number; // Timeout for connect handshake (default: 120000)
55
- requestTimeoutMs?: number; // Timeout for RPC requests (default: 30000)
56
- connectParams?: Partial<ConnectParams> // Static object, or...
159
+ connectTimeoutMs?: number; // Handshake timeout in ms (default: 120000)
160
+ requestTimeoutMs?: number; // RPC request timeout in ms (default: 30000)
161
+ connectParams?: Partial<ConnectParams> // Static connect params, or...
57
162
  | ((challenge: { nonce: string; ts: number }) => // ...function receiving challenge
58
163
  Partial<ConnectParams> | Promise<Partial<ConnectParams>>);
164
+ deviceIdentity?: DeviceIdentityStore; // Enable built-in device signing
165
+ deviceToken?: DeviceTokenStore; // Persist device tokens
166
+ reconnect?: ReconnectConfig; // Auto-reconnection settings
167
+ onConnection?: (connected: boolean) => void; // Connection state callback
168
+ onPairingRequired?: (required: boolean) => void; // Device pairing callback
59
169
  }
60
170
  ```
61
171
 
62
- #### Methods
63
-
64
- **Connection Management**
65
- - `connect(): Promise<HelloOk>` - Connect and authenticate
66
- - `disconnect(): void` - Disconnect from Gateway
67
- - `isConnected(): boolean` - Check connection status
68
- - `getConnectionId(): string | null` - Get the current connection ID
69
- - `addEventListener(listener): () => void` - Add event listener
70
-
71
- **Configuration**
72
- - `getConfig(params?): Promise<any>` - Get configuration
73
- - `setConfig(params): Promise<any>` - Update configuration
74
- - `getConfigSchema(params?): Promise<ConfigSchemaResponse>` - Get configuration schema
75
- - `applyConfig(params): Promise<any>` - Apply configuration changes
76
- - `patchConfig(params): Promise<any>` - Patch configuration
77
-
78
- **Sessions**
79
- - `listSessions(params?): Promise<any>` - List sessions
80
- - `deleteSession(params): Promise<any>` - Delete a session
81
- - `previewSessions(params): Promise<any>` - Preview sessions
82
- - `resolveSession(params): Promise<any>` - Resolve session
83
- - `patchSession(params): Promise<any>` - Patch session
84
- - `resetSession(params): Promise<any>` - Reset session
85
- - `compactSession(params): Promise<any>` - Compact session
86
- - `getSessionsUsage(params?): Promise<any>` - Get session usage
87
-
88
- **Agents**
89
- - `listAgents(params?): Promise<AgentsListResult>` - List available agents
90
- - `createAgent(params): Promise<AgentsCreateResult>` - Create agent
91
- - `updateAgent(params): Promise<AgentsUpdateResult>` - Update agent
92
- - `deleteAgent(params): Promise<AgentsDeleteResult>` - Delete agent
93
- - `getAgentIdentity(params?): Promise<AgentIdentityResult>` - Get agent identity
94
- - `sendToAgent(params): Promise<any>` - Send a message to agent
95
- - `waitForAgent(params): Promise<any>` - Wait for agent run to complete
96
-
97
- **Agent Files**
98
- - `getAgentFile(params): Promise<AgentsFilesGetResult>` - Get agent file
99
- - `listAgentFiles(params): Promise<AgentsFilesListResult>` - List agent files
100
- - `setAgentFile(params): Promise<AgentsFilesSetResult>` - Update agent file
101
-
102
- **Models**
103
- - `listModels(params?): Promise<ModelsListResult>` - List available models
104
-
105
- **Messaging**
106
- - `send(params): Promise<any>` - Send a message
107
- - `poll(params): Promise<any>` - Send a poll
108
- - `wake(params): Promise<any>` - Wake the system
109
-
110
- **Chat**
111
- - `getChatHistory(params): Promise<any>` - Get chat history
112
- - `sendChat(params): Promise<any>` - Send chat message
113
- - `abortChat(params): Promise<any>` - Abort chat
114
- - `injectChat(params): Promise<any>` - Inject chat message
115
-
116
- **Wizard**
117
- - `startWizard(params?): Promise<WizardStartResult>` - Start wizard
118
- - `wizardNext(params): Promise<WizardNextResult>` - Wizard next step
119
- - `cancelWizard(params): Promise<any>` - Cancel wizard
120
- - `getWizardStatus(params): Promise<WizardStatusResult>` - Get wizard status
121
-
122
- **Channels & Talk**
123
- - `getChannelsStatus(params?): Promise<ChannelsStatusResult>` - Get channels status
124
- - `logoutChannel(params): Promise<any>` - Logout from channel
125
- - `setTalkMode(params): Promise<any>` - Set talk mode
126
- - `getTalkConfig(params?): Promise<TalkConfigResult>` - Get talk config
127
-
128
- **Authentication**
129
- - `startWebLogin(params?): Promise<any>` - Start web login
130
- - `waitForWebLogin(params?): Promise<any>` - Wait for web login
131
-
132
- **Skills**
133
- - `getSkillsStatus(params?): Promise<any>` - Get skills status
134
- - `getSkillsBins(params?): Promise<SkillsBinsResult>` - Get skills bins
135
- - `installSkill(params): Promise<any>` - Install skill
136
- - `updateSkill(params): Promise<any>` - Update skill
137
-
138
- **Cron Jobs**
139
- - `listCronJobs(params?): Promise<{ jobs: CronJob[] }>` - List cron jobs
140
- - `getCronStatus(params?): Promise<any>` - Get cron status
141
- - `addCronJob(params): Promise<{ job: CronJob }>` - Add cron job
142
- - `updateCronJob(params): Promise<{ job: CronJob }>` - Update cron job
143
- - `removeCronJob(params): Promise<any>` - Remove cron job
144
- - `runCronJob(params): Promise<any>` - Run cron job
145
- - `getCronRuns(params): Promise<{ runs: CronRunLogEntry[] }>` - Get cron job runs
146
-
147
- **Execution Approvals**
148
- - `getExecApprovals(params?): Promise<ExecApprovalsSnapshot>` - Get exec approvals
149
- - `setExecApprovals(params): Promise<ExecApprovalsSnapshot>` - Set exec approvals
150
- - `getNodeExecApprovals(params): Promise<ExecApprovalsSnapshot>` - Get node exec approvals
151
- - `setNodeExecApprovals(params): Promise<ExecApprovalsSnapshot>` - Set node exec approvals
152
- - `requestExecApproval(params): Promise<any>` - Request exec approval
153
- - `resolveExecApproval(params): Promise<any>` - Resolve exec approval
154
-
155
- **Device Pairing**
156
- - `listDevicePairings(params?): Promise<any>` - List device pairing requests
157
- - `approveDevicePairing(params): Promise<any>` - Approve device pairing
158
- - `rejectDevicePairing(params): Promise<any>` - Reject device pairing
159
- - `removeDevicePairing(params): Promise<any>` - Remove paired device
160
- - `rotateDeviceToken(params): Promise<any>` - Rotate device token
161
- - `revokeDeviceToken(params): Promise<any>` - Revoke device token
162
-
163
- **Node Management**
164
- - `requestNodePairing(params): Promise<any>` - Request node pairing
165
- - `listNodePairings(params?): Promise<any>` - List node pairing requests
166
- - `approveNodePairing(params): Promise<any>` - Approve node pairing
167
- - `rejectNodePairing(params): Promise<any>` - Reject node pairing
168
- - `verifyNodePairing(params): Promise<any>` - Verify node pairing
169
- - `renameNode(params): Promise<any>` - Rename node
170
- - `listNodes(params?): Promise<any>` - List nodes
171
- - `describeNode(params): Promise<any>` - Describe node
172
- - `invokeNode(params): Promise<any>` - Invoke node command
173
- - `testPush(params): Promise<PushTestResult>` - Test push notification to node
174
-
175
- **Logs**
176
- - `getLogTail(params?): Promise<LogsTailResult>` - Get log tail
177
-
178
- **Updates**
179
- - `updateRun(params): Promise<any>` - Update and run
180
-
181
- **Generic**
182
- - `call<T>(method, params?): Promise<T>` - Generic RPC method call for any method
183
-
184
- ### `ServerOpenClawClient`
185
-
186
- Server-side client manager for connection lifecycle management.
172
+ ## API Methods
173
+
174
+ ### Connection
175
+
176
+ | Method | Returns | Description |
177
+ |---|---|---|
178
+ | `connect()` | `Promise<HelloOk>` | Connect and authenticate |
179
+ | `disconnect()` | `void` | Disconnect (stops auto-reconnect) |
180
+ | `isConnected()` | `boolean` | Check connection status |
181
+ | `getConnectionId()` | `string \| null` | Current connection ID |
182
+ | `addEventListener(listener)` | `() => void` | Add event listener (returns unsubscribe fn) |
183
+
184
+ ### Configuration
185
+
186
+ | Method | Description |
187
+ |---|---|
188
+ | `getConfig(params?)` | Get configuration |
189
+ | `setConfig(params)` | Set configuration |
190
+ | `getConfigSchema(params?)` | Get configuration schema |
191
+ | `applyConfig(params)` | Apply configuration changes |
192
+ | `patchConfig(params)` | Patch configuration |
193
+
194
+ ### Sessions
195
+
196
+ | Method | Description |
197
+ |---|---|
198
+ | `listSessions(params?)` | List sessions |
199
+ | `deleteSession(params)` | Delete a session |
200
+ | `previewSessions(params)` | Preview sessions |
201
+ | `resolveSession(params)` | Resolve session |
202
+ | `patchSession(params)` | Patch session |
203
+ | `resetSession(params)` | Reset session |
204
+ | `compactSession(params)` | Compact session |
205
+ | `getSessionsUsage(params?)` | Get session usage |
206
+
207
+ ### Agents
208
+
209
+ | Method | Description |
210
+ |---|---|
211
+ | `listAgents(params?)` | List available agents |
212
+ | `createAgent(params)` | Create agent |
213
+ | `updateAgent(params)` | Update agent |
214
+ | `deleteAgent(params)` | Delete agent |
215
+ | `getAgentIdentity(params?)` | Get agent identity |
216
+ | `sendToAgent(params)` | Send message to agent |
217
+ | `waitForAgent(params)` | Wait for agent run |
218
+ | `getAgentFile(params)` | Get agent file |
219
+ | `listAgentFiles(params)` | List agent files |
220
+ | `setAgentFile(params)` | Set agent file content |
221
+
222
+ ### Chat & Messaging
223
+
224
+ | Method | Description |
225
+ |---|---|
226
+ | `sendChat(params)` | Send chat message |
227
+ | `getChatHistory(params)` | Get chat history |
228
+ | `abortChat(params)` | Abort chat |
229
+ | `injectChat(params)` | Inject chat message |
230
+ | `send(params)` | Send a message |
231
+ | `poll(params)` | Send a poll |
232
+ | `wake(params)` | Wake the system |
233
+
234
+ ### Models
235
+
236
+ | Method | Description |
237
+ |---|---|
238
+ | `listModels(params?)` | List available models |
239
+
240
+ ### Device Pairing
241
+
242
+ | Method | Description |
243
+ |---|---|
244
+ | `listDevicePairings(params?)` | List device pairing requests |
245
+ | `approveDevicePairing(params)` | Approve device pairing |
246
+ | `rejectDevicePairing(params)` | Reject device pairing |
247
+ | `removeDevicePairing(params)` | Remove paired device |
248
+ | `rotateDeviceToken(params)` | Rotate device token |
249
+ | `revokeDeviceToken(params)` | Revoke device token |
250
+
251
+ ### Node Management
252
+
253
+ | Method | Description |
254
+ |---|---|
255
+ | `listNodes(params?)` | List nodes |
256
+ | `describeNode(params)` | Describe node |
257
+ | `invokeNode(params)` | Invoke node command |
258
+ | `renameNode(params)` | Rename node |
259
+ | `requestNodePairing(params)` | Request node pairing |
260
+ | `listNodePairings(params?)` | List node pairing requests |
261
+ | `approveNodePairing(params)` | Approve node pairing |
262
+ | `rejectNodePairing(params)` | Reject node pairing |
263
+ | `verifyNodePairing(params)` | Verify node pairing |
264
+ | `testPush(params)` | Test push notification |
265
+
266
+ ### Wizard
267
+
268
+ | Method | Description |
269
+ |---|---|
270
+ | `startWizard(params?)` | Start wizard |
271
+ | `wizardNext(params)` | Wizard next step |
272
+ | `cancelWizard(params)` | Cancel wizard |
273
+ | `getWizardStatus(params)` | Get wizard status |
274
+
275
+ ### Skills
276
+
277
+ | Method | Description |
278
+ |---|---|
279
+ | `getSkillsStatus(params?)` | Get skills status |
280
+ | `getSkillsBins(params?)` | Get skills bins |
281
+ | `installSkill(params)` | Install skill |
282
+ | `updateSkill(params)` | Update skill |
283
+
284
+ ### Cron Jobs
285
+
286
+ | Method | Description |
287
+ |---|---|
288
+ | `listCronJobs(params?)` | List cron jobs |
289
+ | `getCronStatus(params?)` | Get cron status |
290
+ | `addCronJob(params)` | Add cron job |
291
+ | `updateCronJob(params)` | Update cron job |
292
+ | `removeCronJob(params)` | Remove cron job |
293
+ | `runCronJob(params)` | Run cron job |
294
+ | `getCronRuns(params)` | Get cron job runs |
295
+
296
+ ### Execution Approvals
297
+
298
+ | Method | Description |
299
+ |---|---|
300
+ | `getExecApprovals(params?)` | Get exec approvals |
301
+ | `setExecApprovals(params)` | Set exec approvals |
302
+ | `getNodeExecApprovals(params)` | Get node exec approvals |
303
+ | `setNodeExecApprovals(params)` | Set node exec approvals |
304
+ | `requestExecApproval(params)` | Request exec approval |
305
+ | `resolveExecApproval(params)` | Resolve exec approval |
306
+
307
+ ### Channels, Auth & Other
308
+
309
+ | Method | Description |
310
+ |---|---|
311
+ | `getChannelsStatus(params?)` | Get channels status |
312
+ | `logoutChannel(params)` | Logout from channel |
313
+ | `setTalkMode(params)` | Set talk mode |
314
+ | `getTalkConfig(params?)` | Get talk config |
315
+ | `startWebLogin(params?)` | Start web login |
316
+ | `waitForWebLogin(params?)` | Wait for web login |
317
+ | `getLogTail(params?)` | Get log tail |
318
+ | `updateRun(params)` | Update and run |
319
+ | `call(method, params?)` | Generic RPC call |
320
+
321
+ ## Server-Side Usage
322
+
323
+ `ServerOpenClawClient` manages connection lifecycle for server actions (Next.js, etc.):
187
324
 
188
325
  ```typescript
189
326
  import { ServerOpenClawClient, createServerClient } from 'openclaw-client';
@@ -191,7 +328,6 @@ import { ServerOpenClawClient, createServerClient } from 'openclaw-client';
191
328
  // Create from environment variables
192
329
  const serverClient = createServerClient();
193
330
 
194
- // Use with automatic connection management
195
331
  export async function myAction() {
196
332
  return serverClient.withClient(async (client) => {
197
333
  return await client.listSessions();
@@ -200,112 +336,45 @@ export async function myAction() {
200
336
  ```
201
337
 
202
338
  Environment variables:
203
- - `OPENCLAW_GATEWAY_URL` - Gateway URL (default: `http://localhost:18789`)
204
- - `OPENCLAW_TOKEN` - Authentication token
205
-
206
- ## Type Generation & Client Wrapper Maintenance
339
+ - `OPENCLAW_GATEWAY_URL` Gateway URL (default: `http://localhost:18789`)
340
+ - `OPENCLAW_TOKEN` Authentication token
207
341
 
208
- This package uses a deterministic process to keep types and client method wrappers in sync with the OpenClaw protocol schema.
342
+ ## Advanced: Manual Device Signing
209
343
 
210
- ### Step 1: Update the schema
344
+ If you need full control over the signing process, use `connectParams` as a function instead of `deviceIdentity`:
211
345
 
212
- Place the latest `protocol.schema.json` from the OpenClaw Gateway into `src/protocol.schema.json`.
213
-
214
- ### Step 2: Regenerate types
215
-
216
- ```bash
217
- npm run generate:types
346
+ ```typescript
347
+ const client = new OpenClawClient({
348
+ gatewayUrl: 'wss://gateway.example.com',
349
+ token: 'your-token',
350
+ connectParams: async (challenge) => ({
351
+ device: {
352
+ id: myDeviceId,
353
+ publicKey: myPublicKey,
354
+ signature: await sign(challenge.nonce),
355
+ signedAt: Date.now(),
356
+ nonce: challenge.nonce,
357
+ },
358
+ }),
359
+ });
218
360
  ```
219
361
 
220
- This runs `src/generate-openclaw-types.ts` which uses `json-schema-to-typescript` to compile every definition in the schema into TypeScript interfaces. The output is written to `src/types.ts` (auto-generated, do not edit manually).
221
-
222
- ### Step 3: Update client method wrappers
362
+ ## Type Generation
223
363
 
224
- The method wrappers in `src/client.ts` follow a deterministic pattern derived from the type names in `src/types.ts`:
225
-
226
- 1. **Find all `*Params` types** - Each `*Params` interface represents an RPC method.
227
- 2. **Derive the method name** - Convert the type name to a dot-separated RPC method name:
228
- - `ConfigGetParams` → `config.get`
229
- - `SessionsListParams` → `sessions.list`
230
- - `AgentsFilesGetParams` → `agents.files.get`
231
- - `ExecApprovalsNodeSetParams` → `exec.approvals.node.set`
232
- - Top-level methods like `SendParams`, `PollParams`, `WakeParams` → `send`, `poll`, `wake`
233
- 3. **Match result types** - If a corresponding `*Result` type exists (e.g. `AgentsListResult` for `AgentsListParams`), use it as the return type. Otherwise use `Promise<any>`.
234
- 4. **Choose a wrapper method name** - Use a readable camelCase name (e.g. `listSessions`, `getConfig`, `deleteAgent`).
235
- 5. **Default empty params** - If the `*Params` interface has no required fields (e.g. `interface ConfigGetParams {}`), default the parameter to `= {}`.
236
- 6. **Import and add** - Import the new Params/Result types at the top of `client.ts` and add the wrapper method.
237
-
238
- **Skipped types:** Some `*Params` types are not RPC request methods but are used for node-side responses or event payloads (e.g. `NodeInvokeResultParams`, `NodeEventParams`). These are skipped.
239
-
240
- ### Full update workflow
364
+ Types are auto-generated from the OpenClaw protocol schema:
241
365
 
242
366
  ```bash
243
- # 1. Drop in updated schema
244
- cp /path/to/new/protocol.schema.json src/protocol.schema.json
367
+ # 1. Place updated schema
368
+ cp /path/to/protocol.schema.json src/protocol.schema.json
245
369
 
246
370
  # 2. Regenerate types
247
371
  npm run generate:types
248
372
 
249
- # 3. Update client wrappers (compare types.ts *Params exports against client.ts imports)
250
- # - Add imports for any new *Params/*Result types
251
- # - Add wrapper methods following the pattern above
252
- # - Verify no existing types were removed/renamed
253
-
254
- # 4. Build and verify
373
+ # 3. Build
255
374
  npm run build
256
-
257
- # 5. Publish
258
- npm publish
259
375
  ```
260
376
 
261
- ## Development
262
-
263
- ```bash
264
- # Install dependencies
265
- npm install
266
-
267
- # Generate types from schema
268
- npm run generate:types
269
-
270
- # Build the package
271
- npm run build
272
-
273
- # Publish to npm
274
- npm publish
275
- ```
276
-
277
- ## Changelog
278
-
279
- ### 2.0.1
280
-
281
- **Bug Fixes**
282
-
283
- - **Challenge nonce now passed to `connectParams`** - The challenge received during the connect handshake was being ignored (`_challenge`). `connectParams` can now be a function that receives the challenge `{ nonce, ts }`, allowing callers to sign the nonce into `device.nonce`. Static objects still work as before (backwards compatible).
284
-
285
- ### 2.0.0
286
-
287
- **Breaking Changes**
288
-
289
- - **Connect handshake protocol** - The client now implements a challenge-response handshake. On connect, the gateway sends a `connect.challenge` event with a nonce before the client sends its `connect` request. This requires a compatible gateway version.
290
-
291
- **New Features**
292
-
293
- - **Configurable timeouts** - New `connectTimeoutMs` (default 120s) and `requestTimeoutMs` (default 30s) config options.
294
- - **Connect params override** - New `connectParams` config option to merge additional fields into the handshake request (e.g. `device`, `caps`, `commands`).
295
- - **New API methods:**
296
- - `createAgent` / `updateAgent` / `deleteAgent` - Full agent CRUD
297
- - `getSessionsUsage` - Session usage stats
298
- - `getTalkConfig` - Talk configuration
299
- - `removeDevicePairing` - Remove a paired device
300
- - `testPush` - Test push notifications to a node
301
-
302
- ### 1.1.1
303
-
304
- - Documentation updates.
305
-
306
- ### 1.1.0
307
-
308
- - Initial public release with full Gateway RPC coverage.
377
+ See `src/generate-openclaw-types.ts` for the generation logic.
309
378
 
310
379
  ## License
311
380
 
package/dist/client.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { DeviceIdentityStore, DeviceTokenStore } from './device-identity';
2
+ import type { ReconnectConfig } from './reconnect';
1
3
  import type { AgentIdentityParams, AgentIdentityResult, AgentParams, AgentsCreateParams, AgentsCreateResult, AgentsDeleteParams, AgentsDeleteResult, AgentsFilesGetParams, AgentsFilesGetResult, AgentsFilesListParams, AgentsFilesListResult, AgentsFilesSetParams, AgentsFilesSetResult, AgentsListParams, AgentsListResult, AgentsUpdateParams, AgentsUpdateResult, AgentWaitParams, ChannelsLogoutParams, ChannelsStatusParams, ChannelsStatusResult, ChatAbortParams, ChatHistoryParams, ChatInjectParams, ChatSendParams, ConfigApplyParams, ConfigGetParams, ConfigPatchParams, ConfigSchemaParams, ConfigSchemaResponse, ConfigSetParams, ConnectParams, CronAddParams, CronJob, CronListParams, CronRemoveParams, CronRunLogEntry, CronRunParams, CronRunsParams, CronStatusParams, CronUpdateParams, DevicePairApproveParams, DevicePairListParams, DevicePairRejectParams, DevicePairRemoveParams, DeviceTokenRevokeParams, DeviceTokenRotateParams, EventFrame, ExecApprovalRequestParams, ExecApprovalResolveParams, ExecApprovalsGetParams, ExecApprovalsNodeGetParams, ExecApprovalsNodeSetParams, ExecApprovalsSetParams, ExecApprovalsSnapshot, HelloOk, LogsTailParams, LogsTailResult, ModelsListParams, ModelsListResult, NodeDescribeParams, NodeInvokeParams, NodeListParams, NodePairApproveParams, NodePairListParams, NodePairRejectParams, NodePairRequestParams, NodePairVerifyParams, NodeRenameParams, PollParams, PushTestParams, PushTestResult, SendParams, SessionsCompactParams, SessionsDeleteParams, SessionsListParams, SessionsPatchParams, SessionsPreviewParams, SessionsResetParams, SessionsResolveParams, SessionsUsageParams, SkillsBinsParams, SkillsBinsResult, SkillsInstallParams, SkillsStatusParams, SkillsUpdateParams, TalkConfigParams, TalkConfigResult, TalkModeParams, UpdateRunParams, WakeParams, WebLoginStartParams, WebLoginWaitParams, WizardCancelParams, WizardNextParams, WizardNextResult, WizardStartParams, WizardStartResult, WizardStatusParams, WizardStatusResult } from './types';
2
4
  export interface OpenClawClientConfig {
3
5
  gatewayUrl: string;
@@ -19,6 +21,20 @@ export interface OpenClawClientConfig {
19
21
  nonce: string;
20
22
  ts: number;
21
23
  }) => Partial<ConnectParams> | Promise<Partial<ConnectParams>>);
24
+ /** Provide a DeviceIdentityStore to enable built-in Ed25519 device signing.
25
+ * When set, the library generates/loads a keypair and signs the connect
26
+ * request automatically (takes precedence over connectParams function). */
27
+ deviceIdentity?: DeviceIdentityStore;
28
+ /** Optional store for persisting the device token returned by the gateway
29
+ * after pairing approval. The stored token is preferred over config.token
30
+ * for subsequent connections. */
31
+ deviceToken?: DeviceTokenStore;
32
+ /** Enable automatic reconnection with exponential backoff. */
33
+ reconnect?: ReconnectConfig;
34
+ /** Called when connection state changes. */
35
+ onConnection?: (connected: boolean) => void;
36
+ /** Called when the gateway indicates device pairing is required. */
37
+ onPairingRequired?: (required: boolean) => void;
22
38
  }
23
39
  export type EventListener = (event: EventFrame) => void;
24
40
  export declare class OpenClawClient {
@@ -29,6 +45,10 @@ export declare class OpenClawClient {
29
45
  private eventListeners;
30
46
  private connected;
31
47
  private connectionId;
48
+ private deviceManager;
49
+ private reconnectController;
50
+ private reconnecting;
51
+ private intentionalDisconnect;
32
52
  constructor(config: OpenClawClientConfig);
33
53
  /**
34
54
  * Connect to the OpenClaw Gateway and perform handshake.
@@ -77,6 +97,7 @@ export declare class OpenClawClient {
77
97
  * Handle event frame
78
98
  */
79
99
  private handleEvent;
100
+ private attemptReconnect;
80
101
  /**
81
102
  * Handle connection close
82
103
  */