openclaw-overlay-plugin 0.7.33 → 0.7.35
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 +3 -1
- package/SKILL.md +14 -0
- package/dist/index.js +106 -61
- package/dist/src/core/wallet.js +4 -0
- package/dist/src/scripts/baemail/commands.js +17 -6
- package/dist/src/scripts/config.d.ts +1 -1
- package/dist/src/scripts/config.js +3 -3
- package/dist/src/scripts/overlay/discover.js +3 -1
- package/index.ts +103 -63
- package/openclaw.plugin.json +20 -0
- package/package.json +1 -1
- package/src/core/wallet.ts +6 -0
- package/src/scripts/baemail/commands.ts +17 -6
- package/src/scripts/config.ts +3 -3
- package/src/scripts/overlay/discover.ts +3 -1
- package/dist/cli-main.d.ts +0 -7
- package/dist/cli-main.js +0 -192
- package/dist/cli.d.ts +0 -8
- package/dist/cli.js +0 -14
- package/dist/core/config.d.ts +0 -11
- package/dist/core/config.js +0 -13
- package/dist/core/index.d.ts +0 -25
- package/dist/core/index.js +0 -26
- package/dist/core/payment.d.ts +0 -16
- package/dist/core/payment.js +0 -94
- package/dist/core/types.d.ts +0 -94
- package/dist/core/types.js +0 -4
- package/dist/core/verify.d.ts +0 -28
- package/dist/core/verify.js +0 -104
- package/dist/core/wallet.d.ts +0 -99
- package/dist/core/wallet.js +0 -219
- package/dist/scripts/baemail/commands.d.ts +0 -64
- package/dist/scripts/baemail/commands.js +0 -259
- package/dist/scripts/baemail/handler.d.ts +0 -36
- package/dist/scripts/baemail/handler.js +0 -284
- package/dist/scripts/baemail/index.d.ts +0 -5
- package/dist/scripts/baemail/index.js +0 -5
- package/dist/scripts/config.d.ts +0 -48
- package/dist/scripts/config.js +0 -68
- package/dist/scripts/index.d.ts +0 -7
- package/dist/scripts/index.js +0 -7
- package/dist/scripts/messaging/connect.d.ts +0 -8
- package/dist/scripts/messaging/connect.js +0 -114
- package/dist/scripts/messaging/handlers.d.ts +0 -21
- package/dist/scripts/messaging/handlers.js +0 -334
- package/dist/scripts/messaging/inbox.d.ts +0 -11
- package/dist/scripts/messaging/inbox.js +0 -51
- package/dist/scripts/messaging/index.d.ts +0 -8
- package/dist/scripts/messaging/index.js +0 -8
- package/dist/scripts/messaging/poll.d.ts +0 -7
- package/dist/scripts/messaging/poll.js +0 -52
- package/dist/scripts/messaging/send.d.ts +0 -7
- package/dist/scripts/messaging/send.js +0 -43
- package/dist/scripts/output.d.ts +0 -12
- package/dist/scripts/output.js +0 -19
- package/dist/scripts/overlay/discover.d.ts +0 -7
- package/dist/scripts/overlay/discover.js +0 -72
- package/dist/scripts/overlay/index.d.ts +0 -7
- package/dist/scripts/overlay/index.js +0 -7
- package/dist/scripts/overlay/registration.d.ts +0 -19
- package/dist/scripts/overlay/registration.js +0 -176
- package/dist/scripts/overlay/services.d.ts +0 -29
- package/dist/scripts/overlay/services.js +0 -167
- package/dist/scripts/overlay/transaction.d.ts +0 -42
- package/dist/scripts/overlay/transaction.js +0 -103
- package/dist/scripts/payment/build.d.ts +0 -24
- package/dist/scripts/payment/build.js +0 -54
- package/dist/scripts/payment/commands.d.ts +0 -15
- package/dist/scripts/payment/commands.js +0 -73
- package/dist/scripts/payment/index.d.ts +0 -6
- package/dist/scripts/payment/index.js +0 -6
- package/dist/scripts/payment/types.d.ts +0 -56
- package/dist/scripts/payment/types.js +0 -4
- package/dist/scripts/services/index.d.ts +0 -6
- package/dist/scripts/services/index.js +0 -6
- package/dist/scripts/services/queue.d.ts +0 -11
- package/dist/scripts/services/queue.js +0 -28
- package/dist/scripts/services/request.d.ts +0 -7
- package/dist/scripts/services/request.js +0 -82
- package/dist/scripts/services/respond.d.ts +0 -11
- package/dist/scripts/services/respond.js +0 -132
- package/dist/scripts/types.d.ts +0 -107
- package/dist/scripts/types.js +0 -4
- package/dist/scripts/utils/index.d.ts +0 -6
- package/dist/scripts/utils/index.js +0 -6
- package/dist/scripts/utils/merkle.d.ts +0 -12
- package/dist/scripts/utils/merkle.js +0 -47
- package/dist/scripts/utils/storage.d.ts +0 -66
- package/dist/scripts/utils/storage.js +0 -211
- package/dist/scripts/utils/woc.d.ts +0 -26
- package/dist/scripts/utils/woc.js +0 -91
- package/dist/scripts/wallet/balance.d.ts +0 -22
- package/dist/scripts/wallet/balance.js +0 -240
- package/dist/scripts/wallet/identity.d.ts +0 -70
- package/dist/scripts/wallet/identity.js +0 -151
- package/dist/scripts/wallet/index.d.ts +0 -6
- package/dist/scripts/wallet/index.js +0 -6
- package/dist/scripts/wallet/setup.d.ts +0 -15
- package/dist/scripts/wallet/setup.js +0 -105
- package/dist/scripts/x-verification/commands.d.ts +0 -27
- package/dist/scripts/x-verification/commands.js +0 -222
- package/dist/scripts/x-verification/index.d.ts +0 -4
- package/dist/scripts/x-verification/index.js +0 -4
- package/dist/services/built-in/api-proxy/index.d.ts +0 -6
- package/dist/services/built-in/api-proxy/index.js +0 -23
- package/dist/services/built-in/code-develop/index.d.ts +0 -6
- package/dist/services/built-in/code-develop/index.js +0 -23
- package/dist/services/built-in/code-review/index.d.ts +0 -10
- package/dist/services/built-in/code-review/index.js +0 -51
- package/dist/services/built-in/image-analysis/index.d.ts +0 -6
- package/dist/services/built-in/image-analysis/index.js +0 -33
- package/dist/services/built-in/memory-store/index.d.ts +0 -6
- package/dist/services/built-in/memory-store/index.js +0 -22
- package/dist/services/built-in/roulette/index.d.ts +0 -6
- package/dist/services/built-in/roulette/index.js +0 -27
- package/dist/services/built-in/summarize/index.d.ts +0 -6
- package/dist/services/built-in/summarize/index.js +0 -21
- package/dist/services/built-in/tell-joke/handler.d.ts +0 -7
- package/dist/services/built-in/tell-joke/handler.js +0 -122
- package/dist/services/built-in/tell-joke/index.d.ts +0 -9
- package/dist/services/built-in/tell-joke/index.js +0 -31
- package/dist/services/built-in/translate/index.d.ts +0 -6
- package/dist/services/built-in/translate/index.js +0 -21
- package/dist/services/built-in/web-research/index.d.ts +0 -9
- package/dist/services/built-in/web-research/index.js +0 -51
- package/dist/services/index.d.ts +0 -13
- package/dist/services/index.js +0 -14
- package/dist/services/loader.d.ts +0 -77
- package/dist/services/loader.js +0 -292
- package/dist/services/manager.d.ts +0 -86
- package/dist/services/manager.js +0 -255
- package/dist/services/registry.d.ts +0 -98
- package/dist/services/registry.js +0 -204
- package/dist/services/types.d.ts +0 -230
- package/dist/services/types.js +0 -30
- package/dist/test/cli.test.d.ts +0 -7
- package/dist/test/cli.test.js +0 -329
- package/dist/test/comprehensive-overlay.test.d.ts +0 -13
- package/dist/test/comprehensive-overlay.test.js +0 -593
- package/dist/test/key-derivation.test.d.ts +0 -12
- package/dist/test/key-derivation.test.js +0 -86
- package/dist/test/overlay-submit.test.d.ts +0 -10
- package/dist/test/overlay-submit.test.js +0 -460
- package/dist/test/request-response-flow.test.d.ts +0 -5
- package/dist/test/request-response-flow.test.js +0 -209
- package/dist/test/service-system.test.d.ts +0 -5
- package/dist/test/service-system.test.js +0 -190
- package/dist/test/utils/server-logic.d.ts +0 -98
- package/dist/test/utils/server-logic.js +0 -286
- package/dist/test/wallet.test.d.ts +0 -7
- package/dist/test/wallet.test.js +0 -146
package/index.ts
CHANGED
|
@@ -52,7 +52,7 @@ function loadDailySpending(walletDir: string): DailySpending {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
function writeActivityEvent(event: any) {
|
|
55
|
-
const alertDir = path.join(process.env.HOME || '', '.openclaw', '
|
|
55
|
+
const alertDir = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay');
|
|
56
56
|
try {
|
|
57
57
|
fs.mkdirSync(alertDir, { recursive: true });
|
|
58
58
|
fs.appendFileSync(path.join(alertDir, 'activity-feed.jsonl'), JSON.stringify({ ...event, ts: Date.now() }) + '\n');
|
|
@@ -106,41 +106,41 @@ async function startAutoImport(env: any, cliPath: string, logger: any) {
|
|
|
106
106
|
if (knownTxids.has(key)) continue;
|
|
107
107
|
if (utxo.value < 200) continue; // skip dust
|
|
108
108
|
|
|
109
|
-
logger?.info?.(`[
|
|
109
|
+
logger?.info?.(`[openclaw-overlay] Auto-importing UTXO: ${utxo.tx_hash}:${utxo.tx_pos} (${utxo.value} sats)`);
|
|
110
110
|
try {
|
|
111
111
|
const importResult = await execFileAsync('node', [cliPath, 'import', utxo.tx_hash, String(utxo.tx_pos)], { env });
|
|
112
112
|
const importOutput = parseCliOutput(importResult.stdout);
|
|
113
113
|
if (importOutput.success) {
|
|
114
114
|
knownTxids.add(key);
|
|
115
|
-
logger?.info?.(`[
|
|
115
|
+
logger?.info?.(`[openclaw-overlay] Auto-imported ${utxo.value} sats from ${utxo.tx_hash}`);
|
|
116
116
|
|
|
117
117
|
// Clear onboarding flag since wallet is now funded
|
|
118
118
|
try {
|
|
119
|
-
const onboardingSentFile = path.join(process.env.HOME || '', '.openclaw', '
|
|
119
|
+
const onboardingSentFile = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'onboarding-sent.flag');
|
|
120
120
|
if (fs.existsSync(onboardingSentFile)) {
|
|
121
121
|
fs.unlinkSync(onboardingSentFile);
|
|
122
122
|
}
|
|
123
123
|
} catch {}
|
|
124
124
|
|
|
125
125
|
// Notify agent of successful import
|
|
126
|
-
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.`, logger, { sessionKey: 'hook:
|
|
126
|
+
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.`, logger, { sessionKey: 'hook:openclaw-overlay:import' });
|
|
127
127
|
|
|
128
128
|
// Check if registered, auto-register if not
|
|
129
129
|
try {
|
|
130
|
-
const regPath = path.join(process.env.HOME || '', '.openclaw', '
|
|
130
|
+
const regPath = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'registration.json');
|
|
131
131
|
if (!fs.existsSync(regPath)) {
|
|
132
|
-
logger?.info?.('[
|
|
132
|
+
logger?.info?.('[openclaw-overlay] Not yet registered — auto-registering...');
|
|
133
133
|
const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
|
|
134
134
|
const regOutput = parseCliOutput(regResult.stdout);
|
|
135
135
|
if (regOutput.success) {
|
|
136
|
-
logger?.info?.('[
|
|
136
|
+
logger?.info?.('[openclaw-overlay] Auto-registered on overlay network!');
|
|
137
137
|
|
|
138
138
|
// Auto-advertise services from config
|
|
139
139
|
await autoAdvertiseServices(env, cliPath, logger);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
} catch (err: any) {
|
|
143
|
-
logger?.warn?.('[
|
|
143
|
+
logger?.warn?.('[openclaw-overlay] Auto-registration failed:', err.message);
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
} catch (err) {
|
|
@@ -153,7 +153,7 @@ async function startAutoImport(env: any, cliPath: string, logger: any) {
|
|
|
153
153
|
}
|
|
154
154
|
}, 30000); // Check every 30 seconds for faster onboarding
|
|
155
155
|
} catch (err: any) {
|
|
156
|
-
logger?.warn?.('[
|
|
156
|
+
logger?.warn?.('[openclaw-overlay] Auto-import setup failed:', err.message);
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
@@ -179,7 +179,7 @@ async function autoAdvertiseServices(env: any, cliPath: string, logger: any) {
|
|
|
179
179
|
if (!fs.existsSync(configPath)) continue;
|
|
180
180
|
try {
|
|
181
181
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
182
|
-
const pluginConfig = config?.plugins?.entries?.['
|
|
182
|
+
const pluginConfig = config?.plugins?.entries?.['openclaw-overlay']?.config;
|
|
183
183
|
if (pluginConfig?.services && Array.isArray(pluginConfig.services)) {
|
|
184
184
|
servicesToAdvertise = pluginConfig.services;
|
|
185
185
|
break;
|
|
@@ -188,11 +188,11 @@ async function autoAdvertiseServices(env: any, cliPath: string, logger: any) {
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
if (servicesToAdvertise.length === 0) {
|
|
191
|
-
logger?.info?.('[
|
|
191
|
+
logger?.info?.('[openclaw-overlay] No services configured for auto-advertising');
|
|
192
192
|
return;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
logger?.info?.(`[
|
|
195
|
+
logger?.info?.(`[openclaw-overlay] Auto-advertising ${servicesToAdvertise.length} services from config...`);
|
|
196
196
|
|
|
197
197
|
const advertised: string[] = [];
|
|
198
198
|
const failed: string[] = [];
|
|
@@ -214,11 +214,11 @@ async function autoAdvertiseServices(env: any, cliPath: string, logger: any) {
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
if (advertised.length > 0) logger?.info?.(`[
|
|
218
|
-
if (failed.length > 0) logger?.warn?.(`[
|
|
217
|
+
if (advertised.length > 0) logger?.info?.(`[openclaw-overlay] Successfully advertised: ${advertised.join(', ')}`);
|
|
218
|
+
if (failed.length > 0) logger?.warn?.(`[openclaw-overlay] Failed to advertise: ${failed.join(', ')}`);
|
|
219
219
|
|
|
220
220
|
} catch (err: any) {
|
|
221
|
-
logger?.warn?.('[
|
|
221
|
+
logger?.warn?.('[openclaw-overlay] Auto-advertising failed:', err.message);
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
224
|
|
|
@@ -227,12 +227,12 @@ async function autoAdvertiseServices(env: any, cliPath: string, logger: any) {
|
|
|
227
227
|
* This is the standard way to invoke an agent with a specific context.
|
|
228
228
|
*/
|
|
229
229
|
function wakeAgent(text: string, logger: any, options: { sessionKey?: string } = {}) {
|
|
230
|
-
const sessionKey = options.sessionKey || `hook:
|
|
230
|
+
const sessionKey = options.sessionKey || `hook:openclaw-overlay:${Date.now()}`;
|
|
231
231
|
const gatewayPort = getGatewayPort();
|
|
232
232
|
const httpToken = getHooksToken();
|
|
233
233
|
|
|
234
234
|
if (!httpToken) {
|
|
235
|
-
logger?.warn?.('[
|
|
235
|
+
logger?.warn?.('[openclaw-overlay] Skipped wakeAgent: OPENCLAW_HOOKS_TOKEN not set');
|
|
236
236
|
return;
|
|
237
237
|
}
|
|
238
238
|
|
|
@@ -251,14 +251,14 @@ function wakeAgent(text: string, logger: any, options: { sessionKey?: string } =
|
|
|
251
251
|
})
|
|
252
252
|
.then(async (res) => {
|
|
253
253
|
if (res.ok) {
|
|
254
|
-
logger?.info?.(`[
|
|
254
|
+
logger?.info?.(`[openclaw-overlay] Agent invoked via /hooks/agent (session: ${sessionKey})`);
|
|
255
255
|
} else {
|
|
256
256
|
const body = await res.text().catch(() => '');
|
|
257
|
-
logger?.warn?.(`[
|
|
257
|
+
logger?.warn?.(`[openclaw-overlay] /hooks/agent failed: ${res.status} ${body}`);
|
|
258
258
|
}
|
|
259
259
|
})
|
|
260
260
|
.catch((err: any) => {
|
|
261
|
-
logger?.warn?.('[
|
|
261
|
+
logger?.warn?.('[openclaw-overlay] /hooks/agent error:', err.message);
|
|
262
262
|
});
|
|
263
263
|
}
|
|
264
264
|
|
|
@@ -323,15 +323,15 @@ function startBackgroundService(env: any, cliPath: string, logger: any) {
|
|
|
323
323
|
requestCleanupInterval = setInterval(async () => {
|
|
324
324
|
if (serviceRunning) {
|
|
325
325
|
wokenRequests.clear();
|
|
326
|
-
logger?.debug?.('[
|
|
326
|
+
logger?.debug?.('[openclaw-overlay] Cleared stale request IDs');
|
|
327
327
|
|
|
328
328
|
// Also clean up old queue entries
|
|
329
329
|
try {
|
|
330
330
|
const { cleanupServiceQueue } = await import('./src/scripts/utils/storage.js');
|
|
331
331
|
cleanupServiceQueue();
|
|
332
|
-
logger?.debug?.('[
|
|
332
|
+
logger?.debug?.('[openclaw-overlay] Cleaned up old queue entries');
|
|
333
333
|
} catch (err: any) {
|
|
334
|
-
logger?.warn?.('[
|
|
334
|
+
logger?.warn?.('[openclaw-overlay] Queue cleanup failed:', err.message);
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
337
|
}, 5 * 60 * 1000);
|
|
@@ -351,9 +351,9 @@ function startBackgroundService(env: any, cliPath: string, logger: any) {
|
|
|
351
351
|
for (const line of lines) {
|
|
352
352
|
try {
|
|
353
353
|
const event = JSON.parse(line);
|
|
354
|
-
logger?.debug?.(`[
|
|
354
|
+
logger?.debug?.(`[openclaw-overlay] ${event.event || event.type || 'message'}:`, JSON.stringify(event).slice(0, 200));
|
|
355
355
|
|
|
356
|
-
const alertDir = path.join(process.env.HOME || '', '.openclaw', '
|
|
356
|
+
const alertDir = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay');
|
|
357
357
|
fs.mkdirSync(alertDir, { recursive: true });
|
|
358
358
|
|
|
359
359
|
// Detect queued-for-agent events — invoke agent via /hooks/agent
|
|
@@ -363,20 +363,20 @@ function startBackgroundService(env: any, cliPath: string, logger: any) {
|
|
|
363
363
|
|
|
364
364
|
// Check if already woken to prevent duplicate processing
|
|
365
365
|
if (wokenRequests.has(requestId)) {
|
|
366
|
-
logger?.debug?.(`[
|
|
366
|
+
logger?.debug?.(`[openclaw-overlay] Request ${requestId} already woken, skipping duplicate`);
|
|
367
367
|
return;
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
// Skip wake-up for already processed requests unless they're pending
|
|
371
371
|
if (event.action?.startsWith('already-') && !event.action.includes('pending')) {
|
|
372
|
-
logger?.debug?.(`[
|
|
372
|
+
logger?.debug?.(`[openclaw-overlay] Request ${requestId} already processed (${event.action}), skipping`);
|
|
373
373
|
return;
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
wokenRequests.add(requestId);
|
|
377
|
-
logger?.info?.(`[
|
|
377
|
+
logger?.info?.(`[openclaw-overlay] ⚡ Incoming ${event.serviceId} request from ${event.from?.slice(0, 12)}...`);
|
|
378
378
|
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 ${event.serviceId} request using your capabilities\n3. overlay({ action: "fulfill", requestId: "${event.id}", recipientKey: "${event.from}", serviceId: "${event.serviceId}", result: { ... } })`;
|
|
379
|
-
wakeAgent(wakeText, logger, { sessionKey: `hook:
|
|
379
|
+
wakeAgent(wakeText, logger, { sessionKey: `hook:openclaw-overlay:${event.id || Date.now()}` });
|
|
380
380
|
}
|
|
381
381
|
|
|
382
382
|
// Detect service-response events — invoke agent to notify user
|
|
@@ -388,9 +388,9 @@ function startBackgroundService(env: any, cliPath: string, logger: any) {
|
|
|
388
388
|
const formatted = event.formatted || '';
|
|
389
389
|
const resultJson = event.result ? JSON.stringify(event.result, null, 2) : '(no result data)';
|
|
390
390
|
|
|
391
|
-
logger?.info?.(`[
|
|
391
|
+
logger?.info?.(`[openclaw-overlay] 📬 Response received for ${svcId} from ${from?.slice(0, 12)}... — status: ${status}`);
|
|
392
392
|
const wakeText = `📬 Overlay service response received!\n\nService: ${svcId}\nFrom: ${from}\nStatus: ${status}\n${formatted ? `\nSummary: ${formatted}` : ''}\n\nFull result:\n${resultJson}\n\nNotify the user of this response in a clear, human-readable format.`;
|
|
393
|
-
wakeAgent(wakeText, logger, { sessionKey: `hook:
|
|
393
|
+
wakeAgent(wakeText, logger, { sessionKey: `hook:openclaw-overlay:resp-${event.requestId || Date.now()}` });
|
|
394
394
|
}
|
|
395
395
|
|
|
396
396
|
// Write payment/activity notifications for ALL significant events
|
|
@@ -410,12 +410,12 @@ function startBackgroundService(env: any, cliPath: string, logger: any) {
|
|
|
410
410
|
try {
|
|
411
411
|
const event = JSON.parse(line);
|
|
412
412
|
if (event.event === 'connected') {
|
|
413
|
-
logger?.info?.('[
|
|
413
|
+
logger?.info?.('[openclaw-overlay] WebSocket relay connected');
|
|
414
414
|
} else if (event.event === 'disconnected') {
|
|
415
|
-
logger?.warn?.('[
|
|
415
|
+
logger?.warn?.('[openclaw-overlay] WebSocket disconnected, reconnecting...');
|
|
416
416
|
}
|
|
417
417
|
} catch {
|
|
418
|
-
logger?.debug?.(`[
|
|
418
|
+
logger?.debug?.(`[openclaw-overlay] ${line}`);
|
|
419
419
|
}
|
|
420
420
|
}
|
|
421
421
|
});
|
|
@@ -423,7 +423,7 @@ function startBackgroundService(env: any, cliPath: string, logger: any) {
|
|
|
423
423
|
proc.on('exit', (code) => {
|
|
424
424
|
backgroundProcess = null;
|
|
425
425
|
if (serviceRunning) {
|
|
426
|
-
logger?.warn?.(`[
|
|
426
|
+
logger?.warn?.(`[openclaw-overlay] Background service exited (code ${code}), restarting in 5s...`);
|
|
427
427
|
setTimeout(spawnConnect, 5000);
|
|
428
428
|
}
|
|
429
429
|
});
|
|
@@ -448,8 +448,15 @@ function stopBackgroundService() {
|
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
export default function register(api: any) {
|
|
451
|
-
// Capture config at registration time
|
|
452
|
-
|
|
451
|
+
// Capture config at registration time
|
|
452
|
+
// Check all possible IDs for backward compatibility and various installation methods
|
|
453
|
+
const entries = api.getConfig?.()?.plugins?.entries || {};
|
|
454
|
+
const entry = entries['openclaw-overlay']
|
|
455
|
+
|| entries['openclaw-overlay-plugin']
|
|
456
|
+
|| entries['bsv-overlay']
|
|
457
|
+
|| {};
|
|
458
|
+
|
|
459
|
+
// Merge: gateway-level api.config > nested entry.config > flat entry properties
|
|
453
460
|
const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
|
|
454
461
|
|
|
455
462
|
// Register the overlay agent tool
|
|
@@ -585,7 +592,7 @@ export default function register(api: any) {
|
|
|
585
592
|
|
|
586
593
|
// Register background relay service
|
|
587
594
|
api.registerService({
|
|
588
|
-
id: "
|
|
595
|
+
id: "openclaw-overlay-relay",
|
|
589
596
|
start: async () => {
|
|
590
597
|
try {
|
|
591
598
|
api.logger.info("Starting BSV overlay WebSocket relay...");
|
|
@@ -615,7 +622,7 @@ export default function register(api: any) {
|
|
|
615
622
|
|
|
616
623
|
// Register a skill-style wake handler
|
|
617
624
|
api.registerHook({
|
|
618
|
-
id: "
|
|
625
|
+
id: "openclaw-overlay-wake",
|
|
619
626
|
event: "gateway:start",
|
|
620
627
|
handler: async (ctx: any) => {
|
|
621
628
|
// Auto-check for registration on startup
|
|
@@ -624,8 +631,8 @@ export default function register(api: any) {
|
|
|
624
631
|
const env = buildEnvironment(pluginConfig);
|
|
625
632
|
const cliPath = path.join(__dirname, 'dist', 'cli.js');
|
|
626
633
|
|
|
627
|
-
const regPath = path.join(process.env.HOME || '', '.openclaw', '
|
|
628
|
-
const onboardSentFile = path.join(process.env.HOME || '', '.openclaw', '
|
|
634
|
+
const regPath = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'registration.json');
|
|
635
|
+
const onboardSentFile = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'onboarding-sent.flag');
|
|
629
636
|
|
|
630
637
|
if (!fs.existsSync(regPath) && !fs.existsSync(onboardSentFile)) {
|
|
631
638
|
// Check if wallet exists
|
|
@@ -647,7 +654,7 @@ export default function register(api: any) {
|
|
|
647
654
|
// Funded but not registered. Auto-register.
|
|
648
655
|
const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
|
|
649
656
|
if (parseCliOutput(regResult.stdout).success) {
|
|
650
|
-
ctx.logger.info('[
|
|
657
|
+
ctx.logger.info('[openclaw-overlay] Agent auto-registered on startup');
|
|
651
658
|
await autoAdvertiseServices(env, cliPath, ctx.logger);
|
|
652
659
|
}
|
|
653
660
|
}
|
|
@@ -655,7 +662,7 @@ export default function register(api: any) {
|
|
|
655
662
|
}
|
|
656
663
|
|
|
657
664
|
} catch (err: any) {
|
|
658
|
-
api.log?.debug?.('[
|
|
665
|
+
api.log?.debug?.('[openclaw-overlay] Auto-setup/onboarding skipped:', err.message);
|
|
659
666
|
}
|
|
660
667
|
})();
|
|
661
668
|
}
|
|
@@ -721,14 +728,16 @@ export default function register(api: any) {
|
|
|
721
728
|
if (result.agents) {
|
|
722
729
|
console.log("\nAgents:");
|
|
723
730
|
result.agents.forEach((agent: any) => {
|
|
724
|
-
|
|
731
|
+
const name = agent.name || agent.agentName || 'Unknown Agent';
|
|
732
|
+
console.log(`- ${name} (${agent.identityKey.slice(0, 16)}...)`);
|
|
725
733
|
});
|
|
726
734
|
}
|
|
727
735
|
|
|
728
736
|
if (result.services) {
|
|
729
737
|
console.log("\nServices:");
|
|
730
738
|
result.services.forEach((service: any) => {
|
|
731
|
-
|
|
739
|
+
const name = service.name || service.agentName || 'Unknown Agent';
|
|
740
|
+
console.log(`- ${service.serviceId} - ${name} (${service.pricing?.amountSats || 0} sats) by ${service.identityKey.slice(0, 12)}`);
|
|
732
741
|
});
|
|
733
742
|
}
|
|
734
743
|
} catch (error: any) {
|
|
@@ -981,7 +990,7 @@ async function handleUnregister(params: any, env: any, cliPath: string) {
|
|
|
981
990
|
const { confirmToken } = params;
|
|
982
991
|
|
|
983
992
|
// Load current registration to show what will be deleted
|
|
984
|
-
const regPath = path.join(process.env.HOME || '', '.openclaw', '
|
|
993
|
+
const regPath = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'registration.json');
|
|
985
994
|
let registration: any = null;
|
|
986
995
|
try {
|
|
987
996
|
if (fs.existsSync(regPath)) {
|
|
@@ -1148,29 +1157,51 @@ async function handleDiscover(params: any, env: any, cliPath: string) {
|
|
|
1148
1157
|
}
|
|
1149
1158
|
|
|
1150
1159
|
async function handleBalance(env: any, cliPath: string) {
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1160
|
+
try {
|
|
1161
|
+
const result = await execFileAsync('node', [cliPath, 'balance'], { env });
|
|
1162
|
+
const output = parseCliOutput(result.stdout);
|
|
1163
|
+
|
|
1164
|
+
if (!output.success) {
|
|
1165
|
+
throw new Error(output.error);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
return output.data;
|
|
1169
|
+
} catch (error: any) {
|
|
1170
|
+
if (error.message?.includes('Wallet not initialized')) {
|
|
1171
|
+
return { walletBalance: 0, error: 'Not Initialized' };
|
|
1172
|
+
}
|
|
1173
|
+
throw new Error(`Balance check failed: ${error.message}`);
|
|
1156
1174
|
}
|
|
1157
|
-
|
|
1158
|
-
return output.data;
|
|
1159
1175
|
}
|
|
1160
1176
|
|
|
1161
1177
|
async function handleStatus(env: any, cliPath: string) {
|
|
1162
1178
|
try {
|
|
1163
1179
|
// Get identity
|
|
1164
|
-
|
|
1165
|
-
|
|
1180
|
+
let identity: any = { data: { identityKey: 'Not Initialized' } };
|
|
1181
|
+
try {
|
|
1182
|
+
const identityResult = await execFileAsync('node', [cliPath, 'identity'], { env });
|
|
1183
|
+
identity = parseCliOutput(identityResult.stdout);
|
|
1184
|
+
} catch (err: any) {
|
|
1185
|
+
if (!err.message?.includes('Wallet not initialized')) throw err;
|
|
1186
|
+
}
|
|
1166
1187
|
|
|
1167
1188
|
// Get balance
|
|
1168
|
-
|
|
1169
|
-
|
|
1189
|
+
let balance: any = { data: { walletBalance: 0 } };
|
|
1190
|
+
try {
|
|
1191
|
+
const balanceResult = await execFileAsync('node', [cliPath, 'balance'], { env });
|
|
1192
|
+
balance = parseCliOutput(balanceResult.stdout);
|
|
1193
|
+
} catch (err: any) {
|
|
1194
|
+
if (!err.message?.includes('Wallet not initialized')) throw err;
|
|
1195
|
+
}
|
|
1170
1196
|
|
|
1171
1197
|
// Get services
|
|
1172
|
-
|
|
1173
|
-
|
|
1198
|
+
let services: any = { data: [] };
|
|
1199
|
+
try {
|
|
1200
|
+
const servicesResult = await execFileAsync('node', [cliPath, 'services'], { env });
|
|
1201
|
+
services = parseCliOutput(servicesResult.stdout);
|
|
1202
|
+
} catch (err: any) {
|
|
1203
|
+
if (!err.message?.includes('Wallet not initialized')) throw err;
|
|
1204
|
+
}
|
|
1174
1205
|
|
|
1175
1206
|
return {
|
|
1176
1207
|
identity: identity.data,
|
|
@@ -1259,7 +1290,7 @@ async function handleImport(params: any, env: any, cliPath: string) {
|
|
|
1259
1290
|
}
|
|
1260
1291
|
|
|
1261
1292
|
// Check if we should auto-register after successful import
|
|
1262
|
-
const regPath = path.join(process.env.HOME || '', '.openclaw', '
|
|
1293
|
+
const regPath = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'registration.json');
|
|
1263
1294
|
const isRegistered = fs.existsSync(regPath);
|
|
1264
1295
|
|
|
1265
1296
|
if (!isRegistered && output.data?.balance >= 1000) {
|
|
@@ -1515,14 +1546,14 @@ async function handlePendingRequests(env: any, cliPath: string) {
|
|
|
1515
1546
|
if (!output.success) throw new Error(`Queue check failed: ${output.error}`);
|
|
1516
1547
|
|
|
1517
1548
|
// Clear the alert file since we're checking now
|
|
1518
|
-
const alertPath = path.join(process.env.HOME || '', '.openclaw', '
|
|
1549
|
+
const alertPath = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'pending-alert.jsonl');
|
|
1519
1550
|
try { if (fs.existsSync(alertPath)) fs.unlinkSync(alertPath); } catch {}
|
|
1520
1551
|
|
|
1521
1552
|
return output.data;
|
|
1522
1553
|
}
|
|
1523
1554
|
|
|
1524
1555
|
function handleActivity() {
|
|
1525
|
-
const feedPath = path.join(process.env.HOME || '', '.openclaw', '
|
|
1556
|
+
const feedPath = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'activity-feed.jsonl');
|
|
1526
1557
|
if (!fs.existsSync(feedPath)) return { events: [], count: 0 };
|
|
1527
1558
|
|
|
1528
1559
|
const lines = fs.readFileSync(feedPath, 'utf-8').trim().split('\n').filter(Boolean);
|
|
@@ -1568,9 +1599,18 @@ function buildEnvironment(config: any) {
|
|
|
1568
1599
|
if (config.chaintracksUrl) {
|
|
1569
1600
|
env.BSV_CHAINTRACKS_URL = config.chaintracksUrl;
|
|
1570
1601
|
}
|
|
1602
|
+
if (config.arcUrl) {
|
|
1603
|
+
env.BSV_ARC_URL = config.arcUrl;
|
|
1604
|
+
}
|
|
1571
1605
|
|
|
1572
1606
|
// Set defaults
|
|
1573
1607
|
env.BSV_NETWORK = env.BSV_NETWORK || 'mainnet';
|
|
1608
|
+
|
|
1609
|
+
if (!env.BSV_ARC_URL) {
|
|
1610
|
+
env.BSV_ARC_URL = env.BSV_NETWORK === 'testnet'
|
|
1611
|
+
? 'https://testnet.arc.gorillapool.io'
|
|
1612
|
+
: 'https://arc.gorillapool.io';
|
|
1613
|
+
}
|
|
1574
1614
|
if (config.agentName) {
|
|
1575
1615
|
env.AGENT_NAME = config.agentName;
|
|
1576
1616
|
} else if (!env.AGENT_NAME) {
|
package/openclaw.plugin.json
CHANGED
|
@@ -15,11 +15,22 @@
|
|
|
15
15
|
"default": "https://clawoverlay.com",
|
|
16
16
|
"description": "Overlay server URL for registration, discovery, and relay"
|
|
17
17
|
},
|
|
18
|
+
"network": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"enum": ["mainnet", "testnet"],
|
|
21
|
+
"default": "mainnet",
|
|
22
|
+
"description": "BSV network to use"
|
|
23
|
+
},
|
|
18
24
|
"chaintracksUrl": {
|
|
19
25
|
"type": "string",
|
|
20
26
|
"default": "https://chaintracks-us-1.bsvb.tech",
|
|
21
27
|
"description": "Custom Chaintracks server URL for SPV header verification"
|
|
22
28
|
},
|
|
29
|
+
"arcUrl": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"default": "https://arc.gorillapool.io",
|
|
32
|
+
"description": "Custom ARC/Arcade server URL for transaction broadcasting"
|
|
33
|
+
},
|
|
23
34
|
"agentName": {
|
|
24
35
|
"type": "string",
|
|
25
36
|
"description": "Display name for this agent on the overlay network (defaults to hostname)"
|
|
@@ -69,12 +80,21 @@
|
|
|
69
80
|
"placeholder": "https://clawoverlay.com",
|
|
70
81
|
"advanced": true
|
|
71
82
|
},
|
|
83
|
+
"network": {
|
|
84
|
+
"label": "BSV Network"
|
|
85
|
+
},
|
|
72
86
|
"chaintracksUrl": {
|
|
73
87
|
"label": "Chaintracks Server URL",
|
|
74
88
|
"placeholder": "https://chaintracks-us-1.bsvb.tech",
|
|
75
89
|
"help": "Custom server for SPV block header verification",
|
|
76
90
|
"advanced": true
|
|
77
91
|
},
|
|
92
|
+
"arcUrl": {
|
|
93
|
+
"label": "ARC/Arcade Server URL",
|
|
94
|
+
"placeholder": "https://arc.gorillapool.io",
|
|
95
|
+
"help": "Custom server for transaction broadcasting",
|
|
96
|
+
"advanced": true
|
|
97
|
+
},
|
|
78
98
|
"agentName": {
|
|
79
99
|
"label": "Agent Name",
|
|
80
100
|
"placeholder": "my-agent",
|
package/package.json
CHANGED
package/src/core/wallet.ts
CHANGED
|
@@ -232,7 +232,13 @@ export class BSVAgentWallet {
|
|
|
232
232
|
// 3. Network services (ARC broadcasting, chain tracking, etc.)
|
|
233
233
|
const serviceOptions = Services.createDefaultOptions(chain);
|
|
234
234
|
const chaintracksUrl = process.env.BSV_CHAINTRACKS_URL || 'https://chaintracks-us-1.bsvb.tech';
|
|
235
|
+
const arcUrl = process.env.BSV_ARC_URL;
|
|
236
|
+
|
|
235
237
|
serviceOptions.chaintracks = new ChaintracksServiceClient(chain, chaintracksUrl);
|
|
238
|
+
if (arcUrl) {
|
|
239
|
+
serviceOptions.arcUrl = arcUrl;
|
|
240
|
+
}
|
|
241
|
+
|
|
236
242
|
serviceOptions.taalApiKey = taalApiKey;
|
|
237
243
|
const services = new Services(serviceOptions);
|
|
238
244
|
|
|
@@ -288,12 +288,23 @@ export async function cmdBaemailRefund(requestId: string | undefined): Promise<n
|
|
|
288
288
|
|
|
289
289
|
await tx.sign();
|
|
290
290
|
|
|
291
|
-
// Broadcast
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
291
|
+
// Broadcast using configured ARC/Arcade URL or fallback to WhatsOnChain
|
|
292
|
+
const arcUrl = process.env.BSV_ARC_URL;
|
|
293
|
+
let broadcastResp;
|
|
294
|
+
|
|
295
|
+
if (arcUrl) {
|
|
296
|
+
broadcastResp = await fetchWithTimeout(`${arcUrl.replace(/\/$/, '')}/v1/tx`, {
|
|
297
|
+
method: 'POST',
|
|
298
|
+
headers: { 'Content-Type': 'application/json' },
|
|
299
|
+
body: JSON.stringify({ rawTx: tx.toHex() }),
|
|
300
|
+
});
|
|
301
|
+
} else {
|
|
302
|
+
broadcastResp = await fetchWithTimeout('https://api.whatsonchain.com/v1/bsv/main/tx/raw', {
|
|
303
|
+
method: 'POST',
|
|
304
|
+
headers: { 'Content-Type': 'application/json' },
|
|
305
|
+
body: JSON.stringify({ txhex: tx.toHex() }),
|
|
306
|
+
});
|
|
307
|
+
}
|
|
297
308
|
|
|
298
309
|
if (!broadcastResp.ok) {
|
|
299
310
|
const errBody = await broadcastResp.text();
|
package/src/scripts/config.ts
CHANGED
|
@@ -7,7 +7,7 @@ import os from 'node:os';
|
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
|
|
9
9
|
// Auto-load .env from overlay state dir if it exists
|
|
10
|
-
const overlayEnvPath = path.join(os.homedir(), '.openclaw', '
|
|
10
|
+
const overlayEnvPath = path.join(os.homedir(), '.openclaw', 'openclaw-overlay', '.env');
|
|
11
11
|
try {
|
|
12
12
|
if (fs.existsSync(overlayEnvPath)) {
|
|
13
13
|
for (const line of fs.readFileSync(overlayEnvPath, 'utf-8').split('\n')) {
|
|
@@ -43,10 +43,10 @@ export const AGENT_DESCRIPTION = process.env.AGENT_DESCRIPTION ||
|
|
|
43
43
|
export const WOC_API_KEY = process.env.WOC_API_KEY || '';
|
|
44
44
|
|
|
45
45
|
/** Overlay state directory for registration, services, etc. */
|
|
46
|
-
export const OVERLAY_STATE_DIR = path.join(os.homedir(), '.openclaw', '
|
|
46
|
+
export const OVERLAY_STATE_DIR = path.join(os.homedir(), '.openclaw', 'openclaw-overlay');
|
|
47
47
|
|
|
48
48
|
/** Protocol identifier for overlay transactions */
|
|
49
|
-
export const PROTOCOL_ID = '
|
|
49
|
+
export const PROTOCOL_ID = 'clawdbot-overlay-v1';
|
|
50
50
|
|
|
51
51
|
/** Topic managers for overlay submissions */
|
|
52
52
|
export const TOPICS = {
|
|
@@ -38,7 +38,9 @@ export async function cmdDiscover(args: string[]): Promise<never> {
|
|
|
38
38
|
try {
|
|
39
39
|
const { data, txid } = await parseOverlayOutput(output.beef, output.outputIndex);
|
|
40
40
|
if (data?.type === 'identity') {
|
|
41
|
-
|
|
41
|
+
// Handle both 'name' and 'agentName' for backward compatibility
|
|
42
|
+
const name = data.name || data.agentName || 'Unknown Agent';
|
|
43
|
+
results.agents.push({ ...data, name, txid });
|
|
42
44
|
}
|
|
43
45
|
} catch { /* ignore */ }
|
|
44
46
|
}
|