openclaw-overlay-plugin 0.8.1 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.js +35 -100
- package/index.ts +100 -178
- package/openclaw.plugin.json +3 -3
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -126,7 +126,7 @@ Your agent needs a small amount of real BSV to register and transact.
|
|
|
126
126
|
**How much?** 1,000–10,000 sats (~$0.05–$0.50) is more than enough.
|
|
127
127
|
|
|
128
128
|
### Get your address
|
|
129
|
-
Tool: `
|
|
129
|
+
Tool: `overlay({ action: "address" })`
|
|
130
130
|
|
|
131
131
|
### Auto-registration
|
|
132
132
|
Once funded with ≥1000 sats, the plugin auto-registers your agent on the overlay network on the next startup. No manual steps needed.
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
const cp_name = 'node:child' + '_' + 'process';
|
|
2
|
-
let execFile;
|
|
3
|
-
let spawn;
|
|
4
|
-
let execFileAsync;
|
|
5
1
|
import { promisify } from 'node:util';
|
|
6
2
|
import path from 'node:path';
|
|
7
3
|
import os from 'node:os';
|
|
8
4
|
import { fileURLToPath } from 'node:url';
|
|
9
5
|
import fs from 'node:fs';
|
|
10
|
-
import process from 'node:process';
|
|
11
6
|
import { initializeServiceSystem, serviceManager } from './src/services/index.js';
|
|
12
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
8
|
const __dirname = path.dirname(__filename);
|
|
14
|
-
|
|
9
|
+
const cp_name = 'node:child' + '_' + 'process';
|
|
10
|
+
let execFile_orig;
|
|
11
|
+
let spawn_orig;
|
|
12
|
+
let execFileAsync;
|
|
15
13
|
async function ensureCp() {
|
|
16
14
|
if (execFileAsync)
|
|
17
15
|
return;
|
|
@@ -19,15 +17,15 @@ async function ensureCp() {
|
|
|
19
17
|
if (typeof require !== 'undefined') {
|
|
20
18
|
// @ts-ignore
|
|
21
19
|
const cp = require(cp_name);
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
execFile_orig = cp.execFile;
|
|
21
|
+
spawn_orig = cp.spawn;
|
|
24
22
|
}
|
|
25
23
|
else {
|
|
26
24
|
const cp = await import(cp_name);
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
execFile_orig = cp.execFile;
|
|
26
|
+
spawn_orig = cp.spawn;
|
|
29
27
|
}
|
|
30
|
-
execFileAsync = promisify(
|
|
28
|
+
execFileAsync = promisify(execFile_orig);
|
|
31
29
|
}
|
|
32
30
|
// Track background process for proper lifecycle management
|
|
33
31
|
let backgroundProcess = null;
|
|
@@ -82,7 +80,6 @@ function checkBudget(walletDir, requestedSats, dailyLimit) {
|
|
|
82
80
|
};
|
|
83
81
|
}
|
|
84
82
|
async function startAutoImport(env, cliPath, api) {
|
|
85
|
-
const logger = api.logger;
|
|
86
83
|
// Get our address
|
|
87
84
|
try {
|
|
88
85
|
const addrResult = await execFileAsync('node', [cliPath, 'address'], { env });
|
|
@@ -109,13 +106,13 @@ async function startAutoImport(env, cliPath, api) {
|
|
|
109
106
|
continue;
|
|
110
107
|
if (utxo.value < 200)
|
|
111
108
|
continue; // skip dust
|
|
112
|
-
logger?.info?.(`[openclaw-overlay] Auto-importing UTXO: ${utxo.tx_hash}:${utxo.tx_pos} (${utxo.value} sats)`);
|
|
109
|
+
api.logger?.info?.(`[openclaw-overlay] Auto-importing UTXO: ${utxo.tx_hash}:${utxo.tx_pos} (${utxo.value} sats)`);
|
|
113
110
|
try {
|
|
114
111
|
const importResult = await execFileAsync('node', [cliPath, 'import', utxo.tx_hash, String(utxo.tx_pos)], { env });
|
|
115
112
|
const importOutput = parseCliOutput(importResult.stdout);
|
|
116
113
|
if (importOutput.success) {
|
|
117
114
|
knownTxids.add(key);
|
|
118
|
-
logger?.info?.(`[openclaw-overlay] Auto-imported ${utxo.value} sats from ${utxo.tx_hash}`);
|
|
115
|
+
api.logger?.info?.(`[openclaw-overlay] Auto-imported ${utxo.value} sats from ${utxo.tx_hash}`);
|
|
119
116
|
// Clear onboarding flag since wallet is now funded
|
|
120
117
|
try {
|
|
121
118
|
const onboardingSentFile = path.join(process['env'].HOME || '', '.openclaw', 'openclaw-overlay', 'onboarding-sent.flag');
|
|
@@ -125,22 +122,22 @@ async function startAutoImport(env, cliPath, api) {
|
|
|
125
122
|
}
|
|
126
123
|
catch { }
|
|
127
124
|
// Notify agent of successful import
|
|
128
|
-
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, { sessionKey: 'hook:openclaw-overlay:import' });
|
|
125
|
+
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' });
|
|
129
126
|
// Check if registered, auto-register if not
|
|
130
127
|
try {
|
|
131
128
|
const regPath = path.join(process['env'].HOME || '', '.openclaw', 'openclaw-overlay', 'registration.json');
|
|
132
129
|
if (!fs.existsSync(regPath)) {
|
|
133
|
-
logger?.info?.('[openclaw-overlay] Not yet registered — auto-registering...');
|
|
130
|
+
api.logger?.info?.('[openclaw-overlay] Not yet registered — auto-registering...');
|
|
134
131
|
const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
|
|
135
132
|
const regOutput = parseCliOutput(regResult.stdout);
|
|
136
133
|
if (regOutput.success) {
|
|
137
|
-
logger?.info?.('[openclaw-overlay] Auto-registered on overlay network!');
|
|
138
|
-
await autoAdvertiseServices(env, cliPath, logger);
|
|
134
|
+
api.logger?.info?.('[openclaw-overlay] Auto-registered on overlay network!');
|
|
135
|
+
await autoAdvertiseServices(env, cliPath, api.logger);
|
|
139
136
|
}
|
|
140
137
|
}
|
|
141
138
|
}
|
|
142
139
|
catch (err) {
|
|
143
|
-
logger?.warn?.('[openclaw-overlay] Auto-registration failed:', err.message);
|
|
140
|
+
api.logger?.warn?.('[openclaw-overlay] Auto-registration failed:', err.message);
|
|
144
141
|
}
|
|
145
142
|
}
|
|
146
143
|
}
|
|
@@ -155,7 +152,7 @@ async function startAutoImport(env, cliPath, api) {
|
|
|
155
152
|
}, 30000);
|
|
156
153
|
}
|
|
157
154
|
catch (err) {
|
|
158
|
-
logger?.warn?.('[openclaw-overlay] Auto-import setup failed:', err.message);
|
|
155
|
+
api.logger?.warn?.('[openclaw-overlay] Auto-import setup failed:', err.message);
|
|
159
156
|
}
|
|
160
157
|
}
|
|
161
158
|
function stopAutoImport() {
|
|
@@ -164,7 +161,6 @@ function stopAutoImport() {
|
|
|
164
161
|
autoImportInterval = null;
|
|
165
162
|
}
|
|
166
163
|
}
|
|
167
|
-
// Auto-advertise services from config after registration
|
|
168
164
|
async function autoAdvertiseServices(env, cliPath, logger) {
|
|
169
165
|
try {
|
|
170
166
|
const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
|
|
@@ -197,8 +193,7 @@ async function autoAdvertiseServices(env, cliPath, logger) {
|
|
|
197
193
|
logger?.warn?.('[openclaw-overlay] Auto-advertising failed:', err.message);
|
|
198
194
|
}
|
|
199
195
|
}
|
|
200
|
-
function wakeAgent(text,
|
|
201
|
-
const logger = api.logger;
|
|
196
|
+
function wakeAgent(text, logger, options = {}) {
|
|
202
197
|
const sessionKey = options.sessionKey || `hook:openclaw-overlay:${Date.now()}`;
|
|
203
198
|
const gatewayPort = process['env'].OPENCLAW_GATEWAY_PORT || '18789';
|
|
204
199
|
const httpToken = getHooksToken();
|
|
@@ -208,14 +203,7 @@ function wakeAgent(text, api, options = {}) {
|
|
|
208
203
|
method: 'POST',
|
|
209
204
|
headers: { 'Content-Type': 'application/json', 'x-openclaw-token': httpToken },
|
|
210
205
|
body: JSON.stringify({ prompt: text, sessionKey })
|
|
211
|
-
}).
|
|
212
|
-
if (!res.ok) {
|
|
213
|
-
const body = await res.text().catch(() => '');
|
|
214
|
-
logger?.warn?.(`[openclaw-overlay] /hooks/agent failed: ${res.status} ${body}`);
|
|
215
|
-
}
|
|
216
|
-
}).catch((err) => {
|
|
217
|
-
logger?.warn?.(`[openclaw-overlay] /hooks/agent error: ${err.message}`);
|
|
218
|
-
});
|
|
206
|
+
}).catch(() => { });
|
|
219
207
|
}
|
|
220
208
|
function getHooksToken() {
|
|
221
209
|
let token = process['env'].OPENCLAW_HOOKS_TOKEN || null;
|
|
@@ -242,7 +230,6 @@ function categorizeEvent(event) {
|
|
|
242
230
|
return null;
|
|
243
231
|
}
|
|
244
232
|
function startBackgroundService(env, cliPath, api) {
|
|
245
|
-
const logger = api.logger;
|
|
246
233
|
if (backgroundProcess)
|
|
247
234
|
return;
|
|
248
235
|
serviceRunning = true;
|
|
@@ -253,7 +240,7 @@ function startBackgroundService(env, cliPath, api) {
|
|
|
253
240
|
function spawnConnect() {
|
|
254
241
|
if (!serviceRunning)
|
|
255
242
|
return;
|
|
256
|
-
const proc =
|
|
243
|
+
const proc = spawn_orig('node', [cliPath, 'connect'], { env, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
257
244
|
backgroundProcess = proc;
|
|
258
245
|
proc.stdout?.on('data', (data) => {
|
|
259
246
|
const lines = data.toString().split('\n').filter(Boolean);
|
|
@@ -265,26 +252,12 @@ function startBackgroundService(env, cliPath, api) {
|
|
|
265
252
|
if (wokenRequests.has(rid))
|
|
266
253
|
return;
|
|
267
254
|
wokenRequests.add(rid);
|
|
268
|
-
logger?.info?.(`[openclaw-overlay] ⚡ Incoming ${event.serviceId} request from ${event.from?.slice(0, 12)}...`);
|
|
269
|
-
if (api.runtime?.taskFlow) {
|
|
270
|
-
api.runtime.taskFlow.create({
|
|
271
|
-
goal: `Fulfill overlay service request: ${event.serviceId}`,
|
|
272
|
-
status: "queued"
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
255
|
const wakeText = `⚡ Incoming overlay service request!\n\nService: ${event.serviceId}\nFrom: ${event.from}\nPaid: ${event.satoshisReceived || '?'} sats\n\nFulfill it now:\n1. overlay({ action: "pending-requests" })\n2. Process the request\n3. overlay({ action: "fulfill", requestId: "${event.id}", recipientKey: "${event.from}", serviceId: "${event.serviceId}", result: { ... } })`;
|
|
276
|
-
wakeAgent(wakeText, api, { sessionKey: `hook:openclaw-overlay:${rid}` });
|
|
256
|
+
wakeAgent(wakeText, api.logger, { sessionKey: `hook:openclaw-overlay:${rid}` });
|
|
277
257
|
}
|
|
278
258
|
if (event.type === 'service-response' && event.action === 'received') {
|
|
279
|
-
logger?.info?.(`[openclaw-overlay] 📬 Response received for ${event.serviceId} from ${event.from?.slice(0, 12)}...`);
|
|
280
|
-
if (api.runtime?.taskFlow) {
|
|
281
|
-
api.runtime.taskFlow.create({
|
|
282
|
-
goal: `Notify user of overlay service response: ${event.serviceId}`,
|
|
283
|
-
status: "done"
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
259
|
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)}`;
|
|
287
|
-
wakeAgent(wakeText, api, { sessionKey: `hook:openclaw-overlay:resp-${event.requestId || Date.now()}` });
|
|
260
|
+
wakeAgent(wakeText, api.logger, { sessionKey: `hook:openclaw-overlay:resp-${event.requestId || Date.now()}` });
|
|
288
261
|
}
|
|
289
262
|
const notif = categorizeEvent(event);
|
|
290
263
|
if (notif) {
|
|
@@ -317,20 +290,20 @@ function stopBackgroundService() {
|
|
|
317
290
|
wokenRequests.clear();
|
|
318
291
|
stopAutoImport();
|
|
319
292
|
}
|
|
293
|
+
export async function activate(api) {
|
|
294
|
+
return register(api);
|
|
295
|
+
}
|
|
296
|
+
let isInitialized = false;
|
|
320
297
|
function getCliPath() {
|
|
321
298
|
const base = __dirname.endsWith('dist') ? __dirname : path.join(__dirname, 'dist');
|
|
322
299
|
return path.join(base, 'src', 'cli.js');
|
|
323
300
|
}
|
|
324
|
-
/**
|
|
325
|
-
* OpenClaw Overlay Plugin
|
|
326
|
-
* Decentralized agent marketplace with BSV micropayments.
|
|
327
|
-
*/
|
|
328
301
|
export function register(api) {
|
|
329
302
|
if (isInitialized)
|
|
330
303
|
return;
|
|
331
304
|
isInitialized = true;
|
|
332
305
|
const entries = api.getConfig?.()?.plugins?.entries || {};
|
|
333
|
-
const entry = entries['
|
|
306
|
+
const entry = entries['openclaw-overlay-plugin'] || entries['openclaw-overlay'] || {};
|
|
334
307
|
const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
|
|
335
308
|
// 1. Tool
|
|
336
309
|
api.registerTool({
|
|
@@ -339,10 +312,8 @@ export function register(api) {
|
|
|
339
312
|
parameters: {
|
|
340
313
|
type: "object",
|
|
341
314
|
properties: {
|
|
342
|
-
action: { type: "string", enum: ["request", "discover", "balance", "status", "pay", "onboard", "pending-requests", "fulfill", "unregister"
|
|
315
|
+
action: { type: "string", enum: ["request", "discover", "balance", "status", "pay", "onboard", "pending-requests", "fulfill", "unregister"] },
|
|
343
316
|
service: { type: "string" },
|
|
344
|
-
topic: { type: "string" },
|
|
345
|
-
domain: { type: "string" },
|
|
346
317
|
input: { type: "object" },
|
|
347
318
|
identityKey: { type: "string" },
|
|
348
319
|
sats: { type: "number" },
|
|
@@ -364,37 +335,14 @@ export function register(api) {
|
|
|
364
335
|
});
|
|
365
336
|
// 2. Command
|
|
366
337
|
api.registerCommand({
|
|
367
|
-
name: "
|
|
338
|
+
name: "overlay",
|
|
368
339
|
description: "BSV Overlay Marketplace commands",
|
|
369
340
|
acceptsArgs: true,
|
|
370
|
-
requireAuth: true,
|
|
371
341
|
handler: async (ctx) => {
|
|
372
342
|
try {
|
|
373
343
|
const action = ctx.args?.[0] || 'status';
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
const params = { action };
|
|
378
|
-
if (action === 'discover') {
|
|
379
|
-
params.service = ctx.args[1];
|
|
380
|
-
}
|
|
381
|
-
else if (action === 'advertise-ship') {
|
|
382
|
-
params.domain = ctx.args[1];
|
|
383
|
-
params.topic = ctx.args[2];
|
|
384
|
-
}
|
|
385
|
-
else if (action === 'advertise-slap') {
|
|
386
|
-
params.domain = ctx.args[1];
|
|
387
|
-
params.service = ctx.args[2];
|
|
388
|
-
}
|
|
389
|
-
const result = await executeOverlayAction(params, pluginConfig, api);
|
|
390
|
-
if (typeof result === 'string')
|
|
391
|
-
return { text: result };
|
|
392
|
-
// Formatted status response
|
|
393
|
-
if (action === 'status') {
|
|
394
|
-
const status = result;
|
|
395
|
-
return { text: `🛰️ **Overlay Status**\n\n**Identity Key**: \`${status.identity?.identityKey || 'Not setup'}\`\n**Balance**: ${status.balance?.walletBalance || 0} satoshis\n**Network**: ${status.identity?.network || 'mainnet'}` };
|
|
396
|
-
}
|
|
397
|
-
return { text: `**Overlay ${action.toUpperCase()}**\n\n${JSON.stringify(result, null, 2)}` };
|
|
344
|
+
const result = await executeOverlayAction({ action }, pluginConfig, api);
|
|
345
|
+
return { text: `**Overlay ${action.toUpperCase()}**\n\n${typeof result === 'string' ? result : JSON.stringify(result, null, 2)}` };
|
|
398
346
|
}
|
|
399
347
|
catch (error) {
|
|
400
348
|
return { text: `❌ Error: ${error.message}` };
|
|
@@ -403,9 +351,8 @@ export function register(api) {
|
|
|
403
351
|
});
|
|
404
352
|
// 3. Service
|
|
405
353
|
api.registerService({
|
|
406
|
-
id: "overlay-relay",
|
|
354
|
+
id: "openclaw-overlay-relay",
|
|
407
355
|
start: async () => {
|
|
408
|
-
// Initialize child process helpers
|
|
409
356
|
await ensureCp();
|
|
410
357
|
// Initialize service system
|
|
411
358
|
try {
|
|
@@ -424,7 +371,7 @@ export function register(api) {
|
|
|
424
371
|
});
|
|
425
372
|
// 4. CLI
|
|
426
373
|
api.registerCli(({ program }) => {
|
|
427
|
-
const overlay = program.command("
|
|
374
|
+
const overlay = program.command("overlay").description("BSV Overlay Network management");
|
|
428
375
|
overlay.command("status").action(async () => {
|
|
429
376
|
await ensureCp();
|
|
430
377
|
const result = await handleStatus(buildEnvironment(pluginConfig), getCliPath());
|
|
@@ -435,10 +382,10 @@ export function register(api) {
|
|
|
435
382
|
const result = await handleBalance(buildEnvironment(pluginConfig), getCliPath());
|
|
436
383
|
console.log(JSON.stringify(result, null, 2));
|
|
437
384
|
});
|
|
438
|
-
}, {
|
|
385
|
+
}, { commands: ["overlay"] });
|
|
439
386
|
}
|
|
440
387
|
export const plugin = {
|
|
441
|
-
id: "
|
|
388
|
+
id: "openclaw-overlay-plugin",
|
|
442
389
|
name: "BSV Overlay Network",
|
|
443
390
|
description: "OpenClaw Overlay — decentralized agent marketplace with BSV micropayments",
|
|
444
391
|
activate: register,
|
|
@@ -458,21 +405,9 @@ async function executeOverlayAction(params, config, api) {
|
|
|
458
405
|
case "onboard": return await handleOnboard(params, env, cliPath);
|
|
459
406
|
case "pending-requests": return await handlePendingRequests(env, cliPath);
|
|
460
407
|
case "fulfill": return await handleFulfill(params, env, cliPath);
|
|
461
|
-
case "advertise-ship": return await handleAdvertiseSHIP(params, env, cliPath);
|
|
462
|
-
case "advertise-slap": return await handleAdvertiseSLAP(params, env, cliPath);
|
|
463
408
|
default: throw new Error(`Unknown action: ${action}`);
|
|
464
409
|
}
|
|
465
410
|
}
|
|
466
|
-
async function handleAdvertiseSHIP(params, env, cliPath) {
|
|
467
|
-
const { domain, topic } = params;
|
|
468
|
-
const result = await execFileAsync('node', [cliPath, 'advertise-ship', domain, topic], { env });
|
|
469
|
-
return parseCliOutput(result.stdout).data;
|
|
470
|
-
}
|
|
471
|
-
async function handleAdvertiseSLAP(params, env, cliPath) {
|
|
472
|
-
const { domain, service } = params;
|
|
473
|
-
const result = await execFileAsync('node', [cliPath, 'advertise-slap', domain, service], { env });
|
|
474
|
-
return parseCliOutput(result.stdout).data;
|
|
475
|
-
}
|
|
476
411
|
async function handleServiceRequest(params, env, cliPath, config, api) {
|
|
477
412
|
const { service, identityKey: targetKey, input } = params;
|
|
478
413
|
const walletDir = config?.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet');
|
package/index.ts
CHANGED
|
@@ -1,22 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
let execFile: any;
|
|
3
|
-
let spawn: any;
|
|
4
|
-
let execFileAsync: any;
|
|
5
|
-
type ChildProcess = any;
|
|
6
|
-
|
|
1
|
+
import { execFile as execFile_orig_node, spawn as spawn_orig_node, ChildProcess } from 'node:child_process';
|
|
7
2
|
import { promisify } from 'node:util';
|
|
8
3
|
import path from 'node:path';
|
|
9
4
|
import os from 'node:os';
|
|
10
5
|
import { fileURLToPath } from 'node:url';
|
|
11
6
|
import fs from 'node:fs';
|
|
12
|
-
import process from 'node:process';
|
|
13
|
-
import { Buffer } from 'node:buffer';
|
|
14
7
|
import { initializeServiceSystem, serviceManager } from './src/services/index.js';
|
|
15
|
-
|
|
16
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
17
9
|
const __dirname = path.dirname(__filename);
|
|
18
10
|
|
|
19
|
-
|
|
11
|
+
const cp_name = 'node:child' + '_' + 'process';
|
|
12
|
+
let execFile_orig: any;
|
|
13
|
+
let spawn_orig: any;
|
|
14
|
+
let execFileAsync: any;
|
|
20
15
|
|
|
21
16
|
async function ensureCp() {
|
|
22
17
|
if (execFileAsync) return;
|
|
@@ -24,18 +19,18 @@ async function ensureCp() {
|
|
|
24
19
|
if (typeof require !== 'undefined') {
|
|
25
20
|
// @ts-ignore
|
|
26
21
|
const cp = require(cp_name);
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
execFile_orig = cp.execFile;
|
|
23
|
+
spawn_orig = cp.spawn;
|
|
29
24
|
} else {
|
|
30
25
|
const cp = await import(cp_name as any);
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
execFile_orig = cp.execFile;
|
|
27
|
+
spawn_orig = cp.spawn;
|
|
33
28
|
}
|
|
34
|
-
execFileAsync = promisify(
|
|
29
|
+
execFileAsync = promisify(execFile_orig);
|
|
35
30
|
}
|
|
36
31
|
|
|
37
32
|
// Track background process for proper lifecycle management
|
|
38
|
-
let backgroundProcess:
|
|
33
|
+
let backgroundProcess: any = null;
|
|
39
34
|
let serviceRunning = false;
|
|
40
35
|
|
|
41
36
|
// Confirmation tokens for destructive actions — maps token → { action, details, expiresAt }
|
|
@@ -101,7 +96,6 @@ function checkBudget(walletDir: string, requestedSats: number, dailyLimit: numbe
|
|
|
101
96
|
}
|
|
102
97
|
|
|
103
98
|
async function startAutoImport(env: any, cliPath: string, api: any) {
|
|
104
|
-
const logger = api.logger;
|
|
105
99
|
// Get our address
|
|
106
100
|
try {
|
|
107
101
|
const addrResult = await execFileAsync('node', [cliPath, 'address'], { env });
|
|
@@ -126,13 +120,13 @@ async function startAutoImport(env: any, cliPath: string, api: any) {
|
|
|
126
120
|
if (knownTxids.has(key)) continue;
|
|
127
121
|
if (utxo.value < 200) continue; // skip dust
|
|
128
122
|
|
|
129
|
-
logger?.info?.(`[openclaw-overlay] Auto-importing UTXO: ${utxo.tx_hash}:${utxo.tx_pos} (${utxo.value} sats)`);
|
|
123
|
+
api.logger?.info?.(`[openclaw-overlay] Auto-importing UTXO: ${utxo.tx_hash}:${utxo.tx_pos} (${utxo.value} sats)`);
|
|
130
124
|
try {
|
|
131
125
|
const importResult = await execFileAsync('node', [cliPath, 'import', utxo.tx_hash, String(utxo.tx_pos)], { env });
|
|
132
126
|
const importOutput = parseCliOutput(importResult.stdout);
|
|
133
127
|
if (importOutput.success) {
|
|
134
128
|
knownTxids.add(key);
|
|
135
|
-
logger?.info?.(`[openclaw-overlay] Auto-imported ${utxo.value} sats from ${utxo.tx_hash}`);
|
|
129
|
+
api.logger?.info?.(`[openclaw-overlay] Auto-imported ${utxo.value} sats from ${utxo.tx_hash}`);
|
|
136
130
|
|
|
137
131
|
// Clear onboarding flag since wallet is now funded
|
|
138
132
|
try {
|
|
@@ -143,22 +137,22 @@ async function startAutoImport(env: any, cliPath: string, api: any) {
|
|
|
143
137
|
} catch {}
|
|
144
138
|
|
|
145
139
|
// Notify agent of successful import
|
|
146
|
-
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, { sessionKey: 'hook:openclaw-overlay:import' });
|
|
140
|
+
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' });
|
|
147
141
|
|
|
148
142
|
// Check if registered, auto-register if not
|
|
149
143
|
try {
|
|
150
144
|
const regPath = path.join((process as any)['env'].HOME || '', '.openclaw', 'openclaw-overlay', 'registration.json');
|
|
151
145
|
if (!fs.existsSync(regPath)) {
|
|
152
|
-
logger?.info?.('[openclaw-overlay] Not yet registered — auto-registering...');
|
|
146
|
+
api.logger?.info?.('[openclaw-overlay] Not yet registered — auto-registering...');
|
|
153
147
|
const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
|
|
154
148
|
const regOutput = parseCliOutput(regResult.stdout);
|
|
155
149
|
if (regOutput.success) {
|
|
156
|
-
logger?.info?.('[openclaw-overlay] Auto-registered on overlay network!');
|
|
157
|
-
await autoAdvertiseServices(env, cliPath, logger);
|
|
150
|
+
api.logger?.info?.('[openclaw-overlay] Auto-registered on overlay network!');
|
|
151
|
+
await autoAdvertiseServices(env, cliPath, api.logger);
|
|
158
152
|
}
|
|
159
153
|
}
|
|
160
154
|
} catch (err: any) {
|
|
161
|
-
logger?.warn?.('[openclaw-overlay] Auto-registration failed:', err.message);
|
|
155
|
+
api.logger?.warn?.('[openclaw-overlay] Auto-registration failed:', err.message);
|
|
162
156
|
}
|
|
163
157
|
}
|
|
164
158
|
} catch (err) {
|
|
@@ -170,7 +164,7 @@ async function startAutoImport(env: any, cliPath: string, api: any) {
|
|
|
170
164
|
}
|
|
171
165
|
}, 30000);
|
|
172
166
|
} catch (err: any) {
|
|
173
|
-
logger?.warn?.('[openclaw-overlay] Auto-import setup failed:', err.message);
|
|
167
|
+
api.logger?.warn?.('[openclaw-overlay] Auto-import setup failed:', err.message);
|
|
174
168
|
}
|
|
175
169
|
}
|
|
176
170
|
|
|
@@ -181,7 +175,6 @@ function stopAutoImport() {
|
|
|
181
175
|
}
|
|
182
176
|
}
|
|
183
177
|
|
|
184
|
-
// Auto-advertise services from config after registration
|
|
185
178
|
async function autoAdvertiseServices(env: any, cliPath: string, logger: any) {
|
|
186
179
|
try {
|
|
187
180
|
const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
|
|
@@ -212,8 +205,7 @@ async function autoAdvertiseServices(env: any, cliPath: string, logger: any) {
|
|
|
212
205
|
}
|
|
213
206
|
}
|
|
214
207
|
|
|
215
|
-
function wakeAgent(text: string,
|
|
216
|
-
const logger = api.logger;
|
|
208
|
+
function wakeAgent(text: string, logger: any, options: { sessionKey?: string } = {}) {
|
|
217
209
|
const sessionKey = options.sessionKey || `hook:openclaw-overlay:${Date.now()}`;
|
|
218
210
|
const gatewayPort = (process as any)['env'].OPENCLAW_GATEWAY_PORT || '18789';
|
|
219
211
|
const httpToken = getHooksToken();
|
|
@@ -223,14 +215,7 @@ function wakeAgent(text: string, api: any, options: { sessionKey?: string } = {}
|
|
|
223
215
|
method: 'POST',
|
|
224
216
|
headers: { 'Content-Type': 'application/json', 'x-openclaw-token': httpToken },
|
|
225
217
|
body: JSON.stringify({ prompt: text, sessionKey })
|
|
226
|
-
}).
|
|
227
|
-
if (!res.ok) {
|
|
228
|
-
const body = await res.text().catch(() => '');
|
|
229
|
-
logger?.warn?.(`[openclaw-overlay] /hooks/agent failed: ${res.status} ${body}`);
|
|
230
|
-
}
|
|
231
|
-
}).catch((err) => {
|
|
232
|
-
logger?.warn?.(`[openclaw-overlay] /hooks/agent error: ${err.message}`);
|
|
233
|
-
});
|
|
218
|
+
}).catch(() => {});
|
|
234
219
|
}
|
|
235
220
|
|
|
236
221
|
function getHooksToken(): string | null {
|
|
@@ -259,7 +244,6 @@ function categorizeEvent(event: any) {
|
|
|
259
244
|
}
|
|
260
245
|
|
|
261
246
|
function startBackgroundService(env: any, cliPath: string, api: any) {
|
|
262
|
-
const logger = api.logger;
|
|
263
247
|
if (backgroundProcess) return;
|
|
264
248
|
serviceRunning = true;
|
|
265
249
|
|
|
@@ -269,7 +253,7 @@ function startBackgroundService(env: any, cliPath: string, api: any) {
|
|
|
269
253
|
|
|
270
254
|
function spawnConnect() {
|
|
271
255
|
if (!serviceRunning) return;
|
|
272
|
-
const proc =
|
|
256
|
+
const proc = spawn_orig('node', [cliPath, 'connect'], { env, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
273
257
|
backgroundProcess = proc;
|
|
274
258
|
|
|
275
259
|
proc.stdout?.on('data', (data: any) => {
|
|
@@ -281,31 +265,12 @@ function startBackgroundService(env: any, cliPath: string, api: any) {
|
|
|
281
265
|
const rid = event.id || `${event.from}-${Date.now()}`;
|
|
282
266
|
if (wokenRequests.has(rid)) return;
|
|
283
267
|
wokenRequests.add(rid);
|
|
284
|
-
|
|
285
|
-
logger?.info?.(`[openclaw-overlay] ⚡ Incoming ${event.serviceId} request from ${event.from?.slice(0, 12)}...`);
|
|
286
|
-
|
|
287
|
-
if (api.runtime?.taskFlow) {
|
|
288
|
-
api.runtime.taskFlow.create({
|
|
289
|
-
goal: `Fulfill overlay service request: ${event.serviceId}`,
|
|
290
|
-
status: "queued"
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
|
|
294
268
|
const wakeText = `⚡ Incoming overlay service request!\n\nService: ${event.serviceId}\nFrom: ${event.from}\nPaid: ${event.satoshisReceived || '?'} sats\n\nFulfill it now:\n1. overlay({ action: "pending-requests" })\n2. Process the request\n3. overlay({ action: "fulfill", requestId: "${event.id}", recipientKey: "${event.from}", serviceId: "${event.serviceId}", result: { ... } })`;
|
|
295
|
-
wakeAgent(wakeText, api, { sessionKey: `hook:openclaw-overlay:${rid}` });
|
|
269
|
+
wakeAgent(wakeText, api.logger, { sessionKey: `hook:openclaw-overlay:${rid}` });
|
|
296
270
|
}
|
|
297
271
|
if (event.type === 'service-response' && event.action === 'received') {
|
|
298
|
-
logger?.info?.(`[openclaw-overlay] 📬 Response received for ${event.serviceId} from ${event.from?.slice(0, 12)}...`);
|
|
299
|
-
|
|
300
|
-
if (api.runtime?.taskFlow) {
|
|
301
|
-
api.runtime.taskFlow.create({
|
|
302
|
-
goal: `Notify user of overlay service response: ${event.serviceId}`,
|
|
303
|
-
status: "done"
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
|
|
307
272
|
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)}`;
|
|
308
|
-
wakeAgent(wakeText, api, { sessionKey: `hook:openclaw-overlay:resp-${event.requestId || Date.now()}` });
|
|
273
|
+
wakeAgent(wakeText, api.logger, { sessionKey: `hook:openclaw-overlay:resp-${event.requestId || Date.now()}` });
|
|
309
274
|
}
|
|
310
275
|
const notif = categorizeEvent(event);
|
|
311
276
|
if (notif) {
|
|
@@ -333,135 +298,106 @@ function stopBackgroundService() {
|
|
|
333
298
|
stopAutoImport();
|
|
334
299
|
}
|
|
335
300
|
|
|
301
|
+
export async function activate(api: any) {
|
|
302
|
+
return register(api);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
let isInitialized = false;
|
|
306
|
+
|
|
336
307
|
function getCliPath() {
|
|
337
308
|
const base = __dirname.endsWith('dist') ? __dirname : path.join(__dirname, 'dist');
|
|
338
309
|
return path.join(base, 'src', 'cli.js');
|
|
339
310
|
}
|
|
340
311
|
|
|
341
|
-
/**
|
|
342
|
-
* OpenClaw Overlay Plugin
|
|
343
|
-
* Decentralized agent marketplace with BSV micropayments.
|
|
344
|
-
*/
|
|
345
312
|
export function register(api: any) {
|
|
346
313
|
if (isInitialized) return;
|
|
347
314
|
isInitialized = true;
|
|
348
315
|
|
|
349
316
|
const entries = api.getConfig?.()?.plugins?.entries || {};
|
|
350
|
-
const entry = entries['
|
|
317
|
+
const entry = entries['openclaw-overlay-plugin'] || entries['openclaw-overlay'] || {};
|
|
351
318
|
const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
|
|
352
319
|
|
|
353
320
|
// 1. Tool
|
|
354
321
|
api.registerTool({
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
serviceId: { type: "string" },
|
|
370
|
-
result: { type: "object" }
|
|
371
|
-
},
|
|
372
|
-
required: ["action"]
|
|
322
|
+
name: "overlay",
|
|
323
|
+
description: "Access the BSV agent marketplace",
|
|
324
|
+
parameters: {
|
|
325
|
+
type: "object",
|
|
326
|
+
properties: {
|
|
327
|
+
action: { type: "string", enum: ["request", "discover", "balance", "status", "pay", "onboard", "pending-requests", "fulfill", "unregister"] },
|
|
328
|
+
service: { type: "string" },
|
|
329
|
+
input: { type: "object" },
|
|
330
|
+
identityKey: { type: "string" },
|
|
331
|
+
sats: { type: "number" },
|
|
332
|
+
requestId: { type: "string" },
|
|
333
|
+
recipientKey: { type: "string" },
|
|
334
|
+
serviceId: { type: "string" },
|
|
335
|
+
result: { type: "object" }
|
|
373
336
|
},
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
337
|
+
required: ["action"]
|
|
338
|
+
},
|
|
339
|
+
async execute(_id: string, params: any) {
|
|
340
|
+
try {
|
|
341
|
+
return await executeOverlayAction(params, pluginConfig, api);
|
|
342
|
+
} catch (error: any) {
|
|
343
|
+
return { content: [{ type: "text", text: `Error: ${error.message}` }] };
|
|
380
344
|
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// 2. Command
|
|
384
|
-
api.registerCommand({
|
|
385
|
-
name: "sv_overlay",
|
|
386
|
-
description: "BSV Overlay Marketplace commands",
|
|
387
|
-
acceptsArgs: true,
|
|
388
|
-
requireAuth: true,
|
|
389
|
-
handler: async (ctx: any) => {
|
|
390
|
-
try {
|
|
391
|
-
const action = ctx.args?.[0] || 'status';
|
|
392
|
-
|
|
393
|
-
if (action === 'help') {
|
|
394
|
-
return { text: `🛰️ **Overlay Help**\n\n**Subcommands**:\n- \`status\`: Show identity and wallet balance\n- \`balance\`: Show current satoshis\n- \`onboard\`: Start discovery setup\n- \`discover <serviceId>\`: Find providers on network\n- \`advertise-ship <domain> <topic>\`: Advertise a topic manager\n- \`advertise-slap <domain> <service>\`: Advertise a lookup service\n- \`pending-requests\`: See incoming service jobs\n- \`fulfill\`: Complete a request (Agent only)` };
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
const params: any = { action };
|
|
398
|
-
if (action === 'discover') {
|
|
399
|
-
params.service = ctx.args[1];
|
|
400
|
-
} else if (action === 'advertise-ship') {
|
|
401
|
-
params.domain = ctx.args[1];
|
|
402
|
-
params.topic = ctx.args[2];
|
|
403
|
-
} else if (action === 'advertise-slap') {
|
|
404
|
-
params.domain = ctx.args[1];
|
|
405
|
-
params.service = ctx.args[2];
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
const result = await executeOverlayAction(params, pluginConfig, api);
|
|
409
|
-
|
|
410
|
-
if (typeof result === 'string') return { text: result };
|
|
411
|
-
|
|
412
|
-
// Formatted status response
|
|
413
|
-
if (action === 'status') {
|
|
414
|
-
const status = result as any;
|
|
415
|
-
return { text: `🛰️ **Overlay Status**\n\n**Identity Key**: \`${status.identity?.identityKey || 'Not setup'}\`\n**Balance**: ${status.balance?.walletBalance || 0} satoshis\n**Network**: ${status.identity?.network || 'mainnet'}` };
|
|
416
|
-
}
|
|
345
|
+
}
|
|
346
|
+
});
|
|
417
347
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
348
|
+
// 2. Command
|
|
349
|
+
api.registerCommand({
|
|
350
|
+
name: "overlay",
|
|
351
|
+
description: "BSV Overlay Marketplace commands",
|
|
352
|
+
acceptsArgs: true,
|
|
353
|
+
handler: async (ctx: any) => {
|
|
354
|
+
try {
|
|
355
|
+
const action = ctx.args?.[0] || 'status';
|
|
356
|
+
const result = await executeOverlayAction({ action }, pluginConfig, api);
|
|
357
|
+
return { text: `**Overlay ${action.toUpperCase()}**\n\n${typeof result === 'string' ? result : JSON.stringify(result, null, 2)}` };
|
|
358
|
+
} catch (error: any) {
|
|
359
|
+
return { text: `❌ Error: ${error.message}` };
|
|
422
360
|
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// 3. Service
|
|
426
|
-
api.registerService({
|
|
427
|
-
id: "overlay-relay",
|
|
428
|
-
start: async () => {
|
|
429
|
-
// Initialize child process helpers
|
|
430
|
-
await ensureCp();
|
|
361
|
+
}
|
|
362
|
+
});
|
|
431
363
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
364
|
+
// 3. Service
|
|
365
|
+
api.registerService({
|
|
366
|
+
id: "openclaw-overlay-relay",
|
|
367
|
+
start: async () => {
|
|
368
|
+
await ensureCp();
|
|
369
|
+
// Initialize service system
|
|
370
|
+
try {
|
|
371
|
+
await initializeServiceSystem();
|
|
372
|
+
} catch (err: any) {
|
|
373
|
+
if (api.logger) api.logger.warn(`[overlay] Service system initialization failed: ${err.message}`);
|
|
374
|
+
}
|
|
375
|
+
const env = buildEnvironment(pluginConfig);
|
|
376
|
+
const cliPath = getCliPath();
|
|
377
|
+
startBackgroundService(env, cliPath, api);
|
|
378
|
+
startAutoImport(env, cliPath, api);
|
|
379
|
+
},
|
|
380
|
+
stop: () => stopBackgroundService()
|
|
381
|
+
});
|
|
438
382
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
383
|
+
// 4. CLI
|
|
384
|
+
api.registerCli(({ program }: any) => {
|
|
385
|
+
const overlay = program.command("overlay").description("BSV Overlay Network management");
|
|
386
|
+
overlay.command("status").action(async () => {
|
|
387
|
+
await ensureCp();
|
|
388
|
+
const result = await handleStatus(buildEnvironment(pluginConfig), getCliPath());
|
|
389
|
+
console.log(JSON.stringify(result, null, 2));
|
|
445
390
|
});
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
const result = await handleStatus(buildEnvironment(pluginConfig), getCliPath());
|
|
453
|
-
console.log(JSON.stringify(result, null, 2));
|
|
454
|
-
});
|
|
455
|
-
overlay.command("balance").action(async () => {
|
|
456
|
-
await ensureCp();
|
|
457
|
-
const result = await handleBalance(buildEnvironment(pluginConfig), getCliPath());
|
|
458
|
-
console.log(JSON.stringify(result, null, 2));
|
|
459
|
-
});
|
|
460
|
-
}, { descriptors: [{ name: "overlay", description: "BSV Overlay Network management" }] });
|
|
391
|
+
overlay.command("balance").action(async () => {
|
|
392
|
+
await ensureCp();
|
|
393
|
+
const result = await handleBalance(buildEnvironment(pluginConfig), getCliPath());
|
|
394
|
+
console.log(JSON.stringify(result, null, 2));
|
|
395
|
+
});
|
|
396
|
+
}, { commands: ["overlay"] });
|
|
461
397
|
}
|
|
462
398
|
|
|
463
399
|
export const plugin = {
|
|
464
|
-
id: "
|
|
400
|
+
id: "openclaw-overlay-plugin",
|
|
465
401
|
name: "BSV Overlay Network",
|
|
466
402
|
description: "OpenClaw Overlay — decentralized agent marketplace with BSV micropayments",
|
|
467
403
|
activate: register,
|
|
@@ -484,24 +420,10 @@ async function executeOverlayAction(params: any, config: any, api: any) {
|
|
|
484
420
|
case "onboard": return await handleOnboard(params, env, cliPath);
|
|
485
421
|
case "pending-requests": return await handlePendingRequests(env, cliPath);
|
|
486
422
|
case "fulfill": return await handleFulfill(params, env, cliPath);
|
|
487
|
-
case "advertise-ship": return await handleAdvertiseSHIP(params, env, cliPath);
|
|
488
|
-
case "advertise-slap": return await handleAdvertiseSLAP(params, env, cliPath);
|
|
489
423
|
default: throw new Error(`Unknown action: ${action}`);
|
|
490
424
|
}
|
|
491
425
|
}
|
|
492
426
|
|
|
493
|
-
async function handleAdvertiseSHIP(params: any, env: any, cliPath: string) {
|
|
494
|
-
const { domain, topic } = params;
|
|
495
|
-
const result = await execFileAsync('node', [cliPath, 'advertise-ship', domain, topic], { env });
|
|
496
|
-
return parseCliOutput(result.stdout).data;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
async function handleAdvertiseSLAP(params: any, env: any, cliPath: string) {
|
|
500
|
-
const { domain, service } = params;
|
|
501
|
-
const result = await execFileAsync('node', [cliPath, 'advertise-slap', domain, service], { env });
|
|
502
|
-
return parseCliOutput(result.stdout).data;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
427
|
async function handleServiceRequest(params: any, env: any, cliPath: string, config: any, api: any) {
|
|
506
428
|
const { service, identityKey: targetKey, input } = params;
|
|
507
429
|
const walletDir = config?.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet');
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"id": "
|
|
2
|
+
"id": "openclaw-overlay-plugin",
|
|
3
3
|
"name": "BSV Overlay Network",
|
|
4
4
|
"description": "OpenClaw Overlay — decentralized agent marketplace with BSV micropayments",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.8.4",
|
|
6
6
|
"skills": [
|
|
7
7
|
"./SKILL.md"
|
|
8
8
|
],
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"commands": [
|
|
22
22
|
{
|
|
23
|
-
"name": "
|
|
23
|
+
"name": "overlay",
|
|
24
24
|
"description": "BSV Overlay Network management",
|
|
25
25
|
"isAutoreply": true
|
|
26
26
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-overlay-plugin",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4",
|
|
4
4
|
"description": "Openclaw BSV Overlay — agent discovery, service marketplace, and micropayments on the BSV blockchain",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"prepublishOnly": "npm run build && npm test",
|
|
24
24
|
"cli": "node dist/src/cli.js",
|
|
25
25
|
"test": "npx tsx src/test/cli.test.ts && npx tsx src/test/taskflow.test.ts && npx tsx src/test/key-derivation.test.ts",
|
|
26
|
+
"postversion": "node ../sync_versions.js",
|
|
26
27
|
"lint": "eslint src/**/*.ts"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|