openclaw-client 2.0.0 → 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:
128
+
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
+ });
41
143
 
42
- Main WebSocket client for OpenClaw Gateway.
144
+ await client.connect();
145
+ // If connection drops, client will automatically reconnect
146
+ // Calling client.disconnect() stops reconnection
147
+ ```
43
148
 
44
- #### Configuration
149
+ ## Configuration Reference
45
150
 
46
151
  ```typescript
47
152
  interface OpenClawClientConfig {
@@ -51,137 +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>; // Extra fields merged into handshake
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...
162
+ | ((challenge: { nonce: string; ts: number }) => // ...function receiving challenge
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
57
169
  }
58
170
  ```
59
171
 
60
- #### Methods
61
-
62
- **Connection Management**
63
- - `connect(): Promise<HelloOk>` - Connect and authenticate
64
- - `disconnect(): void` - Disconnect from Gateway
65
- - `isConnected(): boolean` - Check connection status
66
- - `getConnectionId(): string | null` - Get the current connection ID
67
- - `addEventListener(listener): () => void` - Add event listener
68
-
69
- **Configuration**
70
- - `getConfig(params?): Promise<any>` - Get configuration
71
- - `setConfig(params): Promise<any>` - Update configuration
72
- - `getConfigSchema(params?): Promise<ConfigSchemaResponse>` - Get configuration schema
73
- - `applyConfig(params): Promise<any>` - Apply configuration changes
74
- - `patchConfig(params): Promise<any>` - Patch configuration
75
-
76
- **Sessions**
77
- - `listSessions(params?): Promise<any>` - List sessions
78
- - `deleteSession(params): Promise<any>` - Delete a session
79
- - `previewSessions(params): Promise<any>` - Preview sessions
80
- - `resolveSession(params): Promise<any>` - Resolve session
81
- - `patchSession(params): Promise<any>` - Patch session
82
- - `resetSession(params): Promise<any>` - Reset session
83
- - `compactSession(params): Promise<any>` - Compact session
84
- - `getSessionsUsage(params?): Promise<any>` - Get session usage
85
-
86
- **Agents**
87
- - `listAgents(params?): Promise<AgentsListResult>` - List available agents
88
- - `createAgent(params): Promise<AgentsCreateResult>` - Create agent
89
- - `updateAgent(params): Promise<AgentsUpdateResult>` - Update agent
90
- - `deleteAgent(params): Promise<AgentsDeleteResult>` - Delete agent
91
- - `getAgentIdentity(params?): Promise<AgentIdentityResult>` - Get agent identity
92
- - `sendToAgent(params): Promise<any>` - Send a message to agent
93
- - `waitForAgent(params): Promise<any>` - Wait for agent run to complete
94
-
95
- **Agent Files**
96
- - `getAgentFile(params): Promise<AgentsFilesGetResult>` - Get agent file
97
- - `listAgentFiles(params): Promise<AgentsFilesListResult>` - List agent files
98
- - `setAgentFile(params): Promise<AgentsFilesSetResult>` - Update agent file
99
-
100
- **Models**
101
- - `listModels(params?): Promise<ModelsListResult>` - List available models
102
-
103
- **Messaging**
104
- - `send(params): Promise<any>` - Send a message
105
- - `poll(params): Promise<any>` - Send a poll
106
- - `wake(params): Promise<any>` - Wake the system
107
-
108
- **Chat**
109
- - `getChatHistory(params): Promise<any>` - Get chat history
110
- - `sendChat(params): Promise<any>` - Send chat message
111
- - `abortChat(params): Promise<any>` - Abort chat
112
- - `injectChat(params): Promise<any>` - Inject chat message
113
-
114
- **Wizard**
115
- - `startWizard(params?): Promise<WizardStartResult>` - Start wizard
116
- - `wizardNext(params): Promise<WizardNextResult>` - Wizard next step
117
- - `cancelWizard(params): Promise<any>` - Cancel wizard
118
- - `getWizardStatus(params): Promise<WizardStatusResult>` - Get wizard status
119
-
120
- **Channels & Talk**
121
- - `getChannelsStatus(params?): Promise<ChannelsStatusResult>` - Get channels status
122
- - `logoutChannel(params): Promise<any>` - Logout from channel
123
- - `setTalkMode(params): Promise<any>` - Set talk mode
124
- - `getTalkConfig(params?): Promise<TalkConfigResult>` - Get talk config
125
-
126
- **Authentication**
127
- - `startWebLogin(params?): Promise<any>` - Start web login
128
- - `waitForWebLogin(params?): Promise<any>` - Wait for web login
129
-
130
- **Skills**
131
- - `getSkillsStatus(params?): Promise<any>` - Get skills status
132
- - `getSkillsBins(params?): Promise<SkillsBinsResult>` - Get skills bins
133
- - `installSkill(params): Promise<any>` - Install skill
134
- - `updateSkill(params): Promise<any>` - Update skill
135
-
136
- **Cron Jobs**
137
- - `listCronJobs(params?): Promise<{ jobs: CronJob[] }>` - List cron jobs
138
- - `getCronStatus(params?): Promise<any>` - Get cron status
139
- - `addCronJob(params): Promise<{ job: CronJob }>` - Add cron job
140
- - `updateCronJob(params): Promise<{ job: CronJob }>` - Update cron job
141
- - `removeCronJob(params): Promise<any>` - Remove cron job
142
- - `runCronJob(params): Promise<any>` - Run cron job
143
- - `getCronRuns(params): Promise<{ runs: CronRunLogEntry[] }>` - Get cron job runs
144
-
145
- **Execution Approvals**
146
- - `getExecApprovals(params?): Promise<ExecApprovalsSnapshot>` - Get exec approvals
147
- - `setExecApprovals(params): Promise<ExecApprovalsSnapshot>` - Set exec approvals
148
- - `getNodeExecApprovals(params): Promise<ExecApprovalsSnapshot>` - Get node exec approvals
149
- - `setNodeExecApprovals(params): Promise<ExecApprovalsSnapshot>` - Set node exec approvals
150
- - `requestExecApproval(params): Promise<any>` - Request exec approval
151
- - `resolveExecApproval(params): Promise<any>` - Resolve exec approval
152
-
153
- **Device Pairing**
154
- - `listDevicePairings(params?): Promise<any>` - List device pairing requests
155
- - `approveDevicePairing(params): Promise<any>` - Approve device pairing
156
- - `rejectDevicePairing(params): Promise<any>` - Reject device pairing
157
- - `removeDevicePairing(params): Promise<any>` - Remove paired device
158
- - `rotateDeviceToken(params): Promise<any>` - Rotate device token
159
- - `revokeDeviceToken(params): Promise<any>` - Revoke device token
160
-
161
- **Node Management**
162
- - `requestNodePairing(params): Promise<any>` - Request node pairing
163
- - `listNodePairings(params?): Promise<any>` - List node pairing requests
164
- - `approveNodePairing(params): Promise<any>` - Approve node pairing
165
- - `rejectNodePairing(params): Promise<any>` - Reject node pairing
166
- - `verifyNodePairing(params): Promise<any>` - Verify node pairing
167
- - `renameNode(params): Promise<any>` - Rename node
168
- - `listNodes(params?): Promise<any>` - List nodes
169
- - `describeNode(params): Promise<any>` - Describe node
170
- - `invokeNode(params): Promise<any>` - Invoke node command
171
- - `testPush(params): Promise<PushTestResult>` - Test push notification to node
172
-
173
- **Logs**
174
- - `getLogTail(params?): Promise<LogsTailResult>` - Get log tail
175
-
176
- **Updates**
177
- - `updateRun(params): Promise<any>` - Update and run
178
-
179
- **Generic**
180
- - `call<T>(method, params?): Promise<T>` - Generic RPC method call for any method
181
-
182
- ### `ServerOpenClawClient`
183
-
184
- 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.):
185
324
 
186
325
  ```typescript
187
326
  import { ServerOpenClawClient, createServerClient } from 'openclaw-client';
@@ -189,7 +328,6 @@ import { ServerOpenClawClient, createServerClient } from 'openclaw-client';
189
328
  // Create from environment variables
190
329
  const serverClient = createServerClient();
191
330
 
192
- // Use with automatic connection management
193
331
  export async function myAction() {
194
332
  return serverClient.withClient(async (client) => {
195
333
  return await client.listSessions();
@@ -198,106 +336,45 @@ export async function myAction() {
198
336
  ```
199
337
 
200
338
  Environment variables:
201
- - `OPENCLAW_GATEWAY_URL` - Gateway URL (default: `http://localhost:18789`)
202
- - `OPENCLAW_TOKEN` - Authentication token
203
-
204
- ## Type Generation & Client Wrapper Maintenance
205
-
206
- This package uses a deterministic process to keep types and client method wrappers in sync with the OpenClaw protocol schema.
339
+ - `OPENCLAW_GATEWAY_URL` Gateway URL (default: `http://localhost:18789`)
340
+ - `OPENCLAW_TOKEN` Authentication token
207
341
 
208
- ### Step 1: Update the schema
342
+ ## Advanced: Manual Device Signing
209
343
 
210
- Place the latest `protocol.schema.json` from the OpenClaw Gateway into `src/protocol.schema.json`.
344
+ If you need full control over the signing process, use `connectParams` as a function instead of `deviceIdentity`:
211
345
 
212
- ### Step 2: Regenerate types
213
-
214
- ```bash
215
- 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
+ });
216
360
  ```
217
361
 
218
- 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).
219
-
220
- ### Step 3: Update client method wrappers
221
-
222
- The method wrappers in `src/client.ts` follow a deterministic pattern derived from the type names in `src/types.ts`:
223
-
224
- 1. **Find all `*Params` types** - Each `*Params` interface represents an RPC method.
225
- 2. **Derive the method name** - Convert the type name to a dot-separated RPC method name:
226
- - `ConfigGetParams` → `config.get`
227
- - `SessionsListParams` → `sessions.list`
228
- - `AgentsFilesGetParams` → `agents.files.get`
229
- - `ExecApprovalsNodeSetParams` → `exec.approvals.node.set`
230
- - Top-level methods like `SendParams`, `PollParams`, `WakeParams` → `send`, `poll`, `wake`
231
- 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>`.
232
- 4. **Choose a wrapper method name** - Use a readable camelCase name (e.g. `listSessions`, `getConfig`, `deleteAgent`).
233
- 5. **Default empty params** - If the `*Params` interface has no required fields (e.g. `interface ConfigGetParams {}`), default the parameter to `= {}`.
234
- 6. **Import and add** - Import the new Params/Result types at the top of `client.ts` and add the wrapper method.
362
+ ## Type Generation
235
363
 
236
- **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.
237
-
238
- ### Full update workflow
364
+ Types are auto-generated from the OpenClaw protocol schema:
239
365
 
240
366
  ```bash
241
- # 1. Drop in updated schema
242
- 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
243
369
 
244
370
  # 2. Regenerate types
245
371
  npm run generate:types
246
372
 
247
- # 3. Update client wrappers (compare types.ts *Params exports against client.ts imports)
248
- # - Add imports for any new *Params/*Result types
249
- # - Add wrapper methods following the pattern above
250
- # - Verify no existing types were removed/renamed
251
-
252
- # 4. Build and verify
253
- npm run build
254
-
255
- # 5. Publish
256
- npm publish
257
- ```
258
-
259
- ## Development
260
-
261
- ```bash
262
- # Install dependencies
263
- npm install
264
-
265
- # Generate types from schema
266
- npm run generate:types
267
-
268
- # Build the package
373
+ # 3. Build
269
374
  npm run build
270
-
271
- # Publish to npm
272
- npm publish
273
375
  ```
274
376
 
275
- ## Changelog
276
-
277
- ### 2.0.0
278
-
279
- **Breaking Changes**
280
-
281
- - **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.
282
-
283
- **New Features**
284
-
285
- - **Configurable timeouts** - New `connectTimeoutMs` (default 120s) and `requestTimeoutMs` (default 30s) config options.
286
- - **Connect params override** - New `connectParams` config option to merge additional fields into the handshake request (e.g. `device`, `caps`, `commands`).
287
- - **New API methods:**
288
- - `createAgent` / `updateAgent` / `deleteAgent` - Full agent CRUD
289
- - `getSessionsUsage` - Session usage stats
290
- - `getTalkConfig` - Talk configuration
291
- - `removeDevicePairing` - Remove a paired device
292
- - `testPush` - Test push notifications to a node
293
-
294
- ### 1.1.1
295
-
296
- - Documentation updates.
297
-
298
- ### 1.1.0
299
-
300
- - Initial public release with full Gateway RPC coverage.
377
+ See `src/generate-openclaw-types.ts` for the generation logic.
301
378
 
302
379
  ## License
303
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;
@@ -12,8 +14,27 @@ export interface OpenClawClientConfig {
12
14
  /** Timeout in ms for regular RPC requests (default: 30000). */
13
15
  requestTimeoutMs?: number;
14
16
  /** Additional ConnectParams fields to merge into the handshake request
15
- * (e.g. `device` for device identity, `caps`, `commands`). */
16
- connectParams?: Partial<ConnectParams>;
17
+ * (e.g. `device` for device identity, `caps`, `commands`).
18
+ * Can be a static object or a function that receives the challenge
19
+ * (useful for signing the nonce into `device.nonce`). */
20
+ connectParams?: Partial<ConnectParams> | ((challenge: {
21
+ nonce: string;
22
+ ts: number;
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;
17
38
  }
18
39
  export type EventListener = (event: EventFrame) => void;
19
40
  export declare class OpenClawClient {
@@ -24,6 +45,10 @@ export declare class OpenClawClient {
24
45
  private eventListeners;
25
46
  private connected;
26
47
  private connectionId;
48
+ private deviceManager;
49
+ private reconnectController;
50
+ private reconnecting;
51
+ private intentionalDisconnect;
27
52
  constructor(config: OpenClawClientConfig);
28
53
  /**
29
54
  * Connect to the OpenClaw Gateway and perform handshake.
@@ -72,6 +97,7 @@ export declare class OpenClawClient {
72
97
  * Handle event frame
73
98
  */
74
99
  private handleEvent;
100
+ private attemptReconnect;
75
101
  /**
76
102
  * Handle connection close
77
103
  */