openclaw-overlay-plugin 0.7.30 → 0.7.32

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 (140) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +1408 -0
  3. package/dist/src/cli-main.d.ts +7 -0
  4. package/dist/src/cli-main.js +192 -0
  5. package/dist/src/cli.d.ts +8 -0
  6. package/dist/src/cli.js +14 -0
  7. package/dist/src/core/config.d.ts +11 -0
  8. package/dist/src/core/config.js +13 -0
  9. package/dist/src/core/index.d.ts +25 -0
  10. package/dist/src/core/index.js +26 -0
  11. package/dist/src/core/payment.d.ts +16 -0
  12. package/dist/src/core/payment.js +94 -0
  13. package/dist/src/core/types.d.ts +94 -0
  14. package/dist/src/core/types.js +4 -0
  15. package/dist/src/core/verify.d.ts +28 -0
  16. package/dist/src/core/verify.js +104 -0
  17. package/dist/src/core/wallet.d.ts +99 -0
  18. package/dist/src/core/wallet.js +220 -0
  19. package/dist/src/scripts/baemail/commands.d.ts +64 -0
  20. package/dist/src/scripts/baemail/commands.js +259 -0
  21. package/dist/src/scripts/baemail/handler.d.ts +36 -0
  22. package/dist/src/scripts/baemail/handler.js +284 -0
  23. package/dist/src/scripts/baemail/index.d.ts +5 -0
  24. package/dist/src/scripts/baemail/index.js +5 -0
  25. package/dist/src/scripts/config.d.ts +48 -0
  26. package/dist/src/scripts/config.js +68 -0
  27. package/dist/src/scripts/index.d.ts +7 -0
  28. package/dist/src/scripts/index.js +7 -0
  29. package/dist/src/scripts/messaging/connect.d.ts +8 -0
  30. package/dist/src/scripts/messaging/connect.js +114 -0
  31. package/dist/src/scripts/messaging/handlers.d.ts +21 -0
  32. package/dist/src/scripts/messaging/handlers.js +334 -0
  33. package/dist/src/scripts/messaging/inbox.d.ts +11 -0
  34. package/dist/src/scripts/messaging/inbox.js +51 -0
  35. package/dist/src/scripts/messaging/index.d.ts +8 -0
  36. package/dist/src/scripts/messaging/index.js +8 -0
  37. package/dist/src/scripts/messaging/poll.d.ts +7 -0
  38. package/dist/src/scripts/messaging/poll.js +52 -0
  39. package/dist/src/scripts/messaging/send.d.ts +7 -0
  40. package/dist/src/scripts/messaging/send.js +43 -0
  41. package/dist/src/scripts/output.d.ts +12 -0
  42. package/dist/src/scripts/output.js +19 -0
  43. package/dist/src/scripts/overlay/discover.d.ts +7 -0
  44. package/dist/src/scripts/overlay/discover.js +72 -0
  45. package/dist/src/scripts/overlay/index.d.ts +7 -0
  46. package/dist/src/scripts/overlay/index.js +7 -0
  47. package/dist/src/scripts/overlay/registration.d.ts +19 -0
  48. package/dist/src/scripts/overlay/registration.js +176 -0
  49. package/dist/src/scripts/overlay/services.d.ts +29 -0
  50. package/dist/src/scripts/overlay/services.js +167 -0
  51. package/dist/src/scripts/overlay/transaction.d.ts +42 -0
  52. package/dist/src/scripts/overlay/transaction.js +103 -0
  53. package/dist/src/scripts/payment/build.d.ts +24 -0
  54. package/dist/src/scripts/payment/build.js +54 -0
  55. package/dist/src/scripts/payment/commands.d.ts +15 -0
  56. package/dist/src/scripts/payment/commands.js +73 -0
  57. package/dist/src/scripts/payment/index.d.ts +6 -0
  58. package/dist/src/scripts/payment/index.js +6 -0
  59. package/dist/src/scripts/payment/types.d.ts +56 -0
  60. package/dist/src/scripts/payment/types.js +4 -0
  61. package/dist/src/scripts/services/index.d.ts +6 -0
  62. package/dist/src/scripts/services/index.js +6 -0
  63. package/dist/src/scripts/services/queue.d.ts +11 -0
  64. package/dist/src/scripts/services/queue.js +28 -0
  65. package/dist/src/scripts/services/request.d.ts +7 -0
  66. package/dist/src/scripts/services/request.js +82 -0
  67. package/dist/src/scripts/services/respond.d.ts +11 -0
  68. package/dist/src/scripts/services/respond.js +132 -0
  69. package/dist/src/scripts/types.d.ts +107 -0
  70. package/dist/src/scripts/types.js +4 -0
  71. package/dist/src/scripts/utils/index.d.ts +6 -0
  72. package/dist/src/scripts/utils/index.js +6 -0
  73. package/dist/src/scripts/utils/merkle.d.ts +12 -0
  74. package/dist/src/scripts/utils/merkle.js +47 -0
  75. package/dist/src/scripts/utils/storage.d.ts +66 -0
  76. package/dist/src/scripts/utils/storage.js +211 -0
  77. package/dist/src/scripts/utils/woc.d.ts +26 -0
  78. package/dist/src/scripts/utils/woc.js +91 -0
  79. package/dist/src/scripts/wallet/balance.d.ts +22 -0
  80. package/dist/src/scripts/wallet/balance.js +240 -0
  81. package/dist/src/scripts/wallet/identity.d.ts +70 -0
  82. package/dist/src/scripts/wallet/identity.js +151 -0
  83. package/dist/src/scripts/wallet/index.d.ts +6 -0
  84. package/dist/src/scripts/wallet/index.js +6 -0
  85. package/dist/src/scripts/wallet/setup.d.ts +15 -0
  86. package/dist/src/scripts/wallet/setup.js +105 -0
  87. package/dist/src/scripts/x-verification/commands.d.ts +27 -0
  88. package/dist/src/scripts/x-verification/commands.js +222 -0
  89. package/dist/src/scripts/x-verification/index.d.ts +4 -0
  90. package/dist/src/scripts/x-verification/index.js +4 -0
  91. package/dist/src/services/built-in/api-proxy/index.d.ts +6 -0
  92. package/dist/src/services/built-in/api-proxy/index.js +23 -0
  93. package/dist/src/services/built-in/code-develop/index.d.ts +6 -0
  94. package/dist/src/services/built-in/code-develop/index.js +23 -0
  95. package/dist/src/services/built-in/code-review/index.d.ts +10 -0
  96. package/dist/src/services/built-in/code-review/index.js +51 -0
  97. package/dist/src/services/built-in/image-analysis/index.d.ts +6 -0
  98. package/dist/src/services/built-in/image-analysis/index.js +33 -0
  99. package/dist/src/services/built-in/memory-store/index.d.ts +6 -0
  100. package/dist/src/services/built-in/memory-store/index.js +22 -0
  101. package/dist/src/services/built-in/roulette/index.d.ts +6 -0
  102. package/dist/src/services/built-in/roulette/index.js +27 -0
  103. package/dist/src/services/built-in/summarize/index.d.ts +6 -0
  104. package/dist/src/services/built-in/summarize/index.js +21 -0
  105. package/dist/src/services/built-in/tell-joke/handler.d.ts +7 -0
  106. package/dist/src/services/built-in/tell-joke/handler.js +122 -0
  107. package/dist/src/services/built-in/tell-joke/index.d.ts +9 -0
  108. package/dist/src/services/built-in/tell-joke/index.js +31 -0
  109. package/dist/src/services/built-in/translate/index.d.ts +6 -0
  110. package/dist/src/services/built-in/translate/index.js +21 -0
  111. package/dist/src/services/built-in/web-research/index.d.ts +9 -0
  112. package/dist/src/services/built-in/web-research/index.js +51 -0
  113. package/dist/src/services/index.d.ts +13 -0
  114. package/dist/src/services/index.js +14 -0
  115. package/dist/src/services/loader.d.ts +77 -0
  116. package/dist/src/services/loader.js +292 -0
  117. package/dist/src/services/manager.d.ts +86 -0
  118. package/dist/src/services/manager.js +255 -0
  119. package/dist/src/services/registry.d.ts +98 -0
  120. package/dist/src/services/registry.js +204 -0
  121. package/dist/src/services/types.d.ts +230 -0
  122. package/dist/src/services/types.js +30 -0
  123. package/dist/src/test/cli.test.d.ts +7 -0
  124. package/dist/src/test/cli.test.js +329 -0
  125. package/dist/src/test/comprehensive-overlay.test.d.ts +13 -0
  126. package/dist/src/test/comprehensive-overlay.test.js +593 -0
  127. package/dist/src/test/key-derivation.test.d.ts +12 -0
  128. package/dist/src/test/key-derivation.test.js +86 -0
  129. package/dist/src/test/overlay-submit.test.d.ts +10 -0
  130. package/dist/src/test/overlay-submit.test.js +460 -0
  131. package/dist/src/test/request-response-flow.test.d.ts +5 -0
  132. package/dist/src/test/request-response-flow.test.js +209 -0
  133. package/dist/src/test/service-system.test.d.ts +5 -0
  134. package/dist/src/test/service-system.test.js +190 -0
  135. package/dist/src/test/utils/server-logic.d.ts +98 -0
  136. package/dist/src/test/utils/server-logic.js +286 -0
  137. package/dist/src/test/wallet.test.d.ts +7 -0
  138. package/dist/src/test/wallet.test.js +146 -0
  139. package/index.ts +260 -633
  140. package/package.json +2 -3
package/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { execFile, spawn, ChildProcess } from 'node:child_process';
2
2
  import { promisify } from 'node:util';
3
3
  import path from 'node:path';
4
+ import os from 'node:os';
4
5
  import { fileURLToPath } from 'node:url';
5
6
  import fs from 'node:fs';
6
7
  import { initializeServiceSystem, serviceManager } from './src/services/index.js';
@@ -50,7 +51,7 @@ function loadDailySpending(walletDir: string): DailySpending {
50
51
  return { date: today, totalSats: 0, transactions: [] };
51
52
  }
52
53
 
53
- function writeActivityEvent(event) {
54
+ function writeActivityEvent(event: any) {
54
55
  const alertDir = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay');
55
56
  try {
56
57
  fs.mkdirSync(alertDir, { recursive: true });
@@ -75,7 +76,7 @@ function checkBudget(walletDir: string, requestedSats: number, dailyLimit: numbe
75
76
  };
76
77
  }
77
78
 
78
- async function startAutoImport(env, cliPath, logger) {
79
+ async function startAutoImport(env: any, cliPath: string, logger: any) {
79
80
  // Get our address
80
81
  try {
81
82
  const addrResult = await execFileAsync('node', [cliPath, 'address'], { env });
@@ -138,7 +139,7 @@ async function startAutoImport(env, cliPath, logger) {
138
139
  await autoAdvertiseServices(env, cliPath, logger);
139
140
  }
140
141
  }
141
- } catch (err) {
142
+ } catch (err: any) {
142
143
  logger?.warn?.('[bsv-overlay] Auto-registration failed:', err.message);
143
144
  }
144
145
  }
@@ -151,7 +152,7 @@ async function startAutoImport(env, cliPath, logger) {
151
152
  // WoC API error — just skip this cycle
152
153
  }
153
154
  }, 30000); // Check every 30 seconds for faster onboarding
154
- } catch (err) {
155
+ } catch (err: any) {
155
156
  logger?.warn?.('[bsv-overlay] Auto-import setup failed:', err.message);
156
157
  }
157
158
  }
@@ -164,7 +165,7 @@ function stopAutoImport() {
164
165
  }
165
166
 
166
167
  // Auto-advertise services from config after registration
167
- async function autoAdvertiseServices(env, cliPath, logger) {
168
+ async function autoAdvertiseServices(env: any, cliPath: string, logger: any) {
168
169
  try {
169
170
  // Read config to get services list
170
171
  const configPaths = [
@@ -199,154 +200,54 @@ async function autoAdvertiseServices(env, cliPath, logger) {
199
200
  for (const serviceId of servicesToAdvertise) {
200
201
  const serviceInfo = serviceManager.registry.get(serviceId);
201
202
  if (!serviceInfo) {
202
- logger?.warn?.(`[bsv-overlay] Unknown service ID: ${serviceId}. Skipping.`);
203
203
  failed.push(serviceId);
204
204
  continue;
205
205
  }
206
-
206
+
207
207
  try {
208
- const result = await execFileAsync('node', [
209
- cliPath, 'advertise',
210
- serviceId,
211
- serviceInfo.name,
212
- serviceInfo.defaultPrice.toString(),
213
- serviceInfo.description
208
+ await execFileAsync('node', [
209
+ cliPath, 'advertise', serviceId, serviceInfo.name, serviceInfo.description, String(serviceInfo.defaultPrice)
214
210
  ], { env, timeout: 60000 });
215
-
216
- const output = parseCliOutput(result.stdout);
217
- if (output.success) {
218
- advertised.push(serviceId);
219
- logger?.info?.(`[bsv-overlay] Advertised service: ${serviceInfo.name} (${serviceId}) for ${serviceInfo.defaultPrice} sats`);
220
- } else {
221
- failed.push(serviceId);
222
- logger?.warn?.(`[bsv-overlay] Failed to advertise ${serviceId}: ${output.error}`);
223
- }
224
- } catch (err: any) {
211
+ advertised.push(serviceId);
212
+ } catch {
225
213
  failed.push(serviceId);
226
- logger?.warn?.(`[bsv-overlay] Error advertising ${serviceId}: ${err.message}`);
227
214
  }
228
215
  }
229
216
 
230
- // Wake agent with results
231
- if (advertised.length > 0) {
232
- const serviceList = advertised.map(id => {
233
- const info = serviceManager.registry.get(id);
234
- return `• ${info?.name || id} (${info?.defaultPrice || '?'} sats)`;
235
- }).join('\n');
236
-
237
- wakeAgent(
238
- `🎉 **Services Auto-Advertised!**\n\nThe following services are now live on the overlay network:\n\n${serviceList}\n\n${failed.length > 0 ? `⚠️ Failed to advertise: ${failed.join(', ')}` : ''}`,
239
- logger,
240
- { sessionKey: 'hook:bsv-overlay:services' }
241
- );
242
- }
243
- } catch (err: any) {
244
- logger?.warn?.(`[bsv-overlay] Auto-advertise failed: ${err.message}`);
245
- }
246
- }
247
-
248
- // Auto-enable hooks in OpenClaw config if not already configured.
249
- // Returns true if config was modified (gateway restart needed to activate).
250
- function autoEnableHooks(api: any): boolean {
251
- try {
252
- const configPaths = [
253
- path.join(process.env.HOME || '', '.openclaw', 'openclaw.json'),
254
- path.join(process.env.HOME || '', '.openclaw', 'openclaw.json'),
255
- ];
256
-
257
- for (const configPath of configPaths) {
258
- if (!fs.existsSync(configPath)) continue;
259
-
260
- const raw = fs.readFileSync(configPath, 'utf-8');
261
- const config = JSON.parse(raw);
262
-
263
- // Check if hooks are already enabled with a token
264
- if (config?.hooks?.enabled && config?.hooks?.token) {
265
- api?.log?.debug?.('[bsv-overlay] Hooks already configured.');
266
- return false;
267
- }
268
-
269
- // Generate a random token
270
- const tokenBytes = new Uint8Array(24);
271
- for (let i = 0; i < 24; i++) tokenBytes[i] = Math.floor(Math.random() * 256);
272
- const token = Array.from(tokenBytes).map(b => b.toString(16).padStart(2, '0')).join('');
273
-
274
- // Merge hooks config — preserve existing hooks.internal etc.
275
- config.hooks = {
276
- ...config.hooks,
277
- enabled: true,
278
- token: config.hooks?.token || token,
279
- };
280
-
281
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
282
- api?.log?.info?.(`[bsv-overlay] Auto-enabled hooks in config (${configPath}). Gateway restart needed to activate.`);
283
- return true;
284
- }
217
+ if (advertised.length > 0) logger?.info?.(`[bsv-overlay] Successfully advertised: ${advertised.join(', ')}`);
218
+ if (failed.length > 0) logger?.warn?.(`[bsv-overlay] Failed to advertise: ${failed.join(', ')}`);
219
+
285
220
  } catch (err: any) {
286
- api?.log?.warn?.(`[bsv-overlay] Failed to auto-enable hooks: ${err.message}`);
221
+ logger?.warn?.('[bsv-overlay] Auto-advertising failed:', err.message);
287
222
  }
288
- return false;
289
223
  }
290
224
 
291
- // Discover the gateway HTTP port from environment
292
- function getGatewayPort(): string {
293
- return process.env.OPENCLAW_GATEWAY_PORT || process.env.OPENCLAW_GATEWAY_PORT || '18789';
294
- }
295
-
296
- // Read tokens from env vars or config files.
297
- // Returns { hooksToken, gatewayToken } — hooksToken is preferred for HTTP wake.
298
- function getTokens(): { hooksToken: string | null; gatewayToken: string | null } {
299
- let hooksToken: string | null = process.env.OPENCLAW_HOOKS_TOKEN || process.env.OPENCLAW_HOOKS_TOKEN || null;
300
- let gatewayToken: string | null = process.env.OPENCLAW_GATEWAY_TOKEN || process.env.OPENCLAW_GATEWAY_TOKEN || null;
301
-
302
- try {
303
- const configPaths = [
304
- path.join(process.env.HOME || '', '.openclaw', 'openclaw.json'),
305
- path.join(process.env.HOME || '', '.openclaw', 'openclaw.json'),
306
- ];
307
- for (const p of configPaths) {
308
- if (!fs.existsSync(p)) continue;
309
- const config = JSON.parse(fs.readFileSync(p, 'utf-8'));
310
- if (!hooksToken) hooksToken = config?.hooks?.token || null;
311
- if (!gatewayToken) gatewayToken = config?.gateway?.auth?.token || null;
312
- if (hooksToken && gatewayToken) break;
313
- }
314
- } catch {}
315
- return { hooksToken, gatewayToken };
316
- }
317
-
318
- // Wake the agent via /hooks/agent — runs an isolated agent turn with the
319
- // message as the actual prompt, so the agent sees the request and can act.
320
- // NOTE: /hooks/wake only triggers a heartbeat (reads HEARTBEAT.md) which
321
- // won't surface the overlay request to the agent. /hooks/agent is required.
322
- function wakeAgent(text: string, logger?: any, opts?: { sessionKey?: string }) {
323
- const { hooksToken, gatewayToken } = getTokens();
324
- const port = getGatewayPort();
325
- const httpToken = hooksToken || gatewayToken;
326
-
225
+ /**
226
+ * Wake the agent by calling the /hooks/agent endpoint.
227
+ * This is the standard way to invoke an agent with a specific context.
228
+ */
229
+ function wakeAgent(text: string, logger: any, options: { sessionKey?: string } = {}) {
230
+ const sessionKey = options.sessionKey || `hook:bsv-overlay:${Date.now()}`;
231
+ const gatewayPort = getGatewayPort();
232
+ const httpToken = getHooksToken();
233
+
327
234
  if (!httpToken) {
328
- logger?.warn?.('[bsv-overlay] No gateway/hooks token available — cannot invoke agent');
235
+ logger?.warn?.('[bsv-overlay] Skipped wakeAgent: OPENCLAW_HOOKS_TOKEN not set');
329
236
  return;
330
237
  }
331
238
 
332
- const url = `http://127.0.0.1:${port}/hooks/agent`;
333
- const sessionKey = opts?.sessionKey || `hook:bsv-overlay:${Date.now()}`;
334
-
239
+ const url = `http://localhost:${gatewayPort}/hooks/agent`;
240
+
335
241
  fetch(url, {
336
242
  method: 'POST',
337
243
  headers: {
338
244
  'Content-Type': 'application/json',
339
- 'Authorization': `Bearer ${httpToken}`,
340
245
  'x-openclaw-token': httpToken,
341
246
  },
342
247
  body: JSON.stringify({
343
- message: text,
344
- name: 'BSV Overlay',
248
+ prompt: text,
345
249
  sessionKey,
346
- wakeMode: 'now',
347
- deliver: true,
348
- channel: 'last',
349
- }),
250
+ })
350
251
  })
351
252
  .then(async (res) => {
352
253
  if (res.ok) {
@@ -356,17 +257,33 @@ function wakeAgent(text: string, logger?: any, opts?: { sessionKey?: string }) {
356
257
  logger?.warn?.(`[bsv-overlay] /hooks/agent failed: ${res.status} ${body}`);
357
258
  }
358
259
  })
359
- .catch((err) => {
260
+ .catch((err: any) => {
360
261
  logger?.warn?.('[bsv-overlay] /hooks/agent error:', err.message);
361
262
  });
362
263
  }
363
264
 
364
- // NOTE: WebSocket wake fallback removed — it used cron.wake which triggers
365
- // a heartbeat (same problem as /hooks/wake). /hooks/agent is the correct
366
- // approach for invoking the agent with a specific prompt.
265
+ function getGatewayPort(): string {
266
+ return process.env.OPENCLAW_GATEWAY_PORT || '18789';
267
+ }
268
+
269
+ function getHooksToken(): string | null {
270
+ let hooksToken: string | null = process.env.OPENCLAW_HOOKS_TOKEN || null;
271
+
272
+ if (!hooksToken) {
273
+ try {
274
+ const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
275
+ if (fs.existsSync(configPath)) {
276
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
277
+ hooksToken = config.gateway?.hooksToken || null;
278
+ }
279
+ } catch {}
280
+ }
281
+
282
+ return hooksToken;
283
+ }
367
284
 
368
285
  // Categorize WebSocket events into notification types
369
- function categorizeEvent(event) {
286
+ function categorizeEvent(event: any) {
370
287
  const base = { ts: Date.now(), from: event.from?.slice(0, 16), fullFrom: event.from };
371
288
 
372
289
  // 💰 Incoming payment — someone paid us for a service
@@ -398,7 +315,7 @@ function categorizeEvent(event) {
398
315
  return null;
399
316
  }
400
317
 
401
- function startBackgroundService(env, cliPath, logger) {
318
+ function startBackgroundService(env: any, cliPath: string, logger: any) {
402
319
  if (backgroundProcess) return;
403
320
  serviceRunning = true;
404
321
 
@@ -413,7 +330,7 @@ function startBackgroundService(env, cliPath, logger) {
413
330
  const { cleanupServiceQueue } = await import('./src/scripts/utils/storage.js');
414
331
  cleanupServiceQueue();
415
332
  logger?.debug?.('[bsv-overlay] Cleaned up old queue entries');
416
- } catch (err) {
333
+ } catch (err: any) {
417
334
  logger?.warn?.('[bsv-overlay] Queue cleanup failed:', err.message);
418
335
  }
419
336
  }
@@ -530,7 +447,7 @@ function stopBackgroundService() {
530
447
  stopAutoImport();
531
448
  }
532
449
 
533
- export default function register(api) {
450
+ export default function register(api: any) {
534
451
  // Capture config at registration time (handle both flat and nested structures)
535
452
  const entry = api.getConfig?.()?.plugins?.entries?.['openclaw-overlay'] || {};
536
453
  const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
@@ -559,48 +476,47 @@ export default function register(api) {
559
476
  },
560
477
  input: {
561
478
  type: "object",
562
- description: "Service-specific input data"
563
- },
564
- maxPrice: {
565
- type: "number",
566
- description: "Max sats willing to pay"
479
+ description: "JSON input for the service request"
567
480
  },
568
481
  identityKey: {
569
482
  type: "string",
570
- description: "Target agent key for direct pay/send"
483
+ description: "Target identity public key (for pay/request/send)"
484
+ },
485
+ messageType: {
486
+ type: "string",
487
+ description: "Type of message to send"
488
+ },
489
+ payload: {
490
+ type: "object",
491
+ description: "JSON payload for message send"
571
492
  },
572
493
  sats: {
573
494
  type: "number",
574
- description: "Amount for direct pay"
495
+ description: "Amount in satoshis for payment"
575
496
  },
576
497
  description: {
577
- type: "string"
578
- },
579
- agent: {
580
498
  type: "string",
581
- description: "Agent name filter for discover"
499
+ description: "Payment description"
582
500
  },
583
- // Import parameters
584
501
  txid: {
585
502
  type: "string",
586
- description: "Transaction ID for import"
503
+ description: "Transaction ID to import"
587
504
  },
588
505
  vout: {
589
506
  type: "number",
590
- description: "Output index for import (optional)"
507
+ description: "Output index to import"
591
508
  },
592
- // Service management parameters
593
- serviceId: {
594
- type: "string",
595
- description: "Service ID for advertise/readvertise/remove"
509
+ priceSats: {
510
+ type: "number",
511
+ description: "Price in satoshis for service advertisement"
596
512
  },
597
513
  name: {
598
514
  type: "string",
599
- description: "Service name for advertise/readvertise"
515
+ description: "Service name"
600
516
  },
601
- priceSats: {
517
+ price: {
602
518
  type: "number",
603
- description: "Price in satoshis for advertise"
519
+ description: "Price for service request"
604
520
  },
605
521
  newPrice: {
606
522
  type: "number",
@@ -608,554 +524,265 @@ export default function register(api) {
608
524
  },
609
525
  newName: {
610
526
  type: "string",
611
- description: "New name for readvertise (optional)"
527
+ description: "New name for readvertise"
612
528
  },
613
529
  newDesc: {
614
530
  type: "string",
615
- description: "New description for readvertise (optional)"
531
+ description: "New description for readvertise"
616
532
  },
617
- // Messaging parameters
618
- messageType: {
619
- type: "string",
620
- description: "Message type for send"
621
- },
622
- payload: {
623
- type: "object",
624
- description: "Message payload for send"
625
- },
626
- // Refund parameters
627
533
  address: {
628
534
  type: "string",
629
535
  description: "Destination address for refund"
630
536
  },
631
- // Confirmation token for destructive actions (unregister, remove-service)
632
- confirmToken: {
537
+ agentName: {
633
538
  type: "string",
634
- description: "Confirmation token from a previous preview call — required to execute destructive actions"
539
+ description: "Agent display name for onboard/register"
540
+ },
541
+ agentDescription: {
542
+ type: "string",
543
+ description: "Agent description for onboard/register"
544
+ },
545
+ maxPrice: {
546
+ type: "number",
547
+ description: "Max satoshis allowed for request without confirmation"
635
548
  },
636
- // Fulfill parameters
637
549
  requestId: {
638
550
  type: "string",
639
- description: "Request ID for fulfill"
551
+ description: "ID of the service request to fulfill"
640
552
  },
641
553
  recipientKey: {
642
554
  type: "string",
643
555
  description: "Recipient identity key for fulfill"
644
556
  },
557
+ serviceId: {
558
+ type: "string",
559
+ description: "Service ID for fulfill/remove-service"
560
+ },
645
561
  result: {
646
562
  type: "object",
647
- description: "Service result for fulfill"
648
- },
649
- // Onboard parameters
650
- agentName: {
651
- type: "string",
652
- description: "Agent display name for onboard/register"
563
+ description: "Result data for service fulfillment"
653
564
  },
654
- agentDescription: {
565
+ confirmToken: {
655
566
  type: "string",
656
- description: "Agent description for onboard/register"
567
+ description: "Confirmation token for destructive actions (unregister, remove-service)"
657
568
  }
658
569
  },
659
570
  required: ["action"]
660
571
  },
661
- async execute(id, params) {
662
- const config = pluginConfig;
663
-
572
+ async execute(_id: string, params: any) {
664
573
  try {
665
- const result = await executeOverlayAction(params, config, api);
666
- return {
667
- content: [{
668
- type: "text",
669
- text: typeof result === 'string' ? result : JSON.stringify(result, null, 2)
670
- }]
671
- };
672
- } catch (error) {
673
- return {
674
- content: [{
675
- type: "text",
676
- text: `Error: ${error.message}`
677
- }]
574
+ return await executeOverlayAction(params, pluginConfig, api);
575
+ } catch (error: any) {
576
+ return {
577
+ content: [{
578
+ type: "text",
579
+ text: `Error: ${error.message}`
580
+ }]
678
581
  };
679
582
  }
680
583
  }
681
584
  });
682
585
 
683
- // Register background service for WebSocket relay
586
+ // Register background relay service
684
587
  api.registerService({
685
588
  id: "bsv-overlay-relay",
686
589
  start: async () => {
687
- api.logger.info("Starting BSV overlay WebSocket relay...");
688
590
  try {
689
- const config = pluginConfig;
690
- const env = buildEnvironment(config);
591
+ api.logger.info("Starting BSV overlay WebSocket relay...");
592
+ const env = buildEnvironment(pluginConfig);
691
593
  const cliPath = path.join(__dirname, 'dist', 'cli.js');
692
594
 
693
- // Use the improved background service
595
+ // Initialize the service system if available
596
+ try {
597
+ await initializeServiceSystem();
598
+ } catch {}
599
+
694
600
  startBackgroundService(env, cliPath, api.logger);
695
601
 
696
602
  // Start auto-import
697
603
  startAutoImport(env, cliPath, api.logger);
698
604
 
699
605
  api.logger.info("BSV overlay WebSocket relay started");
700
- } catch (error) {
606
+ } catch (error: any) {
701
607
  api.logger.error(`Failed to start BSV overlay relay: ${error.message}`);
702
608
  }
703
609
  },
704
610
  stop: async () => {
705
611
  api.logger.info("Stopping BSV overlay WebSocket relay...");
706
612
  stopBackgroundService();
707
- api.logger.info("BSV overlay WebSocket relay stopped");
708
613
  }
709
614
  });
710
615
 
711
- // Register /overlay auto-reply command for instant status
712
- api.registerCommand?.({
713
- name: 'overlay',
714
- description: 'Check BSV Overlay Network status instantly',
715
- handler: async (ctx) => {
716
- try {
717
- const config = pluginConfig;
718
- const env = buildEnvironment(config);
719
- const cliPath = path.join(__dirname, 'dist', 'cli.js');
720
-
721
- // Check registration status
722
- const regPath = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'registration.json');
723
- const isRegistered = fs.existsSync(regPath);
724
-
725
- // Get balance
726
- let balance = 0;
727
- let address = '';
728
- try {
729
- const balResult = await execFileAsync('node', [cliPath, 'balance'], { env, timeout: 15000 });
730
- const balOutput = parseCliOutput(balResult.stdout);
731
- balance = balOutput?.data?.walletBalance || 0;
732
- } catch {}
733
-
616
+ // Register a skill-style wake handler
617
+ api.registerHook({
618
+ id: "bsv-overlay-wake",
619
+ event: "gateway:start",
620
+ handler: async (ctx: any) => {
621
+ // Auto-check for registration on startup
622
+ (async () => {
734
623
  try {
735
- const addrResult = await execFileAsync('node', [cliPath, 'address'], { env, timeout: 15000 });
736
- const addrOutput = parseCliOutput(addrResult.stdout);
737
- address = addrOutput?.data?.address || '';
738
- } catch {}
739
-
740
- // Get services count
741
- let servicesCount = 0;
742
- try {
743
- const svcResult = await execFileAsync('node', [cliPath, 'services'], { env, timeout: 15000 });
744
- const svcOutput = parseCliOutput(svcResult.stdout);
745
- servicesCount = svcOutput?.data?.count || 0;
746
- } catch {}
747
-
748
- // Build status message
749
- let text = '**BSV Overlay Status**\n\n';
750
-
751
- if (isRegistered) {
752
- const reg = JSON.parse(fs.readFileSync(regPath, 'utf-8'));
753
- text += `✅ **Registered** as ${reg.agentName || 'Agent'}\n`;
754
- text += `💰 **Balance:** ${balance.toLocaleString()} sats\n`;
755
- text += `📋 **Services:** ${servicesCount} advertised\n`;
756
- text += `🌐 **Network:** ${config?.overlayUrl || 'https://clawoverlay.com'}`;
757
- } else if (balance >= 1000) {
758
- text += `💰 **Funded** (${balance.toLocaleString()} sats)\n`;
759
- text += `⏳ Registering on next cycle...\n`;
760
- text += `\nRun \`overlay({ action: "register" })\` to register now.`;
761
- } else {
762
- text += `❌ **Not Registered**\n\n`;
763
- text += `📬 Fund this address to join:\n\`${address}\`\n\n`;
764
- text += `💰 Need: 1,000+ sats (~$0.05)`;
624
+ const env = buildEnvironment(pluginConfig);
625
+ const cliPath = path.join(__dirname, 'dist', 'cli.js');
626
+
627
+ const regPath = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'registration.json');
628
+ const onboardSentFile = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'onboarding-sent.flag');
629
+
630
+ if (!fs.existsSync(regPath) && !fs.existsSync(onboardSentFile)) {
631
+ // Check if wallet exists
632
+ const walletPath = path.join(pluginConfig.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet'), 'wallet-identity.json');
633
+
634
+ if (!fs.existsSync(walletPath)) {
635
+ // No wallet, no registration — first run ever.
636
+ // We'll let startAutoImport create the wallet via 'address' command,
637
+ // then it will wake the agent when funded.
638
+ } else {
639
+ // Wallet exists but not registered.
640
+ const balResult = await execFileAsync('node', [cliPath, 'balance'], { env });
641
+ const balance = parseCliOutput(balResult.stdout);
642
+
643
+ if ((balance.data?.walletBalance || 0) < 1000) {
644
+ // Funded less than 1000, need more funds to register.
645
+ // We don't wake up here, we wait for auto-import to detect new funds.
646
+ } else {
647
+ // Funded but not registered. Auto-register.
648
+ const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
649
+ if (parseCliOutput(regResult.stdout).success) {
650
+ ctx.logger.info('[bsv-overlay] Agent auto-registered on startup');
651
+ await autoAdvertiseServices(env, cliPath, ctx.logger);
652
+ }
653
+ }
654
+ }
655
+ }
656
+
657
+ } catch (err: any) {
658
+ api.log?.debug?.('[bsv-overlay] Auto-setup/onboarding skipped:', err.message);
765
659
  }
766
-
767
- return { text };
768
- } catch (err: any) {
769
- return { text: `❌ Error checking status: ${err.message}` };
770
- }
660
+ })();
771
661
  }
772
662
  });
773
663
 
774
- // Register CLI commands
775
- api.registerCli(({ program }) => {
776
- const overlay = program.command("overlay").description("BSV Overlay Network commands");
777
-
778
- overlay.command("status")
779
- .description("Show identity, balance, registration, and services")
664
+ // Register CLI extensions
665
+ api.registerCli(({ program }: any) => {
666
+ const overlay = program.command("overlay").description("BSV Overlay Network management");
667
+
668
+ overlay
669
+ .command("status")
670
+ .description("Show agent identity and balance")
780
671
  .action(async () => {
781
672
  try {
782
- const config = pluginConfig;
783
- const result = await handleStatus(buildEnvironment(config), path.join(__dirname, 'dist', 'cli.js'));
784
- console.log("BSV Overlay Status:");
785
- console.log("Identity:", result.identity);
786
- console.log("Balance:", result.balance);
787
- console.log("Services:", result.services);
788
- } catch (error) {
673
+ const env = buildEnvironment(pluginConfig);
674
+ const cliPath = path.join(__dirname, 'dist', 'cli.js');
675
+ const result = await handleStatus(env, cliPath);
676
+ console.log(JSON.stringify(result, null, 2));
677
+ } catch (error: any) {
789
678
  console.error("Error:", error.message);
790
679
  }
791
680
  });
792
-
793
- overlay.command("balance")
681
+
682
+ overlay
683
+ .command("balance")
794
684
  .description("Show wallet balance")
795
685
  .action(async () => {
796
686
  try {
797
- const config = pluginConfig;
798
- const result = await handleBalance(buildEnvironment(config), path.join(__dirname, 'dist', 'cli.js'));
799
- console.log("Balance:", result);
800
- } catch (error) {
687
+ const env = buildEnvironment(pluginConfig);
688
+ const cliPath = path.join(__dirname, 'dist', 'cli.js');
689
+ const result = await handleBalance(env, cliPath);
690
+ console.log(JSON.stringify(result, null, 2));
691
+ } catch (error: any) {
801
692
  console.error("Error:", error.message);
802
693
  }
803
694
  });
804
695
 
805
- overlay.command("address")
696
+ overlay
697
+ .command("address")
806
698
  .description("Show receive address")
807
699
  .action(async () => {
808
700
  try {
809
- const config = pluginConfig;
810
- const result = await handleAddress(buildEnvironment(config), path.join(__dirname, 'dist', 'cli.js'));
811
- console.log("Address:", result);
812
- } catch (error) {
701
+ const env = buildEnvironment(pluginConfig);
702
+ const cliPath = path.join(__dirname, 'dist', 'cli.js');
703
+ const result = await handleAddress(env, cliPath);
704
+ console.log(JSON.stringify(result, null, 2));
705
+ } catch (error: any) {
813
706
  console.error("Error:", error.message);
814
707
  }
815
708
  });
816
709
 
817
- overlay.command("discover")
818
- .description("List agents and services on the network")
819
- .option("--service <type>", "Filter by service type")
820
- .option("--agent <name>", "Filter by agent name")
821
- .action(async (options) => {
710
+ overlay
711
+ .command("discover")
712
+ .description("List agents and services")
713
+ .option("-s, --service <id>", "Filter by service ID")
714
+ .option("-a, --agent <key>", "Filter by agent key")
715
+ .action(async (options: any) => {
822
716
  try {
823
- const config = pluginConfig;
824
- const result = await handleDiscover(options, buildEnvironment(config), path.join(__dirname, 'dist', 'cli.js'));
825
- console.log("Discovery results:");
826
- console.log(`Overlay URL: ${result.overlayUrl}`);
827
- console.log(`Agents: ${result.agentCount}, Services: ${result.serviceCount}`);
828
- if (result.agents?.length > 0) {
717
+ const env = buildEnvironment(pluginConfig);
718
+ const cliPath = path.join(__dirname, 'dist', 'cli.js');
719
+ const result = await handleDiscover(options, env, cliPath);
720
+
721
+ if (result.agents) {
829
722
  console.log("\nAgents:");
830
- result.agents.forEach(agent => {
831
- console.log(` ${agent.agentName} (${agent.identityKey})`);
723
+ result.agents.forEach((agent: any) => {
724
+ console.log(`- ${agent.name} (${agent.identityKey.slice(0, 16)}...)`);
832
725
  });
833
726
  }
834
- if (result.services?.length > 0) {
727
+
728
+ if (result.services) {
835
729
  console.log("\nServices:");
836
- result.services.forEach(service => {
837
- console.log(` ${service.serviceId} - ${service.name} (${service.pricing?.amountSats || 0} sats) by ${service.agentName}`);
730
+ result.services.forEach((service: any) => {
731
+ console.log(`- ${service.name} (${service.serviceId}): ${service.pricing?.amountSats || 0} sats [${service.identityKey.slice(0, 12)}]`);
838
732
  });
839
733
  }
840
- } catch (error) {
734
+ } catch (error: any) {
841
735
  console.error("Error:", error.message);
842
736
  }
843
737
  });
844
738
 
845
- overlay.command("services")
846
- .description("List our advertised services")
739
+ overlay
740
+ .command("register")
741
+ .description("Register on the overlay network")
847
742
  .action(async () => {
848
743
  try {
849
- const config = pluginConfig;
850
- const result = await handleServices(buildEnvironment(config), path.join(__dirname, 'dist', 'cli.js'));
851
- console.log("Our services:", result);
852
- } catch (error) {
853
- console.error("Error:", error.message);
854
- }
855
- });
856
-
857
- overlay.command("setup")
858
- .description("Run initial wallet setup")
859
- .action(async () => {
860
- try {
861
- const config = pluginConfig;
862
- const env = buildEnvironment(config);
744
+ const env = buildEnvironment(pluginConfig);
863
745
  const cliPath = path.join(__dirname, 'dist', 'cli.js');
864
-
865
- const result = await execFileAsync('node', [cliPath, 'setup'], { env });
866
- const output = parseCliOutput(result.stdout);
867
- console.log("Setup result:", output);
868
- } catch (error) {
746
+ const result = await handleRegister(env, cliPath);
747
+ console.log(JSON.stringify(result, null, 2));
748
+ } catch (error: any) {
869
749
  console.error("Error:", error.message);
870
750
  }
871
751
  });
872
-
873
- overlay.command("register")
874
- .description("Register with the overlay network")
875
- .action(async () => {
752
+
753
+ overlay
754
+ .command("onboard")
755
+ .description("Run the onboarding flow")
756
+ .option("-n, --name <name>", "Agent display name")
757
+ .option("-d, --description <desc>", "Agent description")
758
+ .action(async (options: any) => {
876
759
  try {
877
- const config = pluginConfig;
878
- const env = buildEnvironment(config);
760
+ const env = buildEnvironment(pluginConfig);
879
761
  const cliPath = path.join(__dirname, 'dist', 'cli.js');
880
-
881
- const result = await execFileAsync('node', [cliPath, 'register'], { env });
882
- const output = parseCliOutput(result.stdout);
883
- console.log("Registration result:", output);
884
- } catch (error) {
762
+ const result = await handleOnboard(options, env, cliPath);
763
+ console.log(JSON.stringify(result, null, 2));
764
+ } catch (error: any) {
885
765
  console.error("Error:", error.message);
886
766
  }
887
767
  });
888
768
 
889
- overlay.command("wizard")
890
- .description("Interactive setup wizard for BSV Overlay Network")
769
+ overlay
770
+ .command("pending")
771
+ .description("Show pending service requests")
891
772
  .action(async () => {
892
- const readline = await import('readline');
893
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
894
-
895
- const prompt = (question: string): Promise<string> =>
896
- new Promise(resolve => rl.question(question, resolve));
897
-
898
- console.log('\n🔌 BSV Overlay Network — Setup Wizard\n');
899
- console.log('This wizard will help you configure and join the overlay network.\n');
900
-
901
773
  try {
902
- const config = pluginConfig;
903
- const env = buildEnvironment(config);
774
+ const env = buildEnvironment(pluginConfig);
904
775
  const cliPath = path.join(__dirname, 'dist', 'cli.js');
905
-
906
- // Step 1: Agent Identity
907
- console.log('─'.repeat(50));
908
- console.log('Step 1: Agent Identity\n');
909
- console.log('Your agent identity is how other agents will see you on the network.\n');
910
-
911
- const currentName = config?.agentName || env.AGENT_NAME || 'openclaw-agent';
912
- const agentName = await prompt(`Agent name [${currentName}]: `) || currentName;
913
-
914
- const currentDesc = config?.agentDescription || env.AGENT_DESCRIPTION || 'AI agent on the OpenClaw Overlay Network.';
915
- console.log('\nDescribe what your agent does (1-2 sentences):');
916
- const agentDescription = await prompt(`Description [${currentDesc}]: `) || currentDesc;
917
-
918
- // Step 2: Service Selection
919
- console.log('\n' + '─'.repeat(50));
920
- console.log('Step 2: Services to Offer\n');
921
- console.log('Available services:');
922
- const availableServices = serviceManager.getAvailableServices();
923
- availableServices.forEach((svc, i) => {
924
- console.log(` ${i + 1}. ${svc.name} (${svc.defaultPrice} sats) - ${svc.id}`);
925
- });
926
- console.log('\nEnter service numbers separated by commas (e.g., 1,2,5)');
927
- console.log('Or press Enter to skip service selection.\n');
928
- const serviceInput = await prompt('Services to advertise: ');
929
-
930
- const selectedServices: string[] = [];
931
- if (serviceInput.trim()) {
932
- const nums = serviceInput.split(',').map(s => parseInt(s.trim()) - 1);
933
- for (const n of nums) {
934
- if (n >= 0 && n < availableServices.length) {
935
- selectedServices.push(availableServices[n].id);
936
- }
937
- }
938
- }
939
-
940
- // Step 3: Budget Configuration
941
- console.log('\n' + '─'.repeat(50));
942
- console.log('Step 3: Budget Limits\n');
943
- const maxPay = await prompt(`Max auto-pay per request [${config?.maxAutoPaySats || 200}]: `) || String(config?.maxAutoPaySats || 200);
944
- const dailyBudget = await prompt(`Daily spending limit [${config?.dailyBudgetSats || 5000}]: `) || String(config?.dailyBudgetSats || 5000);
945
-
946
- // Generate config
947
- console.log('\n' + '─'.repeat(50));
948
- console.log('Configuration\n');
949
- const newConfig = {
950
- agentName,
951
- agentDescription,
952
- ...(selectedServices.length > 0 && { services: selectedServices }),
953
- maxAutoPaySats: parseInt(maxPay),
954
- dailyBudgetSats: parseInt(dailyBudget)
955
- };
956
- console.log('Add this to your config under plugins.entries.bsv-overlay.config:\n');
957
- console.log(JSON.stringify(newConfig, null, 2));
958
-
959
- // Step 4: Show funding address
960
- console.log('\n' + '─'.repeat(50));
961
- console.log('Step 4: Funding\n');
962
-
963
- // Ensure wallet exists
964
- try {
965
- await execFileAsync('node', [cliPath, 'setup'], { env });
966
- } catch {}
967
-
968
- const addrResult = await execFileAsync('node', [cliPath, 'address'], { env });
969
- const addrOutput = parseCliOutput(addrResult.stdout);
970
- const address = addrOutput?.data?.address;
971
-
972
- const balResult = await execFileAsync('node', [cliPath, 'balance'], { env });
973
- const balOutput = parseCliOutput(balResult.stdout);
974
- const balance = balOutput?.data?.walletBalance || 0;
975
-
976
- if (balance >= 1000) {
977
- console.log(`✅ Wallet already funded: ${balance.toLocaleString()} sats`);
978
- } else {
979
- console.log('Send BSV to this address to fund your agent:\n');
980
- console.log(` 📬 ${address}`);
981
- console.log(` 💰 Minimum: 1,000 sats (~$0.05)\n`);
982
- }
983
-
984
- // Step 5: Registration
985
- console.log('─'.repeat(50));
986
- console.log('Step 5: Registration\n');
987
-
988
- if (balance >= 1000) {
989
- const doRegister = await prompt('Register now? [Y/n]: ');
990
- if (doRegister.toLowerCase() !== 'n') {
991
- console.log('\nRegistering...');
992
- const regResult = await execFileAsync('node', [cliPath, 'register'], {
993
- env: { ...env, AGENT_NAME: agentName, AGENT_DESCRIPTION: agentDescription },
994
- timeout: 60000
995
- });
996
- const regOutput = parseCliOutput(regResult.stdout);
997
- if (regOutput.success) {
998
- console.log('✅ Registered on the overlay network!');
999
-
1000
- // Auto-advertise selected services
1001
- if (selectedServices.length > 0) {
1002
- console.log(`\nAdvertising ${selectedServices.length} services...`);
1003
- for (const serviceId of selectedServices) {
1004
- const svc = serviceManager.registry.get(serviceId);
1005
- if (svc) {
1006
- try {
1007
- await execFileAsync('node', [
1008
- cliPath, 'advertise', serviceId, svc.name, svc.defaultPrice.toString(), svc.description
1009
- ], { env, timeout: 60000 });
1010
- console.log(` ✅ ${svc.name} (${svc.defaultPrice} sats)`);
1011
- } catch (err: any) {
1012
- console.log(` ❌ ${svc.name}: ${err.message}`);
1013
- }
1014
- }
1015
- }
1016
- }
1017
- } else {
1018
- console.log(`❌ Registration failed: ${regOutput.error}`);
1019
- }
1020
- }
1021
- } else {
1022
- console.log('Fund your wallet, then run: openclaw overlay register');
1023
- }
1024
-
1025
- console.log('\n' + '─'.repeat(50));
1026
- console.log('Setup complete! 🎉\n');
1027
-
776
+ const result = await handlePendingRequests(env, cliPath);
777
+ console.log(JSON.stringify(result, null, 2));
1028
778
  } catch (error: any) {
1029
- console.error('\nError:', error.message);
1030
- } finally {
1031
- rl.close();
779
+ console.error("Error:", error.message);
1032
780
  }
1033
781
  });
1034
- }, { commands: ["overlay"] });
1035
-
1036
- // ---------------------------------------------------------------------------
1037
- // Auto-setup + onboarding (best-effort, non-fatal, fire-and-forget)
1038
- // ---------------------------------------------------------------------------
1039
- (async () => {
1040
- try {
1041
- const config = pluginConfig;
1042
- const walletDir = config?.walletDir || path.join(process.env.HOME || '', '.openclaw', 'bsv-wallet');
1043
- const identityFile = path.join(walletDir, 'wallet-identity.json');
1044
- const env = buildEnvironment(config || {});
1045
- const cliPath = path.join(__dirname, 'dist', 'cli.js');
1046
-
1047
- // Step 0: Auto-enable hooks if not configured
1048
- // The plugin needs hooks.enabled + hooks.token for async wake-ups via /hooks/agent
1049
- const hooksAutoConfigured = autoEnableHooks(api);
1050
-
1051
- // Step 1: Create wallet if missing
1052
- let walletJustCreated = false;
1053
- if (!fs.existsSync(identityFile)) {
1054
- api.log?.info?.('[bsv-overlay] No wallet found — running auto-setup...');
1055
- await execFileAsync('node', [cliPath, 'setup'], { env });
1056
- api.log?.info?.('[bsv-overlay] Wallet initialized.');
1057
- walletJustCreated = true;
1058
- }
1059
-
1060
- // Step 2: Get wallet address for onboarding message
1061
- let walletAddress = '';
1062
- try {
1063
- const addrResult = await execFileAsync('node', [cliPath, 'address'], { env });
1064
- const addrOutput = parseCliOutput(addrResult.stdout);
1065
- walletAddress = addrOutput?.data?.address || '';
1066
- } catch {}
1067
-
1068
- // Step 3: Check registration and balance state
1069
- const regPath = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'registration.json');
1070
- const isRegistered = fs.existsSync(regPath);
1071
- let balance = 0;
1072
- try {
1073
- const balResult = await execFileAsync('node', [cliPath, 'balance'], { env });
1074
- const balOutput = parseCliOutput(balResult.stdout);
1075
- balance = balOutput?.data?.walletBalance || 0;
1076
- } catch {}
1077
-
1078
- // Step 4: If funded and not registered → auto-register
1079
- if (!isRegistered && balance >= 1000) {
1080
- // Clear onboarding flag since wallet is now funded
1081
- try {
1082
- const onboardingSentFile = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'onboarding-sent.flag');
1083
- if (fs.existsSync(onboardingSentFile)) {
1084
- fs.unlinkSync(onboardingSentFile);
1085
- }
1086
- } catch {}
1087
-
1088
- api.log?.info?.('[bsv-overlay] Wallet funded but not registered — auto-registering...');
1089
- const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
1090
- const regOutput = parseCliOutput(regResult.stdout);
1091
- if (regOutput.success) {
1092
- api.log?.info?.('[bsv-overlay] Auto-registered on overlay network!');
1093
-
1094
- // Auto-advertise services from config
1095
- await autoAdvertiseServices(env, cliPath, api.log);
1096
-
1097
- const wakeText = `🎉 **BSV Overlay: Registered on the network!**\n\nYour agent is now live on the OpenClaw Overlay Network.\n\nCurrent name: "${env.AGENT_NAME}"\n\nUse /overlay for instant status or ask me about your services.`;
1098
- wakeAgent(wakeText, api.log);
1099
- return; // Registered — done with onboarding
1100
- }
1101
- }
1102
-
1103
- // Step 5: If already registered, nothing to onboard
1104
- if (isRegistered) return;
1105
-
1106
- // Step 6: Not registered + not funded → send onboarding message (only once per wallet)
1107
- // This runs on first startup after plugin install (wallet just created or exists but empty)
1108
- const onboardingSentFile = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'onboarding-sent.flag');
1109
-
1110
- // Check if we already sent onboarding message for this wallet
1111
- let alreadySent = false;
1112
- try {
1113
- if (fs.existsSync(onboardingSentFile)) {
1114
- const flagData = fs.readFileSync(onboardingSentFile, 'utf-8');
1115
- if (flagData.trim() === walletAddress) {
1116
- alreadySent = true;
1117
- }
1118
- }
1119
- } catch {
1120
- // Ignore errors reading flag file
1121
- }
1122
-
1123
- if (alreadySent) {
1124
- api.log?.debug?.('[bsv-overlay] Onboarding message already sent for this wallet address');
1125
- return;
1126
- }
1127
-
1128
- const needsRestart = hooksAutoConfigured;
1129
- let onboardingMsg = `The BSV Overlay Network plugin is installed. Ask the user:\n`;
1130
- onboardingMsg += `1. What name they want for their agent on the network\n`;
1131
- onboardingMsg += `2. A short description of what their agent does\n\n`;
1132
- onboardingMsg += `Wallet address: ${walletAddress}\n`;
1133
- onboardingMsg += `Minimum funding: 1,000 sats (~$0.05). Auto-import runs every 30 seconds.\n`;
1134
-
1135
- if (needsRestart) {
1136
- onboardingMsg += `\nNote: Hooks were auto-configured. A gateway restart is needed to activate async wake-ups.`;
1137
- }
1138
-
1139
- onboardingMsg += `\n\nOnce the user provides name and description, and the wallet is funded, run:\n`;
1140
- onboardingMsg += `overlay({ action: "onboard", agentName: "<name>", agentDescription: "<description>" })`;
1141
-
1142
- wakeAgent(onboardingMsg, api.log, { sessionKey: 'hook:bsv-overlay:onboarding' });
1143
-
1144
- // Mark onboarding as sent for this wallet address
1145
- try {
1146
- fs.mkdirSync(path.dirname(onboardingSentFile), { recursive: true });
1147
- fs.writeFileSync(onboardingSentFile, walletAddress);
1148
- } catch (err: any) {
1149
- api.log?.warn?.(`[bsv-overlay] Failed to save onboarding flag: ${err.message}`);
1150
- }
1151
-
1152
- } catch (err: any) {
1153
- api.log?.debug?.('[bsv-overlay] Auto-setup/onboarding skipped:', err.message);
1154
- }
1155
- })();
782
+ });
1156
783
  }
1157
784
 
1158
- async function executeOverlayAction(params, config, api) {
785
+ async function executeOverlayAction(params: any, config: any, api: any) {
1159
786
  const { action } = params;
1160
787
  const env = buildEnvironment(config);
1161
788
  const cliPath = path.join(__dirname, 'dist', 'cli.js');
@@ -1232,7 +859,7 @@ async function executeOverlayAction(params, config, api) {
1232
859
  }
1233
860
  }
1234
861
 
1235
- async function handleServiceRequest(params, env, cliPath, config, api) {
862
+ async function handleServiceRequest(params: any, env: any, cliPath: string, config: any, api: any) {
1236
863
  const { service, identityKey: targetKey, input, maxPrice } = params;
1237
864
  const walletDir = config?.walletDir || path.join(process.env.HOME || '', '.openclaw', 'bsv-wallet');
1238
865
 
@@ -1259,22 +886,22 @@ async function handleServiceRequest(params, env, cliPath, config, api) {
1259
886
  const identityOutput = parseCliOutput(identityResult.stdout);
1260
887
  const ourKey = identityOutput.data?.identityKey;
1261
888
 
1262
- let externalProviders = providers.filter(p => p.identityKey !== ourKey);
889
+ let externalProviders = providers.filter((p: any) => p.identityKey !== ourKey);
1263
890
  if (externalProviders.length === 0) {
1264
891
  throw new Error("No external providers available (only found our own services)");
1265
892
  }
1266
893
 
1267
894
  // 2b. If caller specified a target identityKey, route to that provider specifically
1268
895
  if (targetKey) {
1269
- const targeted = externalProviders.filter(p => p.identityKey === targetKey);
896
+ const targeted = externalProviders.filter((p: any) => p.identityKey === targetKey);
1270
897
  if (targeted.length === 0) {
1271
- throw new Error(`Specified provider ${targetKey} not found or is our own key. Available: ${externalProviders.map(p => p.identityKey).join(', ')}`);
898
+ throw new Error(`Specified provider ${targetKey} not found or is our own key. Available: ${externalProviders.map((p: any) => p.identityKey).join(', ')}`);
1272
899
  }
1273
900
  externalProviders = targeted;
1274
901
  }
1275
902
 
1276
903
  // 3. Sort by price - FIX: Use pricing.amountSats instead of pricingSats
1277
- externalProviders.sort((a, b) => (a.pricing?.amountSats || 0) - (b.pricing?.amountSats || 0));
904
+ externalProviders.sort((a: any, b: any) => (a.pricing?.amountSats || 0) - (b.pricing?.amountSats || 0));
1278
905
 
1279
906
  const bestProvider = externalProviders[0];
1280
907
  const price = bestProvider.pricing?.amountSats || 0;
@@ -1350,7 +977,7 @@ function validateConfirmToken(token: string, expectedAction: string): { valid: b
1350
977
  return { valid: true, details: entry.details };
1351
978
  }
1352
979
 
1353
- async function handleUnregister(params, env, cliPath) {
980
+ async function handleUnregister(params: any, env: any, cliPath: string) {
1354
981
  const { confirmToken } = params;
1355
982
 
1356
983
  // Load current registration to show what will be deleted
@@ -1430,7 +1057,7 @@ async function handleUnregister(params, env, cliPath) {
1430
1057
  };
1431
1058
  }
1432
1059
 
1433
- async function handleRemoveService(params, env, cliPath) {
1060
+ async function handleRemoveService(params: any, env: any, cliPath: string) {
1434
1061
  const { serviceId, confirmToken } = params;
1435
1062
 
1436
1063
  if (!serviceId) {
@@ -1499,7 +1126,7 @@ async function handleRemoveService(params, env, cliPath) {
1499
1126
  };
1500
1127
  }
1501
1128
 
1502
- async function handleDiscover(params, env, cliPath) {
1129
+ async function handleDiscover(params: any, env: any, cliPath: string) {
1503
1130
  const { service, agent } = params;
1504
1131
  const args = [cliPath, 'discover'];
1505
1132
 
@@ -1520,7 +1147,7 @@ async function handleDiscover(params, env, cliPath) {
1520
1147
  return output.data;
1521
1148
  }
1522
1149
 
1523
- async function handleBalance(env, cliPath) {
1150
+ async function handleBalance(env: any, cliPath: string) {
1524
1151
  const result = await execFileAsync('node', [cliPath, 'balance'], { env });
1525
1152
  const output = parseCliOutput(result.stdout);
1526
1153
 
@@ -1531,7 +1158,7 @@ async function handleBalance(env, cliPath) {
1531
1158
  return output.data;
1532
1159
  }
1533
1160
 
1534
- async function handleStatus(env, cliPath) {
1161
+ async function handleStatus(env: any, cliPath: string) {
1535
1162
  try {
1536
1163
  // Get identity
1537
1164
  const identityResult = await execFileAsync('node', [cliPath, 'identity'], { env });
@@ -1550,12 +1177,12 @@ async function handleStatus(env, cliPath) {
1550
1177
  balance: balance.data,
1551
1178
  services: services.data
1552
1179
  };
1553
- } catch (error) {
1180
+ } catch (error: any) {
1554
1181
  throw new Error(`Status check failed: ${error.message}`);
1555
1182
  }
1556
1183
  }
1557
1184
 
1558
- async function handleDirectPay(params, env, cliPath, config) {
1185
+ async function handleDirectPay(params: any, env: any, cliPath: string, config: any) {
1559
1186
  const { identityKey, sats, description } = params;
1560
1187
  const walletDir = config?.walletDir || path.join(process.env.HOME || '', '.openclaw', 'bsv-wallet');
1561
1188
 
@@ -1589,7 +1216,7 @@ async function handleDirectPay(params, env, cliPath, config) {
1589
1216
  return output.data;
1590
1217
  }
1591
1218
 
1592
- async function handleSetup(env, cliPath) {
1219
+ async function handleSetup(env: any, cliPath: string) {
1593
1220
  const result = await execFileAsync('node', [cliPath, 'setup'], { env });
1594
1221
  const output = parseCliOutput(result.stdout);
1595
1222
 
@@ -1600,7 +1227,7 @@ async function handleSetup(env, cliPath) {
1600
1227
  return output.data;
1601
1228
  }
1602
1229
 
1603
- async function handleAddress(env, cliPath) {
1230
+ async function handleAddress(env: any, cliPath: string) {
1604
1231
  const result = await execFileAsync('node', [cliPath, 'address'], { env });
1605
1232
  const output = parseCliOutput(result.stdout);
1606
1233
 
@@ -1611,7 +1238,7 @@ async function handleAddress(env, cliPath) {
1611
1238
  return output.data;
1612
1239
  }
1613
1240
 
1614
- async function handleImport(params, env, cliPath) {
1241
+ async function handleImport(params: any, env: any, cliPath: string) {
1615
1242
  const { txid, vout } = params;
1616
1243
 
1617
1244
  if (!txid) {
@@ -1664,7 +1291,7 @@ async function handleImport(params, env, cliPath) {
1664
1291
  return output.data;
1665
1292
  }
1666
1293
 
1667
- async function handleRegister(env, cliPath) {
1294
+ async function handleRegister(env: any, cliPath: string) {
1668
1295
  const result = await execFileAsync('node', [cliPath, 'register'], { env });
1669
1296
  const output = parseCliOutput(result.stdout);
1670
1297
 
@@ -1686,7 +1313,7 @@ async function handleRegister(env, cliPath) {
1686
1313
  };
1687
1314
  }
1688
1315
 
1689
- async function handleAdvertise(params, env, cliPath) {
1316
+ async function handleAdvertise(params: any, env: any, cliPath: string) {
1690
1317
  const { serviceId, name, description, priceSats } = params;
1691
1318
 
1692
1319
  if (!serviceId || !name || !description || priceSats === undefined) {
@@ -1703,7 +1330,7 @@ async function handleAdvertise(params, env, cliPath) {
1703
1330
  return output.data;
1704
1331
  }
1705
1332
 
1706
- async function handleReadvertise(params, env, cliPath) {
1333
+ async function handleReadvertise(params: any, env: any, cliPath: string) {
1707
1334
  const { serviceId, newPrice, newName, newDesc } = params;
1708
1335
 
1709
1336
  if (!serviceId || newPrice === undefined) {
@@ -1728,7 +1355,7 @@ async function handleReadvertise(params, env, cliPath) {
1728
1355
  return output.data;
1729
1356
  }
1730
1357
 
1731
- async function handleRemove(params, env, cliPath) {
1358
+ async function handleRemove(params: any, env: any, cliPath: string) {
1732
1359
  const { serviceId } = params;
1733
1360
 
1734
1361
  if (!serviceId) {
@@ -1745,7 +1372,7 @@ async function handleRemove(params, env, cliPath) {
1745
1372
  return output.data;
1746
1373
  }
1747
1374
 
1748
- async function handleSend(params, env, cliPath) {
1375
+ async function handleSend(params: any, env: any, cliPath: string) {
1749
1376
  const { identityKey, messageType, payload } = params;
1750
1377
 
1751
1378
  if (!identityKey || !messageType || !payload) {
@@ -1762,7 +1389,7 @@ async function handleSend(params, env, cliPath) {
1762
1389
  return output.data;
1763
1390
  }
1764
1391
 
1765
- async function handleInbox(env, cliPath) {
1392
+ async function handleInbox(env: any, cliPath: string) {
1766
1393
  const result = await execFileAsync('node', [cliPath, 'inbox'], { env });
1767
1394
  const output = parseCliOutput(result.stdout);
1768
1395
 
@@ -1773,7 +1400,7 @@ async function handleInbox(env, cliPath) {
1773
1400
  return output.data;
1774
1401
  }
1775
1402
 
1776
- async function handleServices(env, cliPath) {
1403
+ async function handleServices(env: any, cliPath: string) {
1777
1404
  const result = await execFileAsync('node', [cliPath, 'services'], { env });
1778
1405
  const output = parseCliOutput(result.stdout);
1779
1406
 
@@ -1784,7 +1411,7 @@ async function handleServices(env, cliPath) {
1784
1411
  return output.data;
1785
1412
  }
1786
1413
 
1787
- async function handleRefund(params, env, cliPath) {
1414
+ async function handleRefund(params: any, env: any, cliPath: string) {
1788
1415
  const { address } = params;
1789
1416
 
1790
1417
  if (!address) {
@@ -1801,7 +1428,7 @@ async function handleRefund(params, env, cliPath) {
1801
1428
  return output.data;
1802
1429
  }
1803
1430
 
1804
- async function handleOnboard(params, env, cliPath) {
1431
+ async function handleOnboard(params: any, env: any, cliPath: string) {
1805
1432
  const { agentName, agentDescription } = params;
1806
1433
  const steps = [];
1807
1434
 
@@ -1815,7 +1442,7 @@ async function handleOnboard(params, env, cliPath) {
1815
1442
  const setup = await execFileAsync('node', [cliPath, 'setup'], { env: onboardEnv });
1816
1443
  const setupOutput = parseCliOutput(setup.stdout);
1817
1444
  steps.push({ step: 'setup', success: true, identityKey: setupOutput.data?.identityKey });
1818
- } catch (err) {
1445
+ } catch (err: any) {
1819
1446
  steps.push({ step: 'setup', success: false, error: err.message });
1820
1447
  return { steps, nextStep: 'Fix wallet setup error and try again' };
1821
1448
  }
@@ -1825,7 +1452,7 @@ async function handleOnboard(params, env, cliPath) {
1825
1452
  const addr = await execFileAsync('node', [cliPath, 'address'], { env: onboardEnv });
1826
1453
  const addrOutput = parseCliOutput(addr.stdout);
1827
1454
  steps.push({ step: 'address', success: true, address: addrOutput.data?.address });
1828
- } catch (err) {
1455
+ } catch (err: any) {
1829
1456
  steps.push({ step: 'address', success: false, error: err.message });
1830
1457
  }
1831
1458
 
@@ -1843,7 +1470,7 @@ async function handleOnboard(params, env, cliPath) {
1843
1470
  nextStep: `Fund your wallet with at least 1,000 sats. Send BSV to: ${steps[1]?.address}. Auto-import is running — once funded, run overlay({ action: "onboard" }) again.`
1844
1471
  };
1845
1472
  }
1846
- } catch (err) {
1473
+ } catch (err: any) {
1847
1474
  steps.push({ step: 'balance', success: false, error: err.message });
1848
1475
  }
1849
1476
 
@@ -1852,7 +1479,7 @@ async function handleOnboard(params, env, cliPath) {
1852
1479
  const reg = await execFileAsync('node', [cliPath, 'register'], { env: onboardEnv, timeout: 60000 });
1853
1480
  const regOutput = parseCliOutput(reg.stdout);
1854
1481
  steps.push({ step: 'register', success: regOutput.success, data: regOutput.data });
1855
- } catch (err) {
1482
+ } catch (err: any) {
1856
1483
  steps.push({ step: 'register', success: false, error: err.message });
1857
1484
  }
1858
1485
 
@@ -1874,12 +1501,12 @@ async function handleOnboard(params, env, cliPath) {
1874
1501
  };
1875
1502
  }
1876
1503
 
1877
- async function handlePendingRequests(env, cliPath) {
1504
+ async function handlePendingRequests(env: any, cliPath: string) {
1878
1505
  // Clean up old queue entries before checking pending requests
1879
1506
  try {
1880
1507
  const { cleanupServiceQueue } = await import('./src/scripts/utils/storage.js');
1881
1508
  cleanupServiceQueue();
1882
- } catch (err) {
1509
+ } catch (err: any) {
1883
1510
  console.error('Queue cleanup failed:', err.message);
1884
1511
  }
1885
1512
 
@@ -1907,7 +1534,7 @@ function handleActivity() {
1907
1534
  return { events, count: events.length };
1908
1535
  }
1909
1536
 
1910
- async function handleFulfill(params, env, cliPath) {
1537
+ async function handleFulfill(params: any, env: any, cliPath: string) {
1911
1538
  const { requestId, recipientKey, serviceId, result } = params;
1912
1539
  if (!requestId || !recipientKey || !serviceId || !result) {
1913
1540
  throw new Error("requestId, recipientKey, serviceId, and result are required");
@@ -1927,7 +1554,7 @@ async function handleFulfill(params, env, cliPath) {
1927
1554
  return output.data;
1928
1555
  }
1929
1556
 
1930
- function buildEnvironment(config) {
1557
+ function buildEnvironment(config: any) {
1931
1558
  const env = { ...process.env };
1932
1559
 
1933
1560
  if (config.walletDir) {
@@ -1959,12 +1586,12 @@ function buildEnvironment(config) {
1959
1586
  return env;
1960
1587
  }
1961
1588
 
1962
- function parseCliOutput(stdout) {
1589
+ function parseCliOutput(stdout: any) {
1963
1590
  try {
1964
1591
  return JSON.parse(stdout.trim());
1965
- } catch (error) {
1592
+ } catch (error: any) {
1966
1593
  throw new Error(`Failed to parse CLI output: ${error.message}`);
1967
1594
  }
1968
1595
  }
1969
1596
 
1970
- // sleep() removed — no longer needed since polling loop was removed
1597
+ // sleep() removed — no longer needed since polling loop was removed