@astroanywhere/agent 0.1.35 → 0.1.36

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.
Files changed (44) hide show
  1. package/dist/cli.js +8 -11
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/start.d.ts.map +1 -1
  4. package/dist/commands/start.js +71 -51
  5. package/dist/commands/start.js.map +1 -1
  6. package/dist/lib/display.d.ts +24 -0
  7. package/dist/lib/display.d.ts.map +1 -0
  8. package/dist/lib/display.js +202 -0
  9. package/dist/lib/display.js.map +1 -0
  10. package/dist/lib/openclaw-bridge.d.ts +73 -0
  11. package/dist/lib/openclaw-bridge.d.ts.map +1 -0
  12. package/dist/lib/openclaw-bridge.js +457 -0
  13. package/dist/lib/openclaw-bridge.js.map +1 -0
  14. package/dist/lib/providers.d.ts.map +1 -1
  15. package/dist/lib/providers.js +46 -53
  16. package/dist/lib/providers.js.map +1 -1
  17. package/dist/lib/ssh-installer.d.ts +19 -10
  18. package/dist/lib/ssh-installer.d.ts.map +1 -1
  19. package/dist/lib/ssh-installer.js +18 -12
  20. package/dist/lib/ssh-installer.js.map +1 -1
  21. package/dist/lib/task-executor.d.ts +8 -1
  22. package/dist/lib/task-executor.d.ts.map +1 -1
  23. package/dist/lib/task-executor.js +77 -4
  24. package/dist/lib/task-executor.js.map +1 -1
  25. package/dist/lib/websocket-client.d.ts +5 -0
  26. package/dist/lib/websocket-client.d.ts.map +1 -1
  27. package/dist/lib/websocket-client.js +159 -0
  28. package/dist/lib/websocket-client.js.map +1 -1
  29. package/dist/mcp/tools.d.ts +1 -1
  30. package/dist/providers/claude-sdk-adapter.d.ts +4 -1
  31. package/dist/providers/claude-sdk-adapter.d.ts.map +1 -1
  32. package/dist/providers/claude-sdk-adapter.js +16 -5
  33. package/dist/providers/claude-sdk-adapter.js.map +1 -1
  34. package/dist/providers/openclaw-adapter.d.ts +46 -29
  35. package/dist/providers/openclaw-adapter.d.ts.map +1 -1
  36. package/dist/providers/openclaw-adapter.js +603 -215
  37. package/dist/providers/openclaw-adapter.js.map +1 -1
  38. package/dist/providers/opencode-adapter.d.ts +29 -0
  39. package/dist/providers/opencode-adapter.d.ts.map +1 -1
  40. package/dist/providers/opencode-adapter.js +145 -38
  41. package/dist/providers/opencode-adapter.js.map +1 -1
  42. package/dist/types.d.ts +83 -1
  43. package/dist/types.d.ts.map +1 -1
  44. package/package.json +1 -1
@@ -0,0 +1,457 @@
1
+ /**
2
+ * OpenClaw Bridge — Persistent gateway connection for channel operations
3
+ *
4
+ * Unlike the per-task OpenClawAdapter (which creates a new connection per task),
5
+ * the bridge maintains a single long-lived WebSocket to the OpenClaw gateway
6
+ * for notification delivery, approval routing, and inbound message forwarding.
7
+ *
8
+ * This enables the relay-routed architecture:
9
+ * Server → Relay → Agent Runner (bridge) → OpenClaw Gateway → User channels
10
+ */
11
+ import { EventEmitter } from 'node:events';
12
+ import { readFileSync, existsSync } from 'node:fs';
13
+ import { join } from 'node:path';
14
+ import { homedir } from 'node:os';
15
+ import WebSocket from 'ws';
16
+ import { randomUUID } from 'node:crypto';
17
+ // ---------------------------------------------------------------------------
18
+ // Constants
19
+ // ---------------------------------------------------------------------------
20
+ const PROTOCOL_VERSION = 3;
21
+ const CONNECT_TIMEOUT_MS = 10_000;
22
+ const REQUEST_TIMEOUT_MS = 15_000;
23
+ const APPROVAL_TIMEOUT_MS = 300_000; // 5 minutes
24
+ const RECONNECT_DELAY_MS = 5_000;
25
+ // ---------------------------------------------------------------------------
26
+ // Bridge
27
+ // ---------------------------------------------------------------------------
28
+ export class OpenClawBridge extends EventEmitter {
29
+ ws = null;
30
+ gatewayConfig = null;
31
+ pendingRequests = new Map();
32
+ pendingApprovals = new Map();
33
+ _connected = false;
34
+ _started = false;
35
+ _connecting = false;
36
+ reconnectTimer = null;
37
+ /** Default recipient for send (e.g., Telegram username, phone). Read from openclaw.json */
38
+ defaultRecipient = null;
39
+ /** Telegram bot token, cached from config at start() */
40
+ telegramBotToken = null;
41
+ get isConnected() {
42
+ return this._connected && this.ws !== null && this.ws.readyState === WebSocket.OPEN;
43
+ }
44
+ // ─── Lifecycle ──────────────────────────────────────────────────
45
+ async start() {
46
+ if (this._started)
47
+ return this._connected;
48
+ const config = this.readGatewayConfig();
49
+ if (!config)
50
+ return false;
51
+ this.gatewayConfig = config;
52
+ this.defaultRecipient = config.defaultRecipient || null;
53
+ this.telegramBotToken = this.readTelegramBotToken();
54
+ this._started = true;
55
+ try {
56
+ await this.connect();
57
+ }
58
+ catch {
59
+ // Reset so future start() calls can retry
60
+ this._started = false;
61
+ }
62
+ if (!this._connected) {
63
+ this._started = false;
64
+ }
65
+ return this._connected;
66
+ }
67
+ stop() {
68
+ this._started = false;
69
+ this._connected = false;
70
+ if (this.reconnectTimer) {
71
+ clearTimeout(this.reconnectTimer);
72
+ this.reconnectTimer = null;
73
+ }
74
+ for (const [id, pending] of this.pendingRequests) {
75
+ clearTimeout(pending.timeoutId);
76
+ pending.reject(new Error('Bridge stopped'));
77
+ this.pendingRequests.delete(id);
78
+ }
79
+ for (const [id, pending] of this.pendingApprovals) {
80
+ clearTimeout(pending.timeoutId);
81
+ pending.reject(new Error('Bridge stopped'));
82
+ this.pendingApprovals.delete(id);
83
+ }
84
+ if (this.ws) {
85
+ this.ws.removeAllListeners();
86
+ this.ws.close();
87
+ this.ws = null;
88
+ }
89
+ // Remove external EventEmitter listeners (e.g., 'inbound' from websocket-client)
90
+ // to prevent leaks if the bridge is restarted after stop()
91
+ this.removeAllListeners();
92
+ }
93
+ // ─── Gateway Config ─────────────────────────────────────────────
94
+ readGatewayConfig() {
95
+ try {
96
+ const configPath = join(homedir(), '.openclaw', 'openclaw.json');
97
+ if (!existsSync(configPath))
98
+ return null;
99
+ const raw = JSON.parse(readFileSync(configPath, 'utf-8'));
100
+ const port = raw?.gateway?.port;
101
+ if (!port)
102
+ return null;
103
+ const token = raw?.gateway?.auth?.token || '';
104
+ const bind = raw?.gateway?.bind || '127.0.0.1';
105
+ const host = bind === 'loopback' || bind === '127.0.0.1' ? '127.0.0.1' : bind;
106
+ // Read default notification recipient from astro-specific config
107
+ const defaultRecipient = raw?.astro?.notifyTo || undefined;
108
+ return { port, token, url: `ws://${host}:${port}`, defaultRecipient };
109
+ }
110
+ catch {
111
+ return null;
112
+ }
113
+ }
114
+ // ─── Gateway Connection ─────────────────────────────────────────
115
+ connect() {
116
+ if (!this.gatewayConfig)
117
+ return Promise.resolve();
118
+ if (this._connecting)
119
+ return Promise.resolve();
120
+ this._connecting = true;
121
+ return new Promise((resolve) => {
122
+ // Clean up old WebSocket handlers to prevent leaks on reconnection
123
+ if (this.ws) {
124
+ this.ws.removeAllListeners();
125
+ this.ws = null;
126
+ }
127
+ const done = () => { this._connecting = false; resolve(); };
128
+ const timeout = setTimeout(() => {
129
+ console.warn('[openclaw-bridge] Connection timeout');
130
+ if (this.ws) {
131
+ this.ws.removeAllListeners();
132
+ this.ws.close();
133
+ this.ws = null;
134
+ }
135
+ done();
136
+ }, CONNECT_TIMEOUT_MS);
137
+ const ws = new WebSocket(this.gatewayConfig.url);
138
+ this.ws = ws;
139
+ ws.on('message', (data) => {
140
+ let frame;
141
+ try {
142
+ frame = JSON.parse(String(data));
143
+ }
144
+ catch {
145
+ return;
146
+ }
147
+ // Challenge → send connect
148
+ if (frame.type === 'event' && frame.event === 'connect.challenge') {
149
+ ws.send(JSON.stringify({
150
+ type: 'req',
151
+ id: 'connect-1',
152
+ method: 'connect',
153
+ params: {
154
+ minProtocol: PROTOCOL_VERSION,
155
+ maxProtocol: PROTOCOL_VERSION,
156
+ client: {
157
+ id: 'gateway-client',
158
+ version: 'dev',
159
+ platform: process.platform,
160
+ mode: 'backend',
161
+ },
162
+ caps: [],
163
+ auth: { token: this.gatewayConfig.token },
164
+ role: 'operator',
165
+ scopes: ['operator.read', 'operator.write', 'operator.admin'],
166
+ },
167
+ }));
168
+ return;
169
+ }
170
+ // Connect response
171
+ if (frame.type === 'res' && frame.id === 'connect-1') {
172
+ clearTimeout(timeout);
173
+ if (frame.ok) {
174
+ this._connected = true;
175
+ console.log('[openclaw-bridge] Connected to gateway');
176
+ this.emit('connected');
177
+ done();
178
+ }
179
+ else {
180
+ console.error('[openclaw-bridge] Handshake failed:', frame.error?.message);
181
+ ws.close();
182
+ done();
183
+ }
184
+ return;
185
+ }
186
+ // After connected — handle responses and events
187
+ if (this._connected) {
188
+ if (frame.type === 'res') {
189
+ this.handleResponse(frame);
190
+ }
191
+ else if (frame.type === 'event') {
192
+ this.handleEvent(frame);
193
+ }
194
+ }
195
+ });
196
+ ws.on('close', () => {
197
+ this._connected = false;
198
+ this.ws = null;
199
+ this.emit('disconnected');
200
+ if (this._started) {
201
+ this.scheduleReconnect();
202
+ }
203
+ });
204
+ ws.on('error', (err) => {
205
+ console.error('[openclaw-bridge] WebSocket error:', err.message);
206
+ clearTimeout(timeout);
207
+ ws.removeAllListeners();
208
+ ws.close();
209
+ this.ws = null;
210
+ done();
211
+ });
212
+ });
213
+ }
214
+ scheduleReconnect() {
215
+ if (this.reconnectTimer)
216
+ return;
217
+ this.reconnectTimer = setTimeout(() => {
218
+ this.reconnectTimer = null;
219
+ if (this._started) {
220
+ this.connect().catch(() => { });
221
+ }
222
+ }, RECONNECT_DELAY_MS);
223
+ }
224
+ // ─── Request/Response ───────────────────────────────────────────
225
+ sendRequest(method, params) {
226
+ return new Promise((resolve, reject) => {
227
+ if (!this.isConnected) {
228
+ reject(new Error('OpenClaw gateway not connected'));
229
+ return;
230
+ }
231
+ const id = randomUUID();
232
+ const timeoutId = setTimeout(() => {
233
+ this.pendingRequests.delete(id);
234
+ reject(new Error(`Request ${method} timed out`));
235
+ }, REQUEST_TIMEOUT_MS);
236
+ this.pendingRequests.set(id, { resolve, reject, timeoutId });
237
+ try {
238
+ this.ws.send(JSON.stringify({
239
+ type: 'req',
240
+ id,
241
+ method,
242
+ params,
243
+ }));
244
+ }
245
+ catch (err) {
246
+ clearTimeout(timeoutId);
247
+ this.pendingRequests.delete(id);
248
+ reject(err instanceof Error ? err : new Error(String(err)));
249
+ }
250
+ });
251
+ }
252
+ handleResponse(frame) {
253
+ if (!frame.id)
254
+ return;
255
+ const pending = this.pendingRequests.get(frame.id);
256
+ if (!pending)
257
+ return;
258
+ clearTimeout(pending.timeoutId);
259
+ this.pendingRequests.delete(frame.id);
260
+ if (frame.ok) {
261
+ pending.resolve(frame.payload);
262
+ }
263
+ else {
264
+ pending.reject(new Error(frame.error?.message || 'Request failed'));
265
+ }
266
+ }
267
+ handleEvent(frame) {
268
+ if (frame.event === 'approval.response') {
269
+ // Direct approval response (if gateway supports it in the future)
270
+ const approvalId = frame.payload?.approvalId;
271
+ const response = frame.payload?.response;
272
+ if (approvalId && response) {
273
+ this.resolveApproval(approvalId, response);
274
+ }
275
+ }
276
+ else if (frame.event === 'message.inbound') {
277
+ const text = frame.payload?.text || '';
278
+ // If there are pending approvals, treat inbound message as an approval response.
279
+ // NOTE: This FIFO approach assumes serialized approvals. Concurrent approvals
280
+ // using the fallback path (no bot token) may match responses to the wrong request.
281
+ // The Telegram polling path (requestApprovalViaTelegram) avoids this issue.
282
+ if (this.pendingApprovals.size > 0 && text.trim()) {
283
+ if (this.pendingApprovals.size > 1) {
284
+ console.warn(`[openclaw-bridge] ${this.pendingApprovals.size} concurrent approvals pending — FIFO matching may route response to wrong request`);
285
+ }
286
+ const [approvalId] = this.pendingApprovals.keys();
287
+ this.resolveApproval(approvalId, text.trim());
288
+ return;
289
+ }
290
+ // Otherwise forward as a regular inbound message
291
+ this.emit('inbound', frame.payload);
292
+ }
293
+ }
294
+ resolveApproval(approvalId, response) {
295
+ const pending = this.pendingApprovals.get(approvalId);
296
+ if (pending) {
297
+ clearTimeout(pending.timeoutId);
298
+ this.pendingApprovals.delete(approvalId);
299
+ pending.resolve(response);
300
+ }
301
+ this.emit('approval-response', { approvalId, response });
302
+ }
303
+ // ─── Public API ─────────────────────────────────────────────────
304
+ async sendNotification(notification) {
305
+ const prefix = this.getNotificationPrefix(notification.type);
306
+ const msg = `${prefix} ${notification.summary}${notification.astroUrl ? `\n\n${notification.astroUrl}` : ''}`;
307
+ const to = notification.to || this.defaultRecipient;
308
+ if (!to) {
309
+ throw new Error('No recipient configured for OpenClaw notifications (set "to" or defaultRecipient)');
310
+ }
311
+ await this.sendRequest('send', {
312
+ to,
313
+ message: msg,
314
+ idempotencyKey: randomUUID(),
315
+ });
316
+ }
317
+ async sendResponse(response) {
318
+ const to = response.to || response.channelId || this.defaultRecipient;
319
+ if (!to) {
320
+ throw new Error('No recipient for OpenClaw response');
321
+ }
322
+ await this.sendRequest('send', {
323
+ to,
324
+ message: response.text,
325
+ idempotencyKey: randomUUID(),
326
+ ...(response.threadId ? { threadId: response.threadId } : {}),
327
+ });
328
+ }
329
+ async requestApproval(opts) {
330
+ const to = opts.to || this.defaultRecipient;
331
+ if (!to) {
332
+ throw new Error('No recipient configured for OpenClaw approval request');
333
+ }
334
+ const options = opts.options ?? ['Yes', 'No'];
335
+ const botToken = this.telegramBotToken;
336
+ if (botToken) {
337
+ return this.requestApprovalViaTelegram(botToken, to, opts.question, options);
338
+ }
339
+ // Fallback: send via gateway send method (no reply detection)
340
+ const optionLines = options.map((o, i) => ` ${i + 1}. ${o}`).join('\n');
341
+ const message = `[Approval Needed]\n\n${opts.question}\n\n${optionLines}\n\nReply with a number (1-${options.length}) or type your answer.`;
342
+ await this.sendRequest('send', {
343
+ to,
344
+ message,
345
+ idempotencyKey: opts.approvalId,
346
+ });
347
+ // Wait for the user's reply via inbound message
348
+ return new Promise((resolve, reject) => {
349
+ const timeoutId = setTimeout(() => {
350
+ this.pendingApprovals.delete(opts.approvalId);
351
+ reject(new Error(`Approval ${opts.approvalId} timed out after ${APPROVAL_TIMEOUT_MS / 1000}s`));
352
+ }, APPROVAL_TIMEOUT_MS);
353
+ this.pendingApprovals.set(opts.approvalId, {
354
+ resolve: resolve,
355
+ reject,
356
+ timeoutId,
357
+ });
358
+ });
359
+ }
360
+ readTelegramBotToken() {
361
+ try {
362
+ const configPath = join(homedir(), '.openclaw', 'openclaw.json');
363
+ if (!existsSync(configPath))
364
+ return null;
365
+ const raw = JSON.parse(readFileSync(configPath, 'utf-8'));
366
+ return raw?.channels?.telegram?.botToken || null;
367
+ }
368
+ catch {
369
+ return null;
370
+ }
371
+ }
372
+ /**
373
+ * Send approval via Telegram as a single poll.
374
+ *
375
+ * Sends one poll (no auto-close). Periodically calls stopPoll to check
376
+ * for votes. If no votes on first check, re-sends the poll once.
377
+ *
378
+ * Text replies are NOT supported via this path because they conflict
379
+ * with the OpenClaw agent session (the agent would also process the reply).
380
+ */
381
+ async requestApprovalViaTelegram(botToken, chatId, question, options) {
382
+ let pollMessageId = await this.telegramSendPoll(botToken, chatId, question, options);
383
+ if (!pollMessageId)
384
+ throw new Error('Failed to send Telegram poll');
385
+ const CHECK_INTERVAL_MS = 10_000;
386
+ let resent = false;
387
+ return new Promise((resolve, reject) => {
388
+ const overallTimeout = setTimeout(() => {
389
+ clearInterval(timer);
390
+ if (pollMessageId) {
391
+ this.telegramStopPoll(botToken, chatId, pollMessageId).catch(() => { });
392
+ }
393
+ reject(new Error('Approval poll timed out'));
394
+ }, APPROVAL_TIMEOUT_MS);
395
+ const timer = setInterval(async () => {
396
+ if (!pollMessageId)
397
+ return;
398
+ try {
399
+ const result = await this.telegramStopPoll(botToken, chatId, pollMessageId);
400
+ if (result && result.total_voter_count > 0) {
401
+ clearInterval(timer);
402
+ clearTimeout(overallTimeout);
403
+ const winner = result.options.reduce((a, b) => b.voter_count > a.voter_count ? b : a);
404
+ resolve(winner.text);
405
+ return;
406
+ }
407
+ // No votes — poll is now closed. Re-send once.
408
+ if (!resent) {
409
+ resent = true;
410
+ pollMessageId = await this.telegramSendPoll(botToken, chatId, question, options);
411
+ }
412
+ else {
413
+ // Already resent — stop checking, wait for timeout
414
+ clearInterval(timer);
415
+ }
416
+ }
417
+ catch {
418
+ // stopPoll failed — ignore
419
+ }
420
+ }, CHECK_INTERVAL_MS);
421
+ });
422
+ }
423
+ async telegramSendPoll(botToken, chatId, question, options) {
424
+ const resp = await fetch(`https://api.telegram.org/bot${botToken}/sendPoll`, {
425
+ method: 'POST',
426
+ headers: { 'Content-Type': 'application/json' },
427
+ body: JSON.stringify({
428
+ chat_id: chatId,
429
+ question: `[Astro] ${question}`,
430
+ options: JSON.stringify(options),
431
+ is_anonymous: false,
432
+ }),
433
+ });
434
+ const data = await resp.json();
435
+ return data.ok ? data.result?.message_id ?? null : null;
436
+ }
437
+ // ─── Telegram Bot API Helpers ──────────────────────────────────────
438
+ async telegramStopPoll(botToken, chatId, messageId) {
439
+ const resp = await fetch(`https://api.telegram.org/bot${botToken}/stopPoll`, {
440
+ method: 'POST',
441
+ headers: { 'Content-Type': 'application/json' },
442
+ body: JSON.stringify({ chat_id: chatId, message_id: messageId }),
443
+ });
444
+ const data = await resp.json();
445
+ return data.ok ? data.result ?? null : null;
446
+ }
447
+ getNotificationPrefix(type) {
448
+ switch (type) {
449
+ case 'task.completed': return '[Completed]';
450
+ case 'task.failed': return '[Failed]';
451
+ case 'approval.requested': return '[Approval Needed]';
452
+ case 'branch.pruned': return '[Pruned]';
453
+ default: return '[Astro]';
454
+ }
455
+ }
456
+ }
457
+ //# sourceMappingURL=openclaw-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-bridge.js","sourceRoot":"","sources":["../../src/lib/openclaw-bridge.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/lib/providers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAuC,MAAM,aAAa,CAAC;AAqhBnG;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CA4C/D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAGlF;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAG9E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAIjE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,MAAM,CAaxE"}
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/lib/providers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAuC,MAAM,aAAa,CAAC;AAugBnG;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CA4C/D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAGlF;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAG9E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAIjE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,MAAM,CAaxE"}
@@ -6,6 +6,7 @@ import { promisify } from 'node:util';
6
6
  import { access, constants, readFile } from 'node:fs/promises';
7
7
  import { join } from 'node:path';
8
8
  import { homedir } from 'node:os';
9
+ import WebSocket from 'ws';
9
10
  import { detectSlurm } from './slurm-detect.js';
10
11
  const execAsync = promisify(exec);
11
12
  /**
@@ -261,76 +262,68 @@ async function detectCodex() {
261
262
  return null;
262
263
  }
263
264
  /**
264
- * Common installation paths for OpenClaw
265
+ * Quick probe: connect to a WebSocket URL and check for connect.challenge.
266
+ * Does NOT perform a full handshake — just confirms the gateway is reachable.
265
267
  */
266
- function getOpenClawPaths() {
267
- const home = homedir();
268
- const platform = process.platform;
269
- const paths = [];
270
- // npm/pnpm global installs
271
- paths.push(join(home, '.npm', 'bin', 'openclaw'));
272
- paths.push(join(home, '.npm-global', 'bin', 'openclaw'));
273
- paths.push(join(home, '.local', 'bin', 'openclaw'));
274
- paths.push(join(home, '.yarn', 'bin', 'openclaw'));
275
- paths.push(join(home, '.pnpm-global', 'bin', 'openclaw'));
276
- if (platform === 'darwin') {
277
- paths.push('/usr/local/bin/openclaw');
278
- paths.push('/opt/homebrew/bin/openclaw');
279
- }
280
- else if (platform === 'win32') {
281
- const appData = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
282
- paths.push(join(appData, 'npm', 'openclaw.cmd'));
283
- paths.push(join(appData, 'npm', 'openclaw'));
284
- }
285
- else {
286
- paths.push('/usr/local/bin/openclaw');
287
- paths.push('/usr/bin/openclaw');
288
- }
289
- return paths;
268
+ function probeGatewayReachable(url) {
269
+ return new Promise((resolve) => {
270
+ let ws;
271
+ const timeout = setTimeout(() => { ws?.removeAllListeners(); ws?.close(); resolve(false); }, 5000);
272
+ ws = new WebSocket(url);
273
+ ws.on('message', (data) => {
274
+ try {
275
+ const frame = JSON.parse(String(data));
276
+ if (frame.type === 'event' && frame.event === 'connect.challenge') {
277
+ clearTimeout(timeout);
278
+ ws.removeAllListeners();
279
+ ws.close();
280
+ resolve(true);
281
+ }
282
+ }
283
+ catch { /* ignore */ }
284
+ });
285
+ ws.on('error', () => { clearTimeout(timeout); ws?.removeAllListeners(); resolve(false); });
286
+ ws.on('close', () => { clearTimeout(timeout); resolve(false); });
287
+ });
290
288
  }
291
289
  /**
292
- * Detect OpenClaw CLI installation
290
+ * Detect OpenClaw gateway availability.
291
+ *
292
+ * Reads ~/.openclaw/openclaw.json for gateway port + auth token,
293
+ * then probes ws://127.0.0.1:{port} for a connect.challenge event.
294
+ * The adapter itself handles the full handshake at execution time.
293
295
  */
294
296
  async function detectOpenClaw() {
295
- const exists = await commandExists('openclaw');
296
- if (exists) {
297
- const path = await getCommandPath('openclaw');
298
- const version = await getCommandVersion('openclaw', '--version');
297
+ try {
298
+ const configPath = join(homedir(), '.openclaw', 'openclaw.json');
299
+ const raw = JSON.parse(await readFile(configPath, 'utf-8'));
300
+ const port = raw?.gateway?.port;
301
+ if (!port)
302
+ return null;
303
+ const bind = raw?.gateway?.bind || '127.0.0.1';
304
+ const host = bind === 'loopback' || bind === '127.0.0.1' ? '127.0.0.1' : bind;
305
+ const url = `ws://${host}:${port}`;
306
+ // Quick probe — just check for connect.challenge (no full handshake)
307
+ const reachable = await probeGatewayReachable(url);
308
+ if (!reachable)
309
+ return null;
299
310
  return {
300
311
  type: 'openclaw',
301
312
  name: 'OpenClaw',
302
- version,
303
- path: path ?? 'openclaw',
313
+ version: null,
314
+ path: url,
304
315
  available: true,
305
316
  capabilities: {
306
317
  streaming: true,
307
318
  tools: true,
308
319
  multiTurn: true,
309
- maxConcurrentTasks: 1,
320
+ maxConcurrentTasks: 10,
310
321
  },
311
322
  };
312
323
  }
313
- const commonPaths = getOpenClawPaths();
314
- for (const clawPath of commonPaths) {
315
- const isExecutable = await fileExecutable(clawPath);
316
- if (isExecutable) {
317
- const version = await getCommandVersion(clawPath, '--version');
318
- return {
319
- type: 'openclaw',
320
- name: 'OpenClaw',
321
- version,
322
- path: clawPath,
323
- available: true,
324
- capabilities: {
325
- streaming: true,
326
- tools: true,
327
- multiTurn: true,
328
- maxConcurrentTasks: 1,
329
- },
330
- };
331
- }
324
+ catch {
325
+ return null;
332
326
  }
333
- return null;
334
327
  }
335
328
  /**
336
329
  * Common installation paths for OpenCode