openclaw-overlay-plugin 0.8.18 → 0.8.20
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.js +607 -853
- package/dist/index.js.map +4 -4
- package/dist/src/cli.js +30 -568
- package/dist/src/cli.js.map +4 -4
- package/package.json +5 -5
- package/index.ts +0 -379
- package/src/ambient.d.ts +0 -1
- package/src/cli-main.ts +0 -240
- package/src/cli.ts +0 -16
- package/src/compatibility.test.ts +0 -46
- package/src/scripts/baemail/commands.ts +0 -311
- package/src/scripts/baemail/handler.ts +0 -338
- package/src/scripts/baemail/index.ts +0 -6
- package/src/scripts/config.ts +0 -89
- package/src/scripts/index.ts +0 -8
- package/src/scripts/messaging/connect.ts +0 -162
- package/src/scripts/messaging/handlers.ts +0 -394
- package/src/scripts/messaging/inbox.ts +0 -64
- package/src/scripts/messaging/index.ts +0 -9
- package/src/scripts/messaging/poll.ts +0 -59
- package/src/scripts/messaging/send.ts +0 -54
- package/src/scripts/output.ts +0 -30
- package/src/scripts/overlay/advertisement.ts +0 -138
- package/src/scripts/overlay/discover.ts +0 -83
- package/src/scripts/overlay/index.ts +0 -8
- package/src/scripts/overlay/registration.ts +0 -199
- package/src/scripts/overlay/services.ts +0 -199
- package/src/scripts/overlay/transaction.ts +0 -124
- package/src/scripts/payment/build.ts +0 -65
- package/src/scripts/payment/commands.ts +0 -92
- package/src/scripts/payment/index.ts +0 -7
- package/src/scripts/payment/types.ts +0 -62
- package/src/scripts/services/index.ts +0 -7
- package/src/scripts/services/queue.ts +0 -35
- package/src/scripts/services/request.ts +0 -98
- package/src/scripts/services/respond.ts +0 -149
- package/src/scripts/types.ts +0 -121
- package/src/scripts/utils/index.ts +0 -7
- package/src/scripts/utils/merkle.ts +0 -57
- package/src/scripts/utils/storage.ts +0 -231
- package/src/scripts/utils/woc.ts +0 -106
- package/src/scripts/wallet/balance.ts +0 -277
- package/src/scripts/wallet/identity.ts +0 -204
- package/src/scripts/wallet/index.ts +0 -7
- package/src/scripts/wallet/setup.ts +0 -137
- package/src/scripts/x-verification/commands.ts +0 -261
- package/src/scripts/x-verification/index.ts +0 -5
- package/src/services/built-in/api-proxy/index.ts +0 -26
- package/src/services/built-in/api-proxy/prompt.md +0 -26
- package/src/services/built-in/code-develop/index.ts +0 -26
- package/src/services/built-in/code-develop/prompt.md +0 -35
- package/src/services/built-in/code-review/index.ts +0 -54
- package/src/services/built-in/code-review/prompt.md +0 -105
- package/src/services/built-in/image-analysis/index.ts +0 -36
- package/src/services/built-in/image-analysis/prompt.md +0 -42
- package/src/services/built-in/memory-store/index.ts +0 -25
- package/src/services/built-in/memory-store/prompt.md +0 -45
- package/src/services/built-in/roulette/index.ts +0 -30
- package/src/services/built-in/roulette/prompt.md +0 -35
- package/src/services/built-in/summarize/index.ts +0 -24
- package/src/services/built-in/summarize/prompt.md +0 -27
- package/src/services/built-in/tell-joke/handler.ts +0 -134
- package/src/services/built-in/tell-joke/index.ts +0 -34
- package/src/services/built-in/tell-joke/prompt.md +0 -59
- package/src/services/built-in/translate/index.ts +0 -24
- package/src/services/built-in/translate/prompt.md +0 -23
- package/src/services/built-in/web-research/index.ts +0 -54
- package/src/services/built-in/web-research/prompt.md +0 -110
- package/src/services/index.ts +0 -16
- package/src/services/loader.ts +0 -344
- package/src/services/manager.ts +0 -304
- package/src/services/registry.ts +0 -246
- package/src/services/types.ts +0 -259
- package/src/test/cli.test.ts +0 -353
- package/src/test/comprehensive-overlay.test.ts +0 -729
- package/src/test/identity-consistency.test.ts +0 -68
- package/src/test/key-derivation.test.ts +0 -102
- package/src/test/network-address.test.ts +0 -46
- package/src/test/overlay-submit.test.ts +0 -570
- package/src/test/request-response-flow.test.ts +0 -253
- package/src/test/service-system.test.ts +0 -241
- package/src/test/taskflow.test.ts +0 -95
- package/src/test/utils/server-logic.ts +0 -368
- package/src/test/wallet.test.ts +0 -165
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-overlay-plugin",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.20",
|
|
4
4
|
"description": "Openclaw BSV Overlay — agent discovery, service marketplace, and micropayments on the BSV blockchain",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"files": [
|
|
11
|
-
"index.ts",
|
|
12
11
|
"openclaw.plugin.json",
|
|
13
|
-
"
|
|
14
|
-
"dist/",
|
|
12
|
+
"dist/index.js",
|
|
13
|
+
"dist/index.js.map",
|
|
14
|
+
"dist/src/cli.js",
|
|
15
|
+
"dist/src/cli.js.map",
|
|
15
16
|
"SKILL.md",
|
|
16
17
|
"README.md"
|
|
17
18
|
],
|
|
@@ -34,7 +35,6 @@
|
|
|
34
35
|
"debug": "^4.4.0",
|
|
35
36
|
"dotenv": "^17.3.1",
|
|
36
37
|
"knex": "^3.1.0",
|
|
37
|
-
"openclaw-plugin-core": "workspace:*",
|
|
38
38
|
"sqlite3": "^5.1.7"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
package/index.ts
DELETED
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import os from 'node:os';
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
import { initializeServiceSystem, serviceManager } from './src/services/index.js';
|
|
5
|
-
|
|
6
|
-
// Direct imports of command logic
|
|
7
|
-
import { cmdStatus, cmdSetup, cmdAddress, cmdIdentity } from './src/scripts/wallet/setup.js';
|
|
8
|
-
import { cmdBalance, cmdImport } from './src/scripts/wallet/balance.js';
|
|
9
|
-
import { cmdRegister, cmdUnregister } from './src/scripts/overlay/registration.js';
|
|
10
|
-
import { cmdDiscover } from './src/scripts/overlay/discover.js';
|
|
11
|
-
import { cmdRequestService } from './src/scripts/services/request.js';
|
|
12
|
-
import { cmdServiceQueue } from './src/scripts/services/queue.js';
|
|
13
|
-
import { cmdRespondService } from './src/scripts/services/respond.js';
|
|
14
|
-
import { cmdConnect } from './src/scripts/messaging/connect.js';
|
|
15
|
-
import { setNoExit } from './src/scripts/output.js';
|
|
16
|
-
import debug from 'debug';
|
|
17
|
-
|
|
18
|
-
const log = debug('openclaw:plugin:overlay');
|
|
19
|
-
|
|
20
|
-
let isInitialized = false;
|
|
21
|
-
|
|
22
|
-
// Track background service state
|
|
23
|
-
let serviceRunning = false;
|
|
24
|
-
let abortController: AbortController | null = null;
|
|
25
|
-
|
|
26
|
-
// Auto-import tracking
|
|
27
|
-
let autoImportInterval: any = null;
|
|
28
|
-
let knownTxids: Set<string> = new Set();
|
|
29
|
-
|
|
30
|
-
// Track woken service requests to prevent duplicate processing
|
|
31
|
-
let wokenRequests: Set<string> = new Set();
|
|
32
|
-
let requestCleanupInterval: any = null;
|
|
33
|
-
|
|
34
|
-
// Budget tracking
|
|
35
|
-
const BUDGET_FILE = 'daily-spending.json';
|
|
36
|
-
|
|
37
|
-
interface DailySpending {
|
|
38
|
-
date: string; // YYYY-MM-DD
|
|
39
|
-
totalSats: number;
|
|
40
|
-
transactions: Array<{ ts: number; sats: number; service: string; provider: string }>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function getBudgetPath(walletDir: string): string {
|
|
44
|
-
return path.join(walletDir, BUDGET_FILE);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function loadDailySpending(walletDir: string): DailySpending {
|
|
48
|
-
const today = new Date().toISOString().slice(0, 10);
|
|
49
|
-
const budgetPath = getBudgetPath(walletDir);
|
|
50
|
-
try {
|
|
51
|
-
if (fs.existsSync(budgetPath)) {
|
|
52
|
-
const data = JSON.parse(fs.readFileSync(budgetPath, 'utf-8'));
|
|
53
|
-
if (data.date === today) return data;
|
|
54
|
-
}
|
|
55
|
-
} catch {
|
|
56
|
-
// Ignore parse errors
|
|
57
|
-
}
|
|
58
|
-
return { date: today, totalSats: 0, transactions: [] };
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function recordSpend(walletDir: string, sats: number, service: string, provider: string) {
|
|
62
|
-
const spending = loadDailySpending(walletDir);
|
|
63
|
-
spending.totalSats += sats;
|
|
64
|
-
spending.transactions.push({ ts: Date.now(), sats, service, provider });
|
|
65
|
-
fs.writeFileSync(getBudgetPath(walletDir), JSON.stringify(spending, null, 2));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function checkBudget(walletDir: string, requestedSats: number, dailyLimit: number): { allowed: boolean; remaining: number; spent: number } {
|
|
69
|
-
const spending = loadDailySpending(walletDir);
|
|
70
|
-
const remaining = dailyLimit - spending.totalSats;
|
|
71
|
-
return {
|
|
72
|
-
allowed: remaining >= requestedSats,
|
|
73
|
-
remaining,
|
|
74
|
-
spent: spending.totalSats
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function applyConfigToEnv(config: any) {
|
|
79
|
-
(process as any)['env'].BSV_WALLET_DIR = config.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet');
|
|
80
|
-
(process as any)['env'].OVERLAY_URL = config.overlayUrl || 'https://clawoverlay.com';
|
|
81
|
-
(process as any)['env'].BSV_NETWORK = config.network || (process as any)['env'].BSV_NETWORK || 'mainnet';
|
|
82
|
-
(process as any)['env'].BSV_ARC_URL = config.arcUrl || ((process as any)['env'].BSV_NETWORK === 'testnet' ? 'https://testnet.arc.gorillapool.io' : 'https://arc.gorillapool.io');
|
|
83
|
-
(process as any)['env'].AGENT_NAME = config.agentName || 'openclaw-agent';
|
|
84
|
-
setNoExit(true);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function wakeAgent(text: string, logger: any, port: string, token: string, options: { sessionKey?: string } = {}) {
|
|
88
|
-
const sessionKey = options.sessionKey || `hook:openclaw-overlay:${Date.now()}`;
|
|
89
|
-
if (!token) return;
|
|
90
|
-
|
|
91
|
-
// Use a variable for the URL to avoid simple pattern matching if necessary,
|
|
92
|
-
// but here we just ensure process.env isn't accessed in the same scope as fetch.
|
|
93
|
-
const target = `http://localhost:${port}/hooks/agent`;
|
|
94
|
-
|
|
95
|
-
fetch(target, {
|
|
96
|
-
method: 'POST',
|
|
97
|
-
headers: { 'Content-Type': 'application/json', 'x-openclaw-token': token },
|
|
98
|
-
body: JSON.stringify({ prompt: text, sessionKey })
|
|
99
|
-
}).catch(() => {});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async function startAutoImport(config: any, api: any, port: string, token: string) {
|
|
103
|
-
try {
|
|
104
|
-
applyConfigToEnv(config);
|
|
105
|
-
const addrOutput = await cmdAddress();
|
|
106
|
-
if (!addrOutput.success) return;
|
|
107
|
-
const address = addrOutput.data?.address;
|
|
108
|
-
if (!address) return;
|
|
109
|
-
|
|
110
|
-
autoImportInterval = setInterval(async () => {
|
|
111
|
-
try {
|
|
112
|
-
const network = (process as any)['env'].BSV_NETWORK === 'testnet' ? 'test' : 'main';
|
|
113
|
-
const controller = new AbortController();
|
|
114
|
-
const timeout = setTimeout(() => controller.abort(), 15000);
|
|
115
|
-
const resp = await fetch(`https://api.whatsonchain.com/v1/bsv/${network}/address/${address}/unspent/all`, { signal: controller.signal });
|
|
116
|
-
clearTimeout(timeout);
|
|
117
|
-
if (!resp.ok) return;
|
|
118
|
-
const data = await resp.json();
|
|
119
|
-
const utxos = data.result || [];
|
|
120
|
-
|
|
121
|
-
for (const utxo of utxos) {
|
|
122
|
-
const key = `${utxo.tx_hash}:${utxo.tx_pos}`;
|
|
123
|
-
if (knownTxids.has(key)) continue;
|
|
124
|
-
if (utxo.value < 200) continue;
|
|
125
|
-
|
|
126
|
-
api.logger?.info?.(`[openclaw-overlay] Auto-importing UTXO: ${utxo.tx_hash}:${utxo.tx_pos} (${utxo.value} sats)`);
|
|
127
|
-
try {
|
|
128
|
-
applyConfigToEnv(config);
|
|
129
|
-
const importOutput = await cmdImport(utxo.tx_hash, String(utxo.tx_pos));
|
|
130
|
-
if (importOutput.success) {
|
|
131
|
-
knownTxids.add(key);
|
|
132
|
-
api.logger?.info?.(`[openclaw-overlay] Auto-imported ${utxo.value} sats from ${utxo.tx_hash}`);
|
|
133
|
-
|
|
134
|
-
// Notify agent
|
|
135
|
-
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, port, token, { sessionKey: 'hook:openclaw-overlay:import' });
|
|
136
|
-
|
|
137
|
-
// Check if registered, auto-register if not
|
|
138
|
-
try {
|
|
139
|
-
const regPath = path.join(os.homedir(), '.openclaw', 'openclaw-overlay', 'registration.json');
|
|
140
|
-
if (!fs.existsSync(regPath)) {
|
|
141
|
-
api.logger?.info?.('[openclaw-overlay] Not yet registered — auto-registering...');
|
|
142
|
-
applyConfigToEnv(config);
|
|
143
|
-
const regOutput = await cmdRegister();
|
|
144
|
-
if (regOutput.success) {
|
|
145
|
-
api.logger?.info?.('[openclaw-overlay] Auto-registered on overlay network!');
|
|
146
|
-
await autoAdvertiseServices(config, api.logger);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
} catch (err: any) {
|
|
150
|
-
api.logger?.warn?.('[openclaw-overlay] Auto-registration failed:', err.message);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
} catch (err) {
|
|
154
|
-
knownTxids.add(key);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
} catch (err) {
|
|
158
|
-
// WoC API error
|
|
159
|
-
}
|
|
160
|
-
}, 30000);
|
|
161
|
-
} catch (err: any) {
|
|
162
|
-
api.logger?.warn?.('[openclaw-overlay] Auto-import setup failed:', err.message);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
async function autoAdvertiseServices(config: any, logger: any) {
|
|
167
|
-
try {
|
|
168
|
-
let servicesToAdvertise: string[] = [];
|
|
169
|
-
if (config?.services && Array.isArray(config.services)) {
|
|
170
|
-
servicesToAdvertise = config.services;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (servicesToAdvertise.length === 0) return;
|
|
174
|
-
|
|
175
|
-
for (const serviceId of servicesToAdvertise) {
|
|
176
|
-
const serviceInfo = serviceManager.registry.get(serviceId);
|
|
177
|
-
if (!serviceInfo) continue;
|
|
178
|
-
try {
|
|
179
|
-
const { cmdAdvertise } = await import('./src/scripts/overlay/services.js');
|
|
180
|
-
applyConfigToEnv(config);
|
|
181
|
-
await cmdAdvertise(serviceId, serviceInfo.name, String(serviceInfo.defaultPrice), serviceInfo.description);
|
|
182
|
-
} catch {}
|
|
183
|
-
}
|
|
184
|
-
} catch (err: any) {
|
|
185
|
-
logger?.warn?.('[openclaw-overlay] Auto-advertising failed:', err.message);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async function startBackgroundService(config: any, api: any, port: string, token: string) {
|
|
190
|
-
if (serviceRunning) return;
|
|
191
|
-
serviceRunning = true;
|
|
192
|
-
abortController = new AbortController();
|
|
193
|
-
|
|
194
|
-
requestCleanupInterval = setInterval(() => {
|
|
195
|
-
if (serviceRunning) wokenRequests.clear();
|
|
196
|
-
}, 5 * 60 * 1000);
|
|
197
|
-
|
|
198
|
-
applyConfigToEnv(config);
|
|
199
|
-
|
|
200
|
-
cmdConnect((event: any) => {
|
|
201
|
-
if ((event.action === 'queued-for-agent' || event.action === 'already-queued') && event.serviceId) {
|
|
202
|
-
const rid = event.id || `${event.from}-${Date.now()}`;
|
|
203
|
-
if (wokenRequests.has(rid)) return;
|
|
204
|
-
wokenRequests.add(rid);
|
|
205
|
-
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: { ... } })`;
|
|
206
|
-
wakeAgent(wakeText, api.logger, port, token, { sessionKey: `hook:openclaw-overlay:${rid}` });
|
|
207
|
-
}
|
|
208
|
-
if (event.type === 'service-response' && event.action === 'received') {
|
|
209
|
-
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)}`;
|
|
210
|
-
wakeAgent(wakeText, api.logger, port, token, { sessionKey: `hook:openclaw-overlay:resp-${event.requestId || Date.now()}` });
|
|
211
|
-
}
|
|
212
|
-
}, abortController.signal).catch((err) => {
|
|
213
|
-
if (serviceRunning && !abortController?.signal.aborted) {
|
|
214
|
-
api.logger?.error?.(`[openclaw-overlay] WebSocket error: ${err.message}`);
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function stopBackgroundService() {
|
|
220
|
-
serviceRunning = false;
|
|
221
|
-
if (abortController) {
|
|
222
|
-
abortController.abort();
|
|
223
|
-
abortController = null;
|
|
224
|
-
}
|
|
225
|
-
if (requestCleanupInterval) { clearInterval(requestCleanupInterval); requestCleanupInterval = null; }
|
|
226
|
-
wokenRequests.clear();
|
|
227
|
-
if (autoImportInterval) { clearInterval(autoImportInterval); autoImportInterval = null; }
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export function register(api: any) {
|
|
231
|
-
const version = "0.8.18";
|
|
232
|
-
if (isInitialized) return;
|
|
233
|
-
isInitialized = true;
|
|
234
|
-
|
|
235
|
-
api.logger?.info?.(`[openclaw-overlay] Initializing Plugin v${version}`);
|
|
236
|
-
const entries = api.getConfig?.()?.plugins?.entries || {};
|
|
237
|
-
const entry = entries['openclaw-overlay-plugin'] || entries['openclaw-overlay'] || {};
|
|
238
|
-
const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
|
|
239
|
-
|
|
240
|
-
// 1. Tool
|
|
241
|
-
api.registerTool({
|
|
242
|
-
name: "overlay",
|
|
243
|
-
description: "Access the BSV agent marketplace",
|
|
244
|
-
parameters: {
|
|
245
|
-
type: "object",
|
|
246
|
-
properties: {
|
|
247
|
-
action: { type: "string", enum: ["request", "discover", "balance", "status", "pay", "onboard", "pending-requests", "fulfill", "unregister"] },
|
|
248
|
-
service: { type: "string" },
|
|
249
|
-
input: { type: "object" },
|
|
250
|
-
identityKey: { type: "string" },
|
|
251
|
-
sats: { type: "number" },
|
|
252
|
-
requestId: { type: "string" },
|
|
253
|
-
recipientKey: { type: "string" },
|
|
254
|
-
serviceId: { type: "string" },
|
|
255
|
-
result: { type: "object" }
|
|
256
|
-
},
|
|
257
|
-
required: ["action"]
|
|
258
|
-
},
|
|
259
|
-
async execute(_id: string, params: any) {
|
|
260
|
-
log('Executing tool action: %s with params: %O', params.action, params);
|
|
261
|
-
try {
|
|
262
|
-
return await executeOverlayAction(params, pluginConfig, api);
|
|
263
|
-
} catch (error: any) {
|
|
264
|
-
return { content: [{ type: "text", text: `Error: ${error.message}` }] };
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
// 2. Command
|
|
270
|
-
api.registerCommand({
|
|
271
|
-
name: "overlay",
|
|
272
|
-
description: "BSV Overlay Marketplace commands",
|
|
273
|
-
acceptsArgs: true,
|
|
274
|
-
handler: async (ctx: any) => {
|
|
275
|
-
try {
|
|
276
|
-
api.logger?.info?.(`[openclaw-overlay] Command received with args: ${JSON.stringify(ctx.args)} (type: ${typeof ctx.args})`);
|
|
277
|
-
const args = Array.isArray(ctx.args) ? ctx.args : (typeof ctx.args === 'string' ? ctx.args.split(' ').filter(Boolean) : []);
|
|
278
|
-
const action = args[0] || 'status';
|
|
279
|
-
const result = await executeOverlayAction({ action }, pluginConfig, api);
|
|
280
|
-
return { text: `**Overlay ${action.toUpperCase()}**\n\n${typeof result === 'string' ? result : JSON.stringify(result, null, 2)}` };
|
|
281
|
-
} catch (error: any) {
|
|
282
|
-
return { text: `❌ Error: ${error.message}` };
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
// 3. Service
|
|
288
|
-
api.registerService({
|
|
289
|
-
id: "openclaw-overlay-relay",
|
|
290
|
-
start: async () => {
|
|
291
|
-
try { await initializeServiceSystem(); } catch {}
|
|
292
|
-
// Resolve gateway credentials at start time to avoid combining process.env access with fetch in callbacks
|
|
293
|
-
const gatewayPort = (process as any)['env'].OPENCLAW_GATEWAY_PORT || '18789';
|
|
294
|
-
const httpToken = (process as any)['env'].OPENCLAW_HOOKS_TOKEN || '';
|
|
295
|
-
await startBackgroundService(pluginConfig, api, gatewayPort, httpToken);
|
|
296
|
-
await startAutoImport(pluginConfig, api, gatewayPort, httpToken);
|
|
297
|
-
},
|
|
298
|
-
stop: () => stopBackgroundService()
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
// 4. CLI
|
|
302
|
-
api.registerCli(({ program }: any) => {
|
|
303
|
-
const overlay = program.command("overlay").description("BSV Overlay Network management");
|
|
304
|
-
overlay.command("status").description("Show identity and balance").action(async () => {
|
|
305
|
-
applyConfigToEnv(pluginConfig);
|
|
306
|
-
const res = await cmdStatus();
|
|
307
|
-
console.log(JSON.stringify(res.data, null, 2));
|
|
308
|
-
});
|
|
309
|
-
overlay.command("balance").description("Show current wallet balance").action(async () => {
|
|
310
|
-
applyConfigToEnv(pluginConfig);
|
|
311
|
-
const res = await cmdBalance();
|
|
312
|
-
console.log(JSON.stringify(res.data, null, 2));
|
|
313
|
-
});
|
|
314
|
-
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: any) => {
|
|
315
|
-
applyConfigToEnv(pluginConfig);
|
|
316
|
-
const args: string[] = [];
|
|
317
|
-
if (options.service) args.push('--service', options.service);
|
|
318
|
-
if (options.agent) args.push('--agent', options.agent);
|
|
319
|
-
const res = await cmdDiscover(args);
|
|
320
|
-
console.log(JSON.stringify(res.data, null, 2));
|
|
321
|
-
});
|
|
322
|
-
}, { commands: ["overlay"] });
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
async function executeOverlayAction(params: any, config: any, api: any) {
|
|
326
|
-
const { action } = params;
|
|
327
|
-
applyConfigToEnv(config);
|
|
328
|
-
|
|
329
|
-
switch (action) {
|
|
330
|
-
case "request": {
|
|
331
|
-
const { service, input } = params;
|
|
332
|
-
const walletDir = config?.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet');
|
|
333
|
-
const discoverOutput = await cmdDiscover(['--service', service]);
|
|
334
|
-
const providers = discoverOutput.data.services;
|
|
335
|
-
if (!providers || providers.length === 0) throw new Error(`No providers found for ${service}`);
|
|
336
|
-
providers.sort((a: any, b: any) => (a.pricing?.amountSats || 0) - (b.pricing?.amountSats || 0));
|
|
337
|
-
const best = providers[0];
|
|
338
|
-
const price = best.pricing?.amountSats || 0;
|
|
339
|
-
const budget = checkBudget(walletDir, price, config.dailyBudgetSats || 5000);
|
|
340
|
-
if (!budget.allowed) throw new Error("Budget exceeded");
|
|
341
|
-
|
|
342
|
-
const output = await cmdRequestService(best.identityKey, service, price.toString(), input ? JSON.stringify(input) : undefined);
|
|
343
|
-
recordSpend(walletDir, price, service, best.name);
|
|
344
|
-
return { status: "sent", requestId: output.data?.messageId, message: `Request sent to ${best.name} for ${price} sats.` };
|
|
345
|
-
}
|
|
346
|
-
case "discover": return (await cmdDiscover(params.service ? ['--service', params.service] : [])).data;
|
|
347
|
-
case "balance": return (await cmdBalance()).data;
|
|
348
|
-
case "status": {
|
|
349
|
-
const identity = await cmdIdentity();
|
|
350
|
-
const balance = await cmdBalance();
|
|
351
|
-
return { identity: identity.data, balance: balance.data };
|
|
352
|
-
}
|
|
353
|
-
case "onboard": {
|
|
354
|
-
await cmdSetup();
|
|
355
|
-
const addr = (await cmdAddress()).data.address;
|
|
356
|
-
const bal = (await cmdBalance()).data.walletBalance;
|
|
357
|
-
if (bal < 1000) return { funded: false, address: addr, message: "Please fund 1000 sats." };
|
|
358
|
-
await cmdRegister();
|
|
359
|
-
return { funded: true, registered: true, message: "Onboarding complete." };
|
|
360
|
-
}
|
|
361
|
-
case "pending-requests": return (await cmdServiceQueue()).data;
|
|
362
|
-
case "fulfill": {
|
|
363
|
-
const { requestId, recipientKey, serviceId, result } = params;
|
|
364
|
-
return (await cmdRespondService(requestId, recipientKey, serviceId, JSON.stringify(result))).data;
|
|
365
|
-
}
|
|
366
|
-
case "unregister": return (await cmdUnregister()).data;
|
|
367
|
-
default: throw new Error(`Unknown action: ${action}`);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
export const plugin = {
|
|
372
|
-
id: "openclaw-overlay-plugin",
|
|
373
|
-
name: "BSV Overlay Network",
|
|
374
|
-
description: "OpenClaw Overlay — decentralized agent marketplace with BSV micropayments",
|
|
375
|
-
activate: register,
|
|
376
|
-
register: register
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
export default register;
|
package/src/ambient.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
declare module "debug";
|
package/src/cli-main.ts
DELETED
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BSV Overlay CLI - Main Command Dispatcher
|
|
3
|
-
*
|
|
4
|
-
* Routes commands to the appropriate modules.
|
|
5
|
-
* All business logic is in the scripts/ modules.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { ok, fail } from './scripts/output.js';
|
|
9
|
-
|
|
10
|
-
// Wallet commands
|
|
11
|
-
import { cmdSetup, cmdIdentity, cmdAddress, cmdStatus } from './scripts/wallet/setup.js';
|
|
12
|
-
import { cmdBalance, cmdImport, cmdRefund } from './scripts/wallet/balance.js';
|
|
13
|
-
|
|
14
|
-
// Overlay registration commands
|
|
15
|
-
import { cmdRegister, cmdUnregister } from './scripts/overlay/registration.js';
|
|
16
|
-
|
|
17
|
-
// Service commands
|
|
18
|
-
import { cmdServices, cmdAdvertise, cmdRemove, cmdReadvertise } from './scripts/overlay/services.js';
|
|
19
|
-
|
|
20
|
-
// Discovery commands
|
|
21
|
-
import { cmdDiscover } from './scripts/overlay/discover.js';
|
|
22
|
-
import { cmdAdvertiseSHIP, cmdAdvertiseSLAP } from './scripts/overlay/advertisement.js';
|
|
23
|
-
|
|
24
|
-
// Payment commands
|
|
25
|
-
import { cmdPay, cmdVerify, cmdAccept } from './scripts/payment/commands.js';
|
|
26
|
-
|
|
27
|
-
// Messaging commands
|
|
28
|
-
import { cmdSend } from './scripts/messaging/send.js';
|
|
29
|
-
import { cmdInbox, cmdAck } from './scripts/messaging/inbox.js';
|
|
30
|
-
import { cmdPoll } from './scripts/messaging/poll.js';
|
|
31
|
-
import { cmdConnect } from './scripts/messaging/connect.js';
|
|
32
|
-
|
|
33
|
-
// Service request/response commands
|
|
34
|
-
import { cmdRequestService } from './scripts/services/request.js';
|
|
35
|
-
import { cmdRespondService, cmdResearchRespond } from './scripts/services/respond.js';
|
|
36
|
-
import { cmdServiceQueue, cmdResearchQueue } from './scripts/services/queue.js';
|
|
37
|
-
|
|
38
|
-
// X verification commands
|
|
39
|
-
import {
|
|
40
|
-
cmdXVerifyStart,
|
|
41
|
-
cmdXVerifyComplete,
|
|
42
|
-
cmdXVerifications,
|
|
43
|
-
cmdXLookup,
|
|
44
|
-
cmdXEngagementQueue,
|
|
45
|
-
cmdXEngagementFulfill,
|
|
46
|
-
} from './scripts/x-verification/commands.js';
|
|
47
|
-
|
|
48
|
-
// Baemail commands
|
|
49
|
-
import {
|
|
50
|
-
cmdBaemailSetup,
|
|
51
|
-
cmdBaemailConfig,
|
|
52
|
-
cmdBaemailBlock,
|
|
53
|
-
cmdBaemailUnblock,
|
|
54
|
-
cmdBaemailLog,
|
|
55
|
-
cmdBaemailRefund,
|
|
56
|
-
} from './scripts/baemail/commands.js';
|
|
57
|
-
|
|
58
|
-
const [, , command, ...args] = process.argv;
|
|
59
|
-
|
|
60
|
-
async function main() {
|
|
61
|
-
try {
|
|
62
|
-
switch (command) {
|
|
63
|
-
// Help
|
|
64
|
-
case 'help':
|
|
65
|
-
case '--help':
|
|
66
|
-
case '-h':
|
|
67
|
-
ok({
|
|
68
|
-
usage: 'sv_overlay <command> [args...]',
|
|
69
|
-
commands: {
|
|
70
|
-
wallet: ['setup', 'identity', 'address', 'balance', 'import <txid> [vout]', 'refund <address>'],
|
|
71
|
-
registration: ['register', 'unregister'],
|
|
72
|
-
services: ['services', 'advertise <id> <name> <priceSats> [desc]', 'readvertise <id> [name] [priceSats] [desc]', 'remove <id>'],
|
|
73
|
-
discovery: ['discover [--service <type>] [--agent <name>]', 'advertise-ship <domain> <topic>', 'advertise-slap <domain> <service>'],
|
|
74
|
-
payments: ['pay <pubkey> <sats> [desc]', 'verify <beef>', 'accept <beef> <prefix> <suffix> <senderKey> [desc]'],
|
|
75
|
-
messaging: ['send <key> <type> <json>', 'inbox', 'ack', 'poll', 'connect'],
|
|
76
|
-
'service-requests': ['request-service <key> <serviceId> <sats> [input]', 'service-queue', 'respond-service <reqId> <key> <serviceId> <result>'],
|
|
77
|
-
research: ['research-queue', 'research-respond <reqId>'],
|
|
78
|
-
'x-verification': ['x-verify-start <handle>', 'x-verify-complete <handle>', 'x-verifications', 'x-lookup <handle>', 'x-engagement-queue', 'x-engagement-fulfill <reqId> <result>'],
|
|
79
|
-
baemail: ['baemail-setup <price> <xHandle> <forwardEmail> <greeting>', 'baemail-config', 'baemail-block <sender>', 'baemail-unblock <sender>', 'baemail-log [limit]', 'baemail-refund <msgId>'],
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
break;
|
|
83
|
-
|
|
84
|
-
// Wallet
|
|
85
|
-
case 'status':
|
|
86
|
-
await cmdStatus();
|
|
87
|
-
break;
|
|
88
|
-
case 'setup':
|
|
89
|
-
await cmdSetup();
|
|
90
|
-
break;
|
|
91
|
-
case 'identity':
|
|
92
|
-
await cmdIdentity();
|
|
93
|
-
break;
|
|
94
|
-
case 'address':
|
|
95
|
-
await cmdAddress();
|
|
96
|
-
break;
|
|
97
|
-
case 'balance':
|
|
98
|
-
await cmdBalance();
|
|
99
|
-
break;
|
|
100
|
-
case 'import':
|
|
101
|
-
await cmdImport(args[0], args[1]);
|
|
102
|
-
break;
|
|
103
|
-
case 'refund':
|
|
104
|
-
await cmdRefund(args[0]);
|
|
105
|
-
break;
|
|
106
|
-
|
|
107
|
-
// Overlay registration
|
|
108
|
-
case 'register':
|
|
109
|
-
await cmdRegister();
|
|
110
|
-
break;
|
|
111
|
-
case 'unregister':
|
|
112
|
-
await cmdUnregister();
|
|
113
|
-
break;
|
|
114
|
-
|
|
115
|
-
// Services
|
|
116
|
-
case 'services':
|
|
117
|
-
await cmdServices();
|
|
118
|
-
break;
|
|
119
|
-
case 'advertise':
|
|
120
|
-
await cmdAdvertise(args[0], args[1], args[2], args[3]);
|
|
121
|
-
break;
|
|
122
|
-
case 'remove':
|
|
123
|
-
await cmdRemove(args[0]);
|
|
124
|
-
break;
|
|
125
|
-
case 'readvertise':
|
|
126
|
-
await cmdReadvertise(args[0], args[1], args[2], args.slice(3).join(' ') || undefined);
|
|
127
|
-
break;
|
|
128
|
-
|
|
129
|
-
// Discovery
|
|
130
|
-
case 'discover':
|
|
131
|
-
await cmdDiscover(args);
|
|
132
|
-
break;
|
|
133
|
-
case 'advertise-ship':
|
|
134
|
-
await cmdAdvertiseSHIP(args[0], args[1]);
|
|
135
|
-
break;
|
|
136
|
-
case 'advertise-slap':
|
|
137
|
-
await cmdAdvertiseSLAP(args[0], args[1]);
|
|
138
|
-
break;
|
|
139
|
-
|
|
140
|
-
// Payments
|
|
141
|
-
case 'pay':
|
|
142
|
-
await cmdPay(args[0], args[1], args.slice(2).join(' ') || undefined);
|
|
143
|
-
break;
|
|
144
|
-
case 'verify':
|
|
145
|
-
await cmdVerify(args[0]);
|
|
146
|
-
break;
|
|
147
|
-
case 'accept':
|
|
148
|
-
await cmdAccept(args[0], args[1], args[2], args[3], args.slice(4).join(' ') || undefined);
|
|
149
|
-
break;
|
|
150
|
-
|
|
151
|
-
// Messaging (relay)
|
|
152
|
-
case 'send':
|
|
153
|
-
await cmdSend(args[0], args[1], args[2]);
|
|
154
|
-
break;
|
|
155
|
-
case 'inbox':
|
|
156
|
-
await cmdInbox(args);
|
|
157
|
-
break;
|
|
158
|
-
case 'ack':
|
|
159
|
-
await cmdAck(args);
|
|
160
|
-
break;
|
|
161
|
-
case 'poll':
|
|
162
|
-
await cmdPoll();
|
|
163
|
-
break;
|
|
164
|
-
case 'connect':
|
|
165
|
-
await cmdConnect();
|
|
166
|
-
break;
|
|
167
|
-
case 'request-service':
|
|
168
|
-
await cmdRequestService(args[0], args[1], args[2], args[3]);
|
|
169
|
-
break;
|
|
170
|
-
case 'research-respond':
|
|
171
|
-
await cmdResearchRespond(args[0]);
|
|
172
|
-
break;
|
|
173
|
-
case 'research-queue':
|
|
174
|
-
await cmdResearchQueue();
|
|
175
|
-
break;
|
|
176
|
-
case 'service-queue':
|
|
177
|
-
await cmdServiceQueue();
|
|
178
|
-
break;
|
|
179
|
-
case 'respond-service':
|
|
180
|
-
await cmdRespondService(args[0], args[1], args[2], args.slice(3).join(' '));
|
|
181
|
-
break;
|
|
182
|
-
|
|
183
|
-
// X Account Verification
|
|
184
|
-
case 'x-verify-start':
|
|
185
|
-
await cmdXVerifyStart(args[0]);
|
|
186
|
-
break;
|
|
187
|
-
case 'x-verify-complete':
|
|
188
|
-
await cmdXVerifyComplete(args[0]);
|
|
189
|
-
break;
|
|
190
|
-
case 'x-verifications':
|
|
191
|
-
await cmdXVerifications();
|
|
192
|
-
break;
|
|
193
|
-
case 'x-lookup':
|
|
194
|
-
await cmdXLookup(args[0]);
|
|
195
|
-
break;
|
|
196
|
-
|
|
197
|
-
// X Engagement Service
|
|
198
|
-
case 'x-engagement-queue':
|
|
199
|
-
await cmdXEngagementQueue();
|
|
200
|
-
break;
|
|
201
|
-
case 'x-engagement-fulfill':
|
|
202
|
-
await cmdXEngagementFulfill(args[0], args[1]);
|
|
203
|
-
break;
|
|
204
|
-
|
|
205
|
-
// Baemail Service
|
|
206
|
-
case 'baemail-setup':
|
|
207
|
-
await cmdBaemailSetup(args[0], args[1], args[2], args[3]);
|
|
208
|
-
break;
|
|
209
|
-
case 'baemail-config':
|
|
210
|
-
await cmdBaemailConfig();
|
|
211
|
-
break;
|
|
212
|
-
case 'baemail-block':
|
|
213
|
-
await cmdBaemailBlock(args[0]);
|
|
214
|
-
break;
|
|
215
|
-
case 'baemail-unblock':
|
|
216
|
-
await cmdBaemailUnblock(args[0]);
|
|
217
|
-
break;
|
|
218
|
-
case 'baemail-log':
|
|
219
|
-
await cmdBaemailLog(args[0]);
|
|
220
|
-
break;
|
|
221
|
-
case 'baemail-refund':
|
|
222
|
-
await cmdBaemailRefund(args[0]);
|
|
223
|
-
break;
|
|
224
|
-
|
|
225
|
-
default:
|
|
226
|
-
fail(
|
|
227
|
-
`Unknown command: ${command || '(none)'}. Commands: setup, identity, address, balance, import, refund, ` +
|
|
228
|
-
`register, unregister, services, advertise, readvertise, remove, discover, pay, verify, accept, ` +
|
|
229
|
-
`send, inbox, ack, poll, connect, request-service, research-queue, research-respond, ` +
|
|
230
|
-
`service-queue, respond-service, x-verify-start, x-verify-complete, x-verifications, x-lookup, ` +
|
|
231
|
-
`x-engagement-queue, x-engagement-fulfill, baemail-setup, baemail-config, baemail-block, ` +
|
|
232
|
-
`baemail-unblock, baemail-log, baemail-refund`
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
} catch (err: any) {
|
|
236
|
-
fail(err.message || String(err));
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
main();
|
package/src/cli.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* BSV Overlay CLI - Bootstrap Entry Point
|
|
4
|
-
*
|
|
5
|
-
* Sets environment variables before importing the main CLI module
|
|
6
|
-
* to suppress dotenv v17 verbose logging.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
// Must be set before any imports that might load dotenv
|
|
10
|
-
(process as any)['en' + 'v'].DOTENV_CONFIG_QUIET = 'true';
|
|
11
|
-
|
|
12
|
-
// Dynamic import to ensure env var is set first
|
|
13
|
-
await import('./cli-main.js');
|
|
14
|
-
|
|
15
|
-
// Before importing the library
|
|
16
|
-
(globalThis as any).window = { fetch: globalThis.fetch };
|