openclaw-overlay-plugin 0.8.4 → 0.8.6

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 (40) hide show
  1. package/dist/index.d.ts +0 -1
  2. package/dist/index.js +118 -231
  3. package/dist/src/cli.js +1 -1
  4. package/dist/src/scripts/baemail/commands.d.ts +6 -6
  5. package/dist/src/scripts/messaging/inbox.d.ts +2 -2
  6. package/dist/src/scripts/messaging/poll.d.ts +1 -1
  7. package/dist/src/scripts/messaging/send.d.ts +1 -1
  8. package/dist/src/scripts/output.d.ts +5 -4
  9. package/dist/src/scripts/output.js +11 -2
  10. package/dist/src/scripts/overlay/advertisement.d.ts +2 -2
  11. package/dist/src/scripts/overlay/discover.d.ts +1 -1
  12. package/dist/src/scripts/overlay/registration.d.ts +2 -2
  13. package/dist/src/scripts/overlay/services.d.ts +4 -4
  14. package/dist/src/scripts/payment/commands.d.ts +3 -3
  15. package/dist/src/scripts/services/queue.d.ts +2 -2
  16. package/dist/src/scripts/services/request.d.ts +1 -1
  17. package/dist/src/scripts/services/respond.d.ts +2 -2
  18. package/dist/src/scripts/wallet/balance.d.ts +2 -2
  19. package/dist/src/scripts/wallet/setup.d.ts +4 -4
  20. package/dist/src/scripts/x-verification/commands.d.ts +6 -6
  21. package/index.ts +117 -244
  22. package/openclaw.plugin.json +2 -2
  23. package/package.json +1 -1
  24. package/src/cli.ts +1 -1
  25. package/src/scripts/baemail/commands.ts +6 -6
  26. package/src/scripts/messaging/inbox.ts +2 -2
  27. package/src/scripts/messaging/poll.ts +1 -1
  28. package/src/scripts/messaging/send.ts +1 -1
  29. package/src/scripts/output.ts +13 -4
  30. package/src/scripts/overlay/advertisement.ts +2 -2
  31. package/src/scripts/overlay/discover.ts +1 -1
  32. package/src/scripts/overlay/registration.ts +2 -2
  33. package/src/scripts/overlay/services.ts +4 -4
  34. package/src/scripts/payment/commands.ts +3 -3
  35. package/src/scripts/services/queue.ts +2 -2
  36. package/src/scripts/services/request.ts +1 -1
  37. package/src/scripts/services/respond.ts +2 -2
  38. package/src/scripts/wallet/balance.ts +2 -2
  39. package/src/scripts/wallet/setup.ts +4 -4
  40. package/src/scripts/x-verification/commands.ts +6 -6
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- export declare function activate(api: any): Promise<void>;
2
1
  export declare function register(api: any): void;
3
2
  export declare const plugin: {
4
3
  id: string;
package/dist/index.js CHANGED
@@ -1,37 +1,19 @@
1
- import { promisify } from 'node:util';
2
1
  import path from 'node:path';
3
2
  import os from 'node:os';
4
- import { fileURLToPath } from 'node:url';
5
3
  import fs from 'node:fs';
6
4
  import { initializeServiceSystem, serviceManager } from './src/services/index.js';
7
- const __filename = fileURLToPath(import.meta.url);
8
- const __dirname = path.dirname(__filename);
9
- const cp_name = 'node:child' + '_' + 'process';
10
- let execFile_orig;
11
- let spawn_orig;
12
- let execFileAsync;
13
- async function ensureCp() {
14
- if (execFileAsync)
15
- return;
16
- // @ts-ignore
17
- if (typeof require !== 'undefined') {
18
- // @ts-ignore
19
- const cp = require(cp_name);
20
- execFile_orig = cp.execFile;
21
- spawn_orig = cp.spawn;
22
- }
23
- else {
24
- const cp = await import(cp_name);
25
- execFile_orig = cp.execFile;
26
- spawn_orig = cp.spawn;
27
- }
28
- execFileAsync = promisify(execFile_orig);
29
- }
5
+ // Direct imports of command logic
6
+ import { cmdStatus, cmdSetup, cmdAddress, cmdIdentity } from './src/scripts/wallet/setup.js';
7
+ import { cmdBalance, cmdImport } from './src/scripts/wallet/balance.js';
8
+ import { cmdRegister, cmdUnregister } from './src/scripts/overlay/registration.js';
9
+ import { cmdDiscover } from './src/scripts/overlay/discover.js';
10
+ import { cmdRequestService } from './src/scripts/services/request.js';
11
+ import { cmdServiceQueue } from './src/scripts/services/queue.js';
12
+ import { cmdRespondService } from './src/scripts/services/respond.js';
13
+ import { setNoExit } from './src/scripts/output.js';
30
14
  // Track background process for proper lifecycle management
31
15
  let backgroundProcess = null;
32
16
  let serviceRunning = false;
33
- // Confirmation tokens for destructive actions — maps token → { action, details, expiresAt }
34
- const pendingConfirmations = new Map();
35
17
  // Auto-import tracking
36
18
  let autoImportInterval = null;
37
19
  let knownTxids = new Set();
@@ -52,18 +34,10 @@ function loadDailySpending(walletDir) {
52
34
  return data;
53
35
  }
54
36
  catch {
55
- // Ignore parse errors - return fresh daily spending for corrupted/missing file
37
+ // Ignore parse errors
56
38
  }
57
39
  return { date: today, totalSats: 0, transactions: [] };
58
40
  }
59
- function writeActivityEvent(event) {
60
- const alertDir = path.join(process['env'].HOME || '', '.openclaw', 'openclaw-overlay');
61
- try {
62
- fs.mkdirSync(alertDir, { recursive: true });
63
- fs.appendFileSync(path.join(alertDir, 'activity-feed.jsonl'), JSON.stringify({ ...event, ts: Date.now() }) + '\n');
64
- }
65
- catch { }
66
- }
67
41
  function recordSpend(walletDir, sats, service, provider) {
68
42
  const spending = loadDailySpending(walletDir);
69
43
  spending.totalSats += sats;
@@ -79,11 +53,18 @@ function checkBudget(walletDir, requestedSats, dailyLimit) {
79
53
  spent: spending.totalSats
80
54
  };
81
55
  }
82
- async function startAutoImport(env, cliPath, api) {
83
- // Get our address
56
+ function applyConfigToEnv(config) {
57
+ process['env'].BSV_WALLET_DIR = config.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet');
58
+ process['env'].OVERLAY_URL = config.overlayUrl || 'https://clawoverlay.com';
59
+ process['env'].BSV_NETWORK = config.network || process['env'].BSV_NETWORK || 'mainnet';
60
+ process['env'].BSV_ARC_URL = config.arcUrl || (process['env'].BSV_NETWORK === 'testnet' ? 'https://testnet.arc.gorillapool.io' : 'https://arc.gorillapool.io');
61
+ process['env'].AGENT_NAME = config.agentName || 'openclaw-agent';
62
+ setNoExit(true);
63
+ }
64
+ async function startAutoImport(config, api) {
84
65
  try {
85
- const addrResult = await execFileAsync('node', [cliPath, 'address'], { env });
86
- const addrOutput = parseCliOutput(addrResult.stdout);
66
+ applyConfigToEnv(config);
67
+ const addrOutput = await cmdAddress();
87
68
  if (!addrOutput.success)
88
69
  return;
89
70
  const address = addrOutput.data?.address;
@@ -91,7 +72,7 @@ async function startAutoImport(env, cliPath, api) {
91
72
  return;
92
73
  autoImportInterval = setInterval(async () => {
93
74
  try {
94
- const network = env.BSV_NETWORK === 'testnet' ? 'test' : 'main';
75
+ const network = process['env'].BSV_NETWORK === 'testnet' ? 'test' : 'main';
95
76
  const controller = new AbortController();
96
77
  const timeout = setTimeout(() => controller.abort(), 15000);
97
78
  const resp = await fetch(`https://api.whatsonchain.com/v1/bsv/${network}/address/${address}/unspent/all`, { signal: controller.signal });
@@ -105,34 +86,26 @@ async function startAutoImport(env, cliPath, api) {
105
86
  if (knownTxids.has(key))
106
87
  continue;
107
88
  if (utxo.value < 200)
108
- continue; // skip dust
89
+ continue;
109
90
  api.logger?.info?.(`[openclaw-overlay] Auto-importing UTXO: ${utxo.tx_hash}:${utxo.tx_pos} (${utxo.value} sats)`);
110
91
  try {
111
- const importResult = await execFileAsync('node', [cliPath, 'import', utxo.tx_hash, String(utxo.tx_pos)], { env });
112
- const importOutput = parseCliOutput(importResult.stdout);
92
+ applyConfigToEnv(config);
93
+ const importOutput = await cmdImport(utxo.tx_hash, String(utxo.tx_pos));
113
94
  if (importOutput.success) {
114
95
  knownTxids.add(key);
115
96
  api.logger?.info?.(`[openclaw-overlay] Auto-imported ${utxo.value} sats from ${utxo.tx_hash}`);
116
- // Clear onboarding flag since wallet is now funded
117
- try {
118
- const onboardingSentFile = path.join(process['env'].HOME || '', '.openclaw', 'openclaw-overlay', 'onboarding-sent.flag');
119
- if (fs.existsSync(onboardingSentFile)) {
120
- fs.unlinkSync(onboardingSentFile);
121
- }
122
- }
123
- catch { }
124
97
  // Notify agent of successful import
125
98
  wakeAgent(`💰 **Wallet Funded!**\n\nAuto-imported ${utxo.value} sats from transaction ${utxo.tx_hash.slice(0, 16)}...\n\nNotify the user their wallet has been funded.`, api.logger, { sessionKey: 'hook:openclaw-overlay:import' });
126
99
  // Check if registered, auto-register if not
127
100
  try {
128
- const regPath = path.join(process['env'].HOME || '', '.openclaw', 'openclaw-overlay', 'registration.json');
101
+ const regPath = path.join(os.homedir(), '.openclaw', 'openclaw-overlay', 'registration.json');
129
102
  if (!fs.existsSync(regPath)) {
130
103
  api.logger?.info?.('[openclaw-overlay] Not yet registered — auto-registering...');
131
- const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
132
- const regOutput = parseCliOutput(regResult.stdout);
104
+ applyConfigToEnv(config);
105
+ const regOutput = await cmdRegister();
133
106
  if (regOutput.success) {
134
107
  api.logger?.info?.('[openclaw-overlay] Auto-registered on overlay network!');
135
- await autoAdvertiseServices(env, cliPath, api.logger);
108
+ await autoAdvertiseServices(config, api.logger);
136
109
  }
137
110
  }
138
111
  }
@@ -155,26 +128,12 @@ async function startAutoImport(env, cliPath, api) {
155
128
  api.logger?.warn?.('[openclaw-overlay] Auto-import setup failed:', err.message);
156
129
  }
157
130
  }
158
- function stopAutoImport() {
159
- if (autoImportInterval) {
160
- clearInterval(autoImportInterval);
161
- autoImportInterval = null;
162
- }
163
- }
164
- async function autoAdvertiseServices(env, cliPath, logger) {
131
+ async function autoAdvertiseServices(config, logger) {
165
132
  try {
166
- const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
167
- if (!fs.existsSync(configPath))
168
- return;
169
133
  let servicesToAdvertise = [];
170
- try {
171
- const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
172
- const pluginConfig = config?.plugins?.entries?.['openclaw-overlay-plugin']?.config || config?.plugins?.entries?.['openclaw-overlay-plugin'];
173
- if (pluginConfig?.services && Array.isArray(pluginConfig.services)) {
174
- servicesToAdvertise = pluginConfig.services;
175
- }
134
+ if (config?.services && Array.isArray(config.services)) {
135
+ servicesToAdvertise = config.services;
176
136
  }
177
- catch { }
178
137
  if (servicesToAdvertise.length === 0)
179
138
  return;
180
139
  for (const serviceId of servicesToAdvertise) {
@@ -182,9 +141,9 @@ async function autoAdvertiseServices(env, cliPath, logger) {
182
141
  if (!serviceInfo)
183
142
  continue;
184
143
  try {
185
- await execFileAsync('node', [
186
- cliPath, 'advertise', serviceId, serviceInfo.name, serviceInfo.description, String(serviceInfo.defaultPrice)
187
- ], { env, timeout: 60000 });
144
+ const { cmdAdvertise } = await import('./src/scripts/overlay/services.js');
145
+ applyConfigToEnv(config);
146
+ await cmdAdvertise(serviceId, serviceInfo.name, String(serviceInfo.defaultPrice), serviceInfo.description);
188
147
  }
189
148
  catch { }
190
149
  }
@@ -196,7 +155,7 @@ async function autoAdvertiseServices(env, cliPath, logger) {
196
155
  function wakeAgent(text, logger, options = {}) {
197
156
  const sessionKey = options.sessionKey || `hook:openclaw-overlay:${Date.now()}`;
198
157
  const gatewayPort = process['env'].OPENCLAW_GATEWAY_PORT || '18789';
199
- const httpToken = getHooksToken();
158
+ const httpToken = process['env'].OPENCLAW_HOOKS_TOKEN || null;
200
159
  if (!httpToken)
201
160
  return;
202
161
  fetch(`http://localhost:${gatewayPort}/hooks/agent`, {
@@ -205,31 +164,7 @@ function wakeAgent(text, logger, options = {}) {
205
164
  body: JSON.stringify({ prompt: text, sessionKey })
206
165
  }).catch(() => { });
207
166
  }
208
- function getHooksToken() {
209
- let token = process['env'].OPENCLAW_HOOKS_TOKEN || null;
210
- if (!token) {
211
- try {
212
- const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
213
- if (fs.existsSync(configPath)) {
214
- const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
215
- token = config.gateway?.hooksToken || null;
216
- }
217
- }
218
- catch { }
219
- }
220
- return token;
221
- }
222
- function categorizeEvent(event) {
223
- const base = { ts: Date.now(), from: event.from?.slice(0, 16), fullFrom: event.from };
224
- if (event.action === 'queued-for-agent' && event.satoshisReceived) {
225
- return { ...base, type: 'incoming_payment', emoji: '💰', serviceId: event.serviceId, sats: event.satoshisReceived, requestId: event.id, message: `Received ${event.satoshisReceived} sats for ${event.serviceId}` };
226
- }
227
- if (event.type === 'service-response' && event.action === 'received') {
228
- return { ...base, type: 'response_received', emoji: '📬', serviceId: event.serviceId, status: event.status, result: event.result, requestId: event.requestId, message: event.formatted || `Response received for ${event.serviceId}: ${event.status}` };
229
- }
230
- return null;
231
- }
232
- function startBackgroundService(env, cliPath, api) {
167
+ function startBackgroundService(config, api) {
233
168
  if (backgroundProcess)
234
169
  return;
235
170
  serviceRunning = true;
@@ -237,10 +172,17 @@ function startBackgroundService(env, cliPath, api) {
237
172
  if (serviceRunning)
238
173
  wokenRequests.clear();
239
174
  }, 5 * 60 * 1000);
240
- function spawnConnect() {
175
+ async function spawnConnect() {
241
176
  if (!serviceRunning)
242
177
  return;
243
- const proc = spawn_orig('node', [cliPath, 'connect'], { env, stdio: ['ignore', 'pipe', 'pipe'] });
178
+ const { spawn } = await import('node:child_process');
179
+ const base = __dirname.endsWith('dist') ? __dirname : path.join(__dirname, 'dist');
180
+ const cliPath = path.join(base, 'src', 'cli.js');
181
+ const env = { ...process['env'] };
182
+ env.BSV_WALLET_DIR = config.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet');
183
+ env.OVERLAY_URL = config.overlayUrl || 'https://clawoverlay.com';
184
+ env.BSV_NETWORK = config.network || env.BSV_NETWORK || 'mainnet';
185
+ const proc = spawn('node', [cliPath, 'connect'], { env, stdio: ['ignore', 'pipe', 'pipe'] });
244
186
  backgroundProcess = proc;
245
187
  proc.stdout?.on('data', (data) => {
246
188
  const lines = data.toString().split('\n').filter(Boolean);
@@ -259,17 +201,11 @@ function startBackgroundService(env, cliPath, api) {
259
201
  const wakeText = `📬 Overlay service response received!\n\nService: ${event.serviceId}\nFrom: ${event.from}\nStatus: ${event.status}\n\nFull result:\n${JSON.stringify(event.result, null, 2)}`;
260
202
  wakeAgent(wakeText, api.logger, { sessionKey: `hook:openclaw-overlay:resp-${event.requestId || Date.now()}` });
261
203
  }
262
- const notif = categorizeEvent(event);
263
- if (notif) {
264
- const dir = path.join(process['env'].HOME || '', '.openclaw', 'openclaw-overlay');
265
- fs.mkdirSync(dir, { recursive: true });
266
- fs.appendFileSync(path.join(dir, 'activity-feed.jsonl'), JSON.stringify(notif) + '\n');
267
- }
268
204
  }
269
205
  catch { }
270
206
  }
271
207
  });
272
- proc.on('exit', (code) => {
208
+ proc.on('exit', () => {
273
209
  backgroundProcess = null;
274
210
  if (serviceRunning)
275
211
  setTimeout(spawnConnect, 5000);
@@ -288,20 +224,12 @@ function stopBackgroundService() {
288
224
  requestCleanupInterval = null;
289
225
  }
290
226
  wokenRequests.clear();
291
- stopAutoImport();
292
- }
293
- export async function activate(api) {
294
- return register(api);
295
- }
296
- let isInitialized = false;
297
- function getCliPath() {
298
- const base = __dirname.endsWith('dist') ? __dirname : path.join(__dirname, 'dist');
299
- return path.join(base, 'src', 'cli.js');
227
+ if (autoImportInterval) {
228
+ clearInterval(autoImportInterval);
229
+ autoImportInterval = null;
230
+ }
300
231
  }
301
232
  export function register(api) {
302
- if (isInitialized)
303
- return;
304
- isInitialized = true;
305
233
  const entries = api.getConfig?.()?.plugins?.entries || {};
306
234
  const entry = entries['openclaw-overlay-plugin'] || entries['openclaw-overlay'] || {};
307
235
  const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
@@ -353,37 +281,86 @@ export function register(api) {
353
281
  api.registerService({
354
282
  id: "openclaw-overlay-relay",
355
283
  start: async () => {
356
- await ensureCp();
357
- // Initialize service system
358
284
  try {
359
285
  await initializeServiceSystem();
360
286
  }
361
- catch (err) {
362
- if (api.logger)
363
- api.logger.warn(`[overlay] Service system initialization failed: ${err.message}`);
364
- }
365
- const env = buildEnvironment(pluginConfig);
366
- const cliPath = getCliPath();
367
- startBackgroundService(env, cliPath, api);
368
- startAutoImport(env, cliPath, api);
287
+ catch { }
288
+ startBackgroundService(pluginConfig, api);
289
+ startAutoImport(pluginConfig, api);
369
290
  },
370
291
  stop: () => stopBackgroundService()
371
292
  });
372
293
  // 4. CLI
373
294
  api.registerCli(({ program }) => {
374
295
  const overlay = program.command("overlay").description("BSV Overlay Network management");
375
- overlay.command("status").action(async () => {
376
- await ensureCp();
377
- const result = await handleStatus(buildEnvironment(pluginConfig), getCliPath());
378
- console.log(JSON.stringify(result, null, 2));
296
+ overlay.command("status").description("Show identity and balance").action(async () => {
297
+ applyConfigToEnv(pluginConfig);
298
+ const res = await cmdStatus();
299
+ console.log(JSON.stringify(res.data, null, 2));
300
+ });
301
+ overlay.command("balance").description("Show current wallet balance").action(async () => {
302
+ applyConfigToEnv(pluginConfig);
303
+ const res = await cmdBalance();
304
+ console.log(JSON.stringify(res.data, null, 2));
379
305
  });
380
- overlay.command("balance").action(async () => {
381
- await ensureCp();
382
- const result = await handleBalance(buildEnvironment(pluginConfig), getCliPath());
383
- console.log(JSON.stringify(result, null, 2));
306
+ overlay.command("discover").description("Find agents and services").option("-s, --service <type>", "Filter by service type").option("-a, --agent <name>", "Filter by agent name").action(async (options) => {
307
+ applyConfigToEnv(pluginConfig);
308
+ const args = [];
309
+ if (options.service)
310
+ args.push('--service', options.service);
311
+ if (options.agent)
312
+ args.push('--agent', options.agent);
313
+ const res = await cmdDiscover(args);
314
+ console.log(JSON.stringify(res.data, null, 2));
384
315
  });
385
316
  }, { commands: ["overlay"] });
386
317
  }
318
+ async function executeOverlayAction(params, config, api) {
319
+ const { action } = params;
320
+ applyConfigToEnv(config);
321
+ switch (action) {
322
+ case "request": {
323
+ const { service, input } = params;
324
+ const walletDir = config?.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet');
325
+ const discoverOutput = await cmdDiscover(['--service', service]);
326
+ const providers = discoverOutput.data.services;
327
+ if (!providers || providers.length === 0)
328
+ throw new Error(`No providers found for ${service}`);
329
+ providers.sort((a, b) => (a.pricing?.amountSats || 0) - (b.pricing?.amountSats || 0));
330
+ const best = providers[0];
331
+ const price = best.pricing?.amountSats || 0;
332
+ const budget = checkBudget(walletDir, price, config.dailyBudgetSats || 5000);
333
+ if (!budget.allowed)
334
+ throw new Error("Budget exceeded");
335
+ const output = await cmdRequestService(best.identityKey, service, price.toString(), input ? JSON.stringify(input) : undefined);
336
+ recordSpend(walletDir, price, service, best.name);
337
+ return { status: "sent", requestId: output.data?.messageId, message: `Request sent to ${best.name} for ${price} sats.` };
338
+ }
339
+ case "discover": return (await cmdDiscover(params.service ? ['--service', params.service] : [])).data;
340
+ case "balance": return (await cmdBalance()).data;
341
+ case "status": {
342
+ const identity = await cmdIdentity();
343
+ const balance = await cmdBalance();
344
+ return { identity: identity.data, balance: balance.data };
345
+ }
346
+ case "onboard": {
347
+ await cmdSetup();
348
+ const addr = (await cmdAddress()).data.address;
349
+ const bal = (await cmdBalance()).data.walletBalance;
350
+ if (bal < 1000)
351
+ return { funded: false, address: addr, message: "Please fund 1000 sats." };
352
+ await cmdRegister();
353
+ return { funded: true, registered: true, message: "Onboarding complete." };
354
+ }
355
+ case "pending-requests": return (await cmdServiceQueue()).data;
356
+ case "fulfill": {
357
+ const { requestId, recipientKey, serviceId, result } = params;
358
+ return (await cmdRespondService(requestId, recipientKey, serviceId, JSON.stringify(result))).data;
359
+ }
360
+ case "unregister": return (await cmdUnregister()).data;
361
+ default: throw new Error(`Unknown action: ${action}`);
362
+ }
363
+ }
387
364
  export const plugin = {
388
365
  id: "openclaw-overlay-plugin",
389
366
  name: "BSV Overlay Network",
@@ -392,93 +369,3 @@ export const plugin = {
392
369
  register: register
393
370
  };
394
371
  export default register;
395
- async function executeOverlayAction(params, config, api) {
396
- await ensureCp();
397
- const { action } = params;
398
- const env = buildEnvironment(config);
399
- const cliPath = getCliPath();
400
- switch (action) {
401
- case "request": return await handleServiceRequest(params, env, cliPath, config, api);
402
- case "discover": return await handleDiscover(params, env, cliPath);
403
- case "balance": return await handleBalance(env, cliPath);
404
- case "status": return await handleStatus(env, cliPath);
405
- case "onboard": return await handleOnboard(params, env, cliPath);
406
- case "pending-requests": return await handlePendingRequests(env, cliPath);
407
- case "fulfill": return await handleFulfill(params, env, cliPath);
408
- default: throw new Error(`Unknown action: ${action}`);
409
- }
410
- }
411
- async function handleServiceRequest(params, env, cliPath, config, api) {
412
- const { service, identityKey: targetKey, input } = params;
413
- const walletDir = config?.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet');
414
- const discoverResult = await execFileAsync('node', [cliPath, 'discover', '--service', service], { env });
415
- const discoverOutput = parseCliOutput(discoverResult.stdout);
416
- const providers = discoverOutput.data.services;
417
- if (!providers || providers.length === 0)
418
- throw new Error(`No providers found for ${service}`);
419
- providers.sort((a, b) => (a.pricing?.amountSats || 0) - (b.pricing?.amountSats || 0));
420
- const best = providers[0];
421
- const price = best.pricing?.amountSats || 0;
422
- const budget = checkBudget(walletDir, price, config.dailyBudgetSats || 5000);
423
- if (!budget.allowed)
424
- throw new Error("Budget exceeded");
425
- const requestArgs = [cliPath, 'request-service', best.identityKey, service, price.toString()];
426
- if (input)
427
- requestArgs.push(JSON.stringify(input));
428
- const res = await execFileAsync('node', requestArgs, { env });
429
- const output = parseCliOutput(res.stdout);
430
- recordSpend(walletDir, price, service, best.name);
431
- return { status: "sent", requestId: output.data?.messageId, message: `Request sent to ${best.name} for ${price} sats.` };
432
- }
433
- async function handleDiscover(params, env, cliPath) {
434
- const args = [cliPath, 'discover'];
435
- if (params.service)
436
- args.push('--service', params.service);
437
- const result = await execFileAsync('node', args, { env });
438
- return parseCliOutput(result.stdout).data;
439
- }
440
- async function handleBalance(env, cliPath) {
441
- const result = await execFileAsync('node', [cliPath, 'balance'], { env });
442
- return parseCliOutput(result.stdout).data;
443
- }
444
- async function handleStatus(env, cliPath) {
445
- const identity = parseCliOutput((await execFileAsync('node', [cliPath, 'identity'], { env })).stdout);
446
- const balance = parseCliOutput((await execFileAsync('node', [cliPath, 'balance'], { env })).stdout);
447
- return { identity: identity.data, balance: balance.data };
448
- }
449
- async function handleOnboard(params, env, cliPath) {
450
- await execFileAsync('node', [cliPath, 'setup'], { env });
451
- const addr = parseCliOutput((await execFileAsync('node', [cliPath, 'address'], { env })).stdout).data.address;
452
- const bal = parseCliOutput((await execFileAsync('node', [cliPath, 'balance'], { env })).stdout).data.walletBalance;
453
- if (bal < 1000)
454
- return { funded: false, address: addr, message: "Please fund 1000 sats." };
455
- await execFileAsync('node', [cliPath, 'register'], { env });
456
- return { funded: true, registered: true, message: "Onboarding complete." };
457
- }
458
- async function handlePendingRequests(env, cliPath) {
459
- const result = await execFileAsync('node', [cliPath, 'service-queue'], { env });
460
- return parseCliOutput(result.stdout).data;
461
- }
462
- async function handleFulfill(params, env, cliPath) {
463
- const { requestId, recipientKey, serviceId, result } = params;
464
- const res = await execFileAsync('node', [cliPath, 'respond-service', requestId, recipientKey, serviceId, JSON.stringify(result)], { env });
465
- return parseCliOutput(res.stdout).data;
466
- }
467
- function buildEnvironment(config) {
468
- const env = { ...process['env'] };
469
- env.BSV_WALLET_DIR = config.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet');
470
- env.OVERLAY_URL = config.overlayUrl || 'https://clawoverlay.com';
471
- env.BSV_NETWORK = config.network || env.BSV_NETWORK || 'mainnet';
472
- env.BSV_ARC_URL = config.arcUrl || (env.BSV_NETWORK === 'testnet' ? 'https://testnet.arc.gorillapool.io' : 'https://arc.gorillapool.io');
473
- env.AGENT_NAME = config.agentName || 'openclaw-agent';
474
- return env;
475
- }
476
- function parseCliOutput(stdout) {
477
- try {
478
- const str = typeof stdout === 'string' ? stdout : String(stdout || '');
479
- return JSON.parse(str.trim());
480
- }
481
- catch (error) {
482
- throw new Error(`Failed to parse CLI output: ${error.message}`);
483
- }
484
- }
package/dist/src/cli.js CHANGED
@@ -8,7 +8,7 @@
8
8
  // Must be set before any imports that might load dotenv
9
9
  process['en' + 'v'].DOTENV_CONFIG_QUIET = 'true';
10
10
  // Dynamic import to ensure env var is set first
11
- import('./cli-main.js');
11
+ await import('./cli-main.js');
12
12
  // Before importing the library
13
13
  globalThis.window = { fetch: globalThis.fetch };
14
14
  export {};
@@ -24,12 +24,12 @@ export declare function loadBaemailConfig(): Promise<any>;
24
24
  /**
25
25
  * List recent baemail deliveries.
26
26
  */
27
- export declare function cmdBaemailLog(limitStr?: string): Promise<never>;
28
- export declare function cmdBaemailSetup(priceSatsStr: string, prioritySats?: string, urgentSats?: string, channel?: string): Promise<never>;
29
- export declare function cmdBaemailConfig(): Promise<never>;
30
- export declare function cmdBaemailBlock(pubkey: string): Promise<never>;
31
- export declare function cmdBaemailUnblock(pubkey: string): Promise<never>;
27
+ export declare function cmdBaemailLog(limitStr?: string): Promise<any>;
28
+ export declare function cmdBaemailSetup(priceSatsStr: string, prioritySats?: string, urgentSats?: string, channel?: string): Promise<any>;
29
+ export declare function cmdBaemailConfig(): Promise<any>;
30
+ export declare function cmdBaemailBlock(pubkey: string): Promise<any>;
31
+ export declare function cmdBaemailUnblock(pubkey: string): Promise<any>;
32
32
  /**
33
33
  * Refund a failed baemail delivery.
34
34
  */
35
- export declare function cmdBaemailRefund(requestId: string | undefined): Promise<never>;
35
+ export declare function cmdBaemailRefund(requestId: string | undefined): Promise<any>;
@@ -4,8 +4,8 @@
4
4
  /**
5
5
  * Inbox command: fetch pending messages.
6
6
  */
7
- export declare function cmdInbox(args: string[]): Promise<never>;
7
+ export declare function cmdInbox(args: string[]): Promise<any>;
8
8
  /**
9
9
  * Ack command: acknowledge processed messages.
10
10
  */
11
- export declare function cmdAck(messageIds: string[]): Promise<never>;
11
+ export declare function cmdAck(messageIds: string[]): Promise<any>;
@@ -4,4 +4,4 @@
4
4
  /**
5
5
  * Poll command: fetch all pending messages and process them.
6
6
  */
7
- export declare function cmdPoll(): Promise<never>;
7
+ export declare function cmdPoll(): Promise<any>;
@@ -4,4 +4,4 @@
4
4
  /**
5
5
  * Send command: send a typed message to another agent.
6
6
  */
7
- export declare function cmdSend(targetKey: string | undefined, type: string | undefined, payloadStr: string | undefined): Promise<never>;
7
+ export declare function cmdSend(targetKey: string | undefined, type: string | undefined, payloadStr: string | undefined): Promise<any>;
@@ -2,11 +2,12 @@
2
2
  * JSON output helpers for CLI commands.
3
3
  * All CLI output follows the { success, data/error } wrapper format.
4
4
  */
5
+ export declare function setNoExit(value: boolean): void;
5
6
  /**
6
- * Output a successful result and exit.
7
+ * Output a successful result and exit (unless noExit is set).
7
8
  */
8
- export declare function ok<T>(data: T): never;
9
+ export declare function ok<T>(data: T): any;
9
10
  /**
10
- * Output an error and exit.
11
+ * Output an error and exit (unless noExit is set).
11
12
  */
12
- export declare function fail(error: string | Error): never;
13
+ export declare function fail(error: string | Error): any;
@@ -2,18 +2,27 @@
2
2
  * JSON output helpers for CLI commands.
3
3
  * All CLI output follows the { success, data/error } wrapper format.
4
4
  */
5
+ // Global flag to prevent exit when used as a library
6
+ let noExitFlag = false;
7
+ export function setNoExit(value) {
8
+ noExitFlag = value;
9
+ }
5
10
  /**
6
- * Output a successful result and exit.
11
+ * Output a successful result and exit (unless noExit is set).
7
12
  */
8
13
  export function ok(data) {
14
+ if (noExitFlag)
15
+ return { success: true, data };
9
16
  console.log(JSON.stringify({ success: true, data }));
10
17
  process.exit(0);
11
18
  }
12
19
  /**
13
- * Output an error and exit.
20
+ * Output an error and exit (unless noExit is set).
14
21
  */
15
22
  export function fail(error) {
16
23
  const message = error instanceof Error ? error.message : String(error);
24
+ if (noExitFlag)
25
+ return { success: false, error: message };
17
26
  console.log(JSON.stringify({ success: false, error: message }));
18
27
  process.exit(1);
19
28
  }
@@ -8,9 +8,9 @@
8
8
  * Advertise a SHIP record.
9
9
  * Announce that you host a specific Topic Manager (tm_).
10
10
  */
11
- export declare function cmdAdvertiseSHIP(domain?: string, topic?: string): Promise<never>;
11
+ export declare function cmdAdvertiseSHIP(domain?: string, topic?: string): Promise<any>;
12
12
  /**
13
13
  * Advertise a SLAP record.
14
14
  * Announce that you host a specific Lookup Service (ls_).
15
15
  */
16
- export declare function cmdAdvertiseSLAP(domain?: string, service?: string): Promise<never>;
16
+ export declare function cmdAdvertiseSLAP(domain?: string, service?: string): Promise<any>;
@@ -4,4 +4,4 @@
4
4
  /**
5
5
  * Discover command: query the overlay for agents and services.
6
6
  */
7
- export declare function cmdDiscover(args: string[]): Promise<never>;
7
+ export declare function cmdDiscover(args: string[]): Promise<any>;
@@ -12,8 +12,8 @@
12
12
  /**
13
13
  * Register command: register this agent on the overlay network.
14
14
  */
15
- export declare function cmdRegister(): Promise<never>;
15
+ export declare function cmdRegister(): Promise<any>;
16
16
  /**
17
17
  * Unregister command: submit revocation tx to remove agent from overlay network.
18
18
  */
19
- export declare function cmdUnregister(): Promise<never>;
19
+ export declare function cmdUnregister(): Promise<any>;
@@ -14,16 +14,16 @@
14
14
  /**
15
15
  * Services command: list currently advertised services.
16
16
  */
17
- export declare function cmdServices(): Promise<never>;
17
+ export declare function cmdServices(): Promise<any>;
18
18
  /**
19
19
  * Advertise command: add a new service advertisement.
20
20
  */
21
- export declare function cmdAdvertise(serviceId: string | undefined, name: string | undefined, priceSatsStr: string | undefined, description?: string): Promise<never>;
21
+ export declare function cmdAdvertise(serviceId: string | undefined, name: string | undefined, priceSatsStr: string | undefined, description?: string): Promise<any>;
22
22
  /**
23
23
  * Remove command: remove a service from local registry.
24
24
  */
25
- export declare function cmdRemove(serviceId: string | undefined): Promise<never>;
25
+ export declare function cmdRemove(serviceId: string | undefined): Promise<any>;
26
26
  /**
27
27
  * Readvertise command: update an existing service advertisement.
28
28
  */
29
- export declare function cmdReadvertise(serviceId: string | undefined, name?: string, priceSatsStr?: string, description?: string): Promise<never>;
29
+ export declare function cmdReadvertise(serviceId: string | undefined, name?: string, priceSatsStr?: string, description?: string): Promise<any>;