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.
- package/dist/index.d.ts +0 -1
- package/dist/index.js +118 -231
- package/dist/src/cli.js +1 -1
- package/dist/src/scripts/baemail/commands.d.ts +6 -6
- package/dist/src/scripts/messaging/inbox.d.ts +2 -2
- package/dist/src/scripts/messaging/poll.d.ts +1 -1
- package/dist/src/scripts/messaging/send.d.ts +1 -1
- package/dist/src/scripts/output.d.ts +5 -4
- package/dist/src/scripts/output.js +11 -2
- package/dist/src/scripts/overlay/advertisement.d.ts +2 -2
- package/dist/src/scripts/overlay/discover.d.ts +1 -1
- package/dist/src/scripts/overlay/registration.d.ts +2 -2
- package/dist/src/scripts/overlay/services.d.ts +4 -4
- package/dist/src/scripts/payment/commands.d.ts +3 -3
- package/dist/src/scripts/services/queue.d.ts +2 -2
- package/dist/src/scripts/services/request.d.ts +1 -1
- package/dist/src/scripts/services/respond.d.ts +2 -2
- package/dist/src/scripts/wallet/balance.d.ts +2 -2
- package/dist/src/scripts/wallet/setup.d.ts +4 -4
- package/dist/src/scripts/x-verification/commands.d.ts +6 -6
- package/index.ts +117 -244
- package/openclaw.plugin.json +2 -2
- package/package.json +1 -1
- package/src/cli.ts +1 -1
- package/src/scripts/baemail/commands.ts +6 -6
- package/src/scripts/messaging/inbox.ts +2 -2
- package/src/scripts/messaging/poll.ts +1 -1
- package/src/scripts/messaging/send.ts +1 -1
- package/src/scripts/output.ts +13 -4
- package/src/scripts/overlay/advertisement.ts +2 -2
- package/src/scripts/overlay/discover.ts +1 -1
- package/src/scripts/overlay/registration.ts +2 -2
- package/src/scripts/overlay/services.ts +4 -4
- package/src/scripts/payment/commands.ts +3 -3
- package/src/scripts/services/queue.ts +2 -2
- package/src/scripts/services/request.ts +1 -1
- package/src/scripts/services/respond.ts +2 -2
- package/src/scripts/wallet/balance.ts +2 -2
- package/src/scripts/wallet/setup.ts +4 -4
- package/src/scripts/x-verification/commands.ts +6 -6
package/dist/index.d.ts
CHANGED
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
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
|
-
|
|
83
|
-
|
|
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
|
-
|
|
86
|
-
const addrOutput =
|
|
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;
|
|
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
|
-
|
|
112
|
-
const importOutput =
|
|
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(
|
|
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
|
-
|
|
132
|
-
const regOutput =
|
|
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(
|
|
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
|
|
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
|
-
|
|
171
|
-
|
|
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
|
|
186
|
-
|
|
187
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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', (
|
|
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
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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
|
|
362
|
-
|
|
363
|
-
|
|
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
|
-
|
|
377
|
-
const
|
|
378
|
-
console.log(JSON.stringify(
|
|
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("
|
|
381
|
-
|
|
382
|
-
const
|
|
383
|
-
|
|
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<
|
|
28
|
-
export declare function cmdBaemailSetup(priceSatsStr: string, prioritySats?: string, urgentSats?: string, channel?: string): Promise<
|
|
29
|
-
export declare function cmdBaemailConfig(): Promise<
|
|
30
|
-
export declare function cmdBaemailBlock(pubkey: string): Promise<
|
|
31
|
-
export declare function cmdBaemailUnblock(pubkey: string): Promise<
|
|
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<
|
|
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<
|
|
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<
|
|
11
|
+
export declare function cmdAck(messageIds: string[]): 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<
|
|
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):
|
|
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):
|
|
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<
|
|
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<
|
|
16
|
+
export declare function cmdAdvertiseSLAP(domain?: string, service?: 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<
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
29
|
+
export declare function cmdReadvertise(serviceId: string | undefined, name?: string, priceSatsStr?: string, description?: string): Promise<any>;
|