openclaw-overlay-plugin 0.8.19 → 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 -3
package/dist/src/cli.js
CHANGED
|
@@ -117,14 +117,14 @@ async function getSdk() {
|
|
|
117
117
|
_sdk = await import("@bsv/sdk");
|
|
118
118
|
return _sdk;
|
|
119
119
|
} catch {
|
|
120
|
-
const { fileURLToPath:
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
const
|
|
120
|
+
const { fileURLToPath: fileURLToPath2 } = await import("node:url");
|
|
121
|
+
const path4 = await import("node:path");
|
|
122
|
+
const os2 = await import("node:os");
|
|
123
|
+
const __dirname2 = path4.dirname(fileURLToPath2(import.meta.url));
|
|
124
124
|
const candidates = [
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
path4.resolve(__dirname2, "..", "..", "..", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js"),
|
|
126
|
+
path4.resolve(__dirname2, "..", "..", "..", "..", "..", "a2a-bsv", "packages", "core", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js"),
|
|
127
|
+
path4.resolve(os2.homedir(), "a2a-bsv", "packages", "core", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js")
|
|
128
128
|
];
|
|
129
129
|
for (const p of candidates) {
|
|
130
130
|
try {
|
|
@@ -614,14 +614,14 @@ async function getSdk2() {
|
|
|
614
614
|
_sdk2 = await import("@bsv/sdk");
|
|
615
615
|
return _sdk2;
|
|
616
616
|
} catch {
|
|
617
|
-
const { fileURLToPath:
|
|
618
|
-
const
|
|
619
|
-
const
|
|
620
|
-
const
|
|
617
|
+
const { fileURLToPath: fileURLToPath2 } = await import("node:url");
|
|
618
|
+
const path4 = await import("node:path");
|
|
619
|
+
const os2 = await import("node:os");
|
|
620
|
+
const __dirname2 = path4.dirname(fileURLToPath2(import.meta.url));
|
|
621
621
|
const candidates = [
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
622
|
+
path4.resolve(__dirname2, "..", "..", "..", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js"),
|
|
623
|
+
path4.resolve(__dirname2, "..", "..", "..", "..", "..", "a2a-bsv", "packages", "core", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js"),
|
|
624
|
+
path4.resolve(os2.homedir(), "a2a-bsv", "packages", "core", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js")
|
|
625
625
|
];
|
|
626
626
|
for (const p of candidates) {
|
|
627
627
|
try {
|
|
@@ -822,14 +822,14 @@ async function getSdk3() {
|
|
|
822
822
|
_sdk3 = await import("@bsv/sdk");
|
|
823
823
|
return _sdk3;
|
|
824
824
|
} catch {
|
|
825
|
-
const { fileURLToPath:
|
|
826
|
-
const
|
|
827
|
-
const
|
|
828
|
-
const
|
|
825
|
+
const { fileURLToPath: fileURLToPath2 } = await import("node:url");
|
|
826
|
+
const path4 = await import("node:path");
|
|
827
|
+
const os2 = await import("node:os");
|
|
828
|
+
const __dirname2 = path4.dirname(fileURLToPath2(import.meta.url));
|
|
829
829
|
const candidates = [
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
830
|
+
path4.resolve(__dirname2, "..", "..", "..", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js"),
|
|
831
|
+
path4.resolve(__dirname2, "..", "..", "..", "..", "..", "a2a-bsv", "packages", "core", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js"),
|
|
832
|
+
path4.resolve(os2.homedir(), "a2a-bsv", "packages", "core", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js")
|
|
833
833
|
];
|
|
834
834
|
for (const p of candidates) {
|
|
835
835
|
try {
|
|
@@ -1048,19 +1048,6 @@ function saveServices(services) {
|
|
|
1048
1048
|
ensureStateDir();
|
|
1049
1049
|
fs6.writeFileSync(PATHS.services, JSON.stringify(services, null, 2), "utf-8");
|
|
1050
1050
|
}
|
|
1051
|
-
function loadXVerifications() {
|
|
1052
|
-
try {
|
|
1053
|
-
if (fs6.existsSync(PATHS.xVerifications)) {
|
|
1054
|
-
return JSON.parse(fs6.readFileSync(PATHS.xVerifications, "utf-8"));
|
|
1055
|
-
}
|
|
1056
|
-
} catch {
|
|
1057
|
-
}
|
|
1058
|
-
return [];
|
|
1059
|
-
}
|
|
1060
|
-
function saveXVerifications(verifications) {
|
|
1061
|
-
ensureStateDir();
|
|
1062
|
-
fs6.writeFileSync(PATHS.xVerifications, JSON.stringify(verifications, null, 2), "utf-8");
|
|
1063
|
-
}
|
|
1064
1051
|
function appendToJsonl(filePath, entry) {
|
|
1065
1052
|
ensureStateDir();
|
|
1066
1053
|
fs6.appendFileSync(filePath, JSON.stringify(entry) + "\n");
|
|
@@ -2492,14 +2479,14 @@ async function getSdk4() {
|
|
|
2492
2479
|
_sdk4 = await import("@bsv/sdk");
|
|
2493
2480
|
return _sdk4;
|
|
2494
2481
|
} catch {
|
|
2495
|
-
const { fileURLToPath:
|
|
2496
|
-
const
|
|
2497
|
-
const
|
|
2498
|
-
const
|
|
2482
|
+
const { fileURLToPath: fileURLToPath2 } = await import("node:url");
|
|
2483
|
+
const path4 = await import("node:path");
|
|
2484
|
+
const os2 = await import("node:os");
|
|
2485
|
+
const __dirname2 = path4.dirname(fileURLToPath2(import.meta.url));
|
|
2499
2486
|
const candidates = [
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2487
|
+
path4.resolve(__dirname2, "..", "..", "..", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js"),
|
|
2488
|
+
path4.resolve(__dirname2, "..", "..", "..", "..", "..", "a2a-bsv", "packages", "core", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js"),
|
|
2489
|
+
path4.resolve(os2.homedir(), "a2a-bsv", "packages", "core", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js")
|
|
2503
2490
|
];
|
|
2504
2491
|
for (const p of candidates) {
|
|
2505
2492
|
try {
|
|
@@ -3120,54 +3107,6 @@ async function cmdRespondService(requestId, recipientKey, serviceId, resultJson)
|
|
|
3120
3107
|
});
|
|
3121
3108
|
return ok({ sent: true, requestId, serviceId, to: recipientKey });
|
|
3122
3109
|
}
|
|
3123
|
-
async function cmdResearchRespond(resultJsonPath) {
|
|
3124
|
-
if (!resultJsonPath) return fail("Usage: research-respond <resultJsonFile>");
|
|
3125
|
-
if (!fs11.existsSync(resultJsonPath)) return fail(`File not found: ${resultJsonPath}`);
|
|
3126
|
-
const result = JSON.parse(fs11.readFileSync(resultJsonPath, "utf-8"));
|
|
3127
|
-
const { requestId, from: recipientKey, query, research } = result;
|
|
3128
|
-
if (!requestId || !recipientKey || !research) {
|
|
3129
|
-
return fail("Result JSON must have: requestId, from, query, research");
|
|
3130
|
-
}
|
|
3131
|
-
const { identityKey, privKey } = await loadIdentity();
|
|
3132
|
-
const responsePayload = {
|
|
3133
|
-
requestId,
|
|
3134
|
-
serviceId: "web-research",
|
|
3135
|
-
status: "fulfilled",
|
|
3136
|
-
result: research,
|
|
3137
|
-
paymentAccepted: true,
|
|
3138
|
-
paymentTxid: result.paymentTxid || null,
|
|
3139
|
-
satoshisReceived: result.satoshisReceived || 0,
|
|
3140
|
-
walletAccepted: result.walletAccepted ?? true
|
|
3141
|
-
};
|
|
3142
|
-
const sig = await signRelayMessage(privKey, recipientKey, "service-response", responsePayload);
|
|
3143
|
-
const sendResp = await fetch(`${OVERLAY_URL}/relay/send`, {
|
|
3144
|
-
method: "POST",
|
|
3145
|
-
headers: { "Content-Type": "application/json" },
|
|
3146
|
-
body: JSON.stringify({
|
|
3147
|
-
from: identityKey,
|
|
3148
|
-
to: recipientKey,
|
|
3149
|
-
type: "service-response",
|
|
3150
|
-
payload: responsePayload,
|
|
3151
|
-
signature: sig
|
|
3152
|
-
})
|
|
3153
|
-
});
|
|
3154
|
-
if (!sendResp.ok) {
|
|
3155
|
-
return fail(`Failed to send response: ${await sendResp.text()}`);
|
|
3156
|
-
}
|
|
3157
|
-
const sendResult = await sendResp.json();
|
|
3158
|
-
if (fs11.existsSync(PATHS.researchQueue)) {
|
|
3159
|
-
const lines = fs11.readFileSync(PATHS.researchQueue, "utf-8").trim().split("\n").filter(Boolean);
|
|
3160
|
-
const remaining = lines.filter((l) => {
|
|
3161
|
-
try {
|
|
3162
|
-
return JSON.parse(l).requestId !== requestId;
|
|
3163
|
-
} catch {
|
|
3164
|
-
return true;
|
|
3165
|
-
}
|
|
3166
|
-
});
|
|
3167
|
-
fs11.writeFileSync(PATHS.researchQueue, remaining.length ? remaining.join("\n") + "\n" : "");
|
|
3168
|
-
}
|
|
3169
|
-
return ok({ responded: true, requestId, to: recipientKey, query, pushed: sendResult.pushed });
|
|
3170
|
-
}
|
|
3171
3110
|
var init_respond = __esm({
|
|
3172
3111
|
"src/scripts/services/respond.ts"() {
|
|
3173
3112
|
"use strict";
|
|
@@ -3188,13 +3127,6 @@ async function cmdServiceQueue() {
|
|
|
3188
3127
|
const pending = entries.filter((e) => e.status === "pending");
|
|
3189
3128
|
return ok({ pending, count: pending.length, total: entries.length });
|
|
3190
3129
|
}
|
|
3191
|
-
async function cmdResearchQueue() {
|
|
3192
|
-
if (!fs12.existsSync(PATHS.researchQueue)) {
|
|
3193
|
-
return ok({ pending: [] });
|
|
3194
|
-
}
|
|
3195
|
-
const entries = readJsonl(PATHS.researchQueue);
|
|
3196
|
-
return ok({ pending: entries, count: entries.length });
|
|
3197
|
-
}
|
|
3198
3130
|
var init_queue = __esm({
|
|
3199
3131
|
"src/scripts/services/queue.ts"() {
|
|
3200
3132
|
"use strict";
|
|
@@ -3204,426 +3136,6 @@ var init_queue = __esm({
|
|
|
3204
3136
|
}
|
|
3205
3137
|
});
|
|
3206
3138
|
|
|
3207
|
-
// src/scripts/x-verification/commands.ts
|
|
3208
|
-
import fs13 from "node:fs";
|
|
3209
|
-
async function getSdk5() {
|
|
3210
|
-
if (_sdk5) return _sdk5;
|
|
3211
|
-
try {
|
|
3212
|
-
_sdk5 = await import("@bsv/sdk");
|
|
3213
|
-
return _sdk5;
|
|
3214
|
-
} catch {
|
|
3215
|
-
const { fileURLToPath: fileURLToPath3 } = await import("node:url");
|
|
3216
|
-
const path5 = await import("node:path");
|
|
3217
|
-
const os3 = await import("node:os");
|
|
3218
|
-
const __dirname3 = path5.dirname(fileURLToPath3(import.meta.url));
|
|
3219
|
-
const candidates = [
|
|
3220
|
-
path5.resolve(__dirname3, "..", "..", "..", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js"),
|
|
3221
|
-
path5.resolve(__dirname3, "..", "..", "..", "..", "..", "a2a-bsv", "packages", "core", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js"),
|
|
3222
|
-
path5.resolve(os3.homedir(), "a2a-bsv", "packages", "core", "node_modules", "@bsv", "sdk", "dist", "esm", "mod.js")
|
|
3223
|
-
];
|
|
3224
|
-
for (const p of candidates) {
|
|
3225
|
-
try {
|
|
3226
|
-
_sdk5 = await import(p);
|
|
3227
|
-
return _sdk5;
|
|
3228
|
-
} catch {
|
|
3229
|
-
}
|
|
3230
|
-
}
|
|
3231
|
-
throw new Error("Cannot find @bsv/sdk. Run setup.sh first.");
|
|
3232
|
-
}
|
|
3233
|
-
}
|
|
3234
|
-
async function cmdXVerifyStart(handleArg) {
|
|
3235
|
-
if (!handleArg) {
|
|
3236
|
-
return fail("Usage: x-verify-start <@handle>");
|
|
3237
|
-
}
|
|
3238
|
-
const sdk = await getSdk5();
|
|
3239
|
-
const handle = handleArg.startsWith("@") ? handleArg : `@${handleArg}`;
|
|
3240
|
-
const { identityKey, privKey } = await loadIdentity();
|
|
3241
|
-
const message = `Verify ${identityKey}`;
|
|
3242
|
-
const msgHash = sdk.Hash.sha256(Array.from(new TextEncoder().encode(message)));
|
|
3243
|
-
const sig = privKey.sign(msgHash);
|
|
3244
|
-
const signatureHex = Array.from(sig.toDER()).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3245
|
-
const pending = {
|
|
3246
|
-
identityKey,
|
|
3247
|
-
handle,
|
|
3248
|
-
signature: signatureHex,
|
|
3249
|
-
message,
|
|
3250
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3251
|
-
};
|
|
3252
|
-
ensureStateDir();
|
|
3253
|
-
fs13.writeFileSync(PATHS.pendingXVerification, JSON.stringify(pending, null, 2));
|
|
3254
|
-
const tweetText = `BSV Agent Verify: ${identityKey.slice(0, 10)}...${identityKey.slice(-10)} sig:${signatureHex.slice(0, 40)}`;
|
|
3255
|
-
return ok({
|
|
3256
|
-
tweetText,
|
|
3257
|
-
handle,
|
|
3258
|
-
identityKey,
|
|
3259
|
-
signature: signatureHex,
|
|
3260
|
-
note: `Post the tweet above from ${handle}, then run: x-verify-complete <tweet_url>`
|
|
3261
|
-
});
|
|
3262
|
-
}
|
|
3263
|
-
async function cmdXVerifyComplete(tweetUrl) {
|
|
3264
|
-
if (!tweetUrl) return fail("Usage: x-verify-complete <tweet-url>");
|
|
3265
|
-
if (!fs13.existsSync(PATHS.pendingXVerification)) {
|
|
3266
|
-
return fail("No pending X verification. Run x-verify-start first.");
|
|
3267
|
-
}
|
|
3268
|
-
const pending = JSON.parse(fs13.readFileSync(PATHS.pendingXVerification, "utf-8"));
|
|
3269
|
-
const tweetIdMatch = tweetUrl.match(/status\/(\d+)/);
|
|
3270
|
-
if (!tweetIdMatch) return fail("Invalid tweet URL. Expected format: https://x.com/user/status/123456789");
|
|
3271
|
-
const tweetId = tweetIdMatch[1];
|
|
3272
|
-
let tweetData;
|
|
3273
|
-
try {
|
|
3274
|
-
return fail('X verification via "bird" CLI is currently disabled for security compliance. Please verify manually.');
|
|
3275
|
-
} catch (err) {
|
|
3276
|
-
return fail(`Failed to fetch tweet: ${err.message}. Make sure bird CLI is configured.`);
|
|
3277
|
-
}
|
|
3278
|
-
const tweetText = tweetData.text || tweetData.full_text || "";
|
|
3279
|
-
if (!tweetText.includes(pending.identityKey.slice(0, 10))) {
|
|
3280
|
-
return fail("Tweet does not contain the expected identity key.");
|
|
3281
|
-
}
|
|
3282
|
-
if (!tweetText.includes(pending.signature.slice(0, 40))) {
|
|
3283
|
-
return fail("Tweet does not contain the expected verification signature prefix.");
|
|
3284
|
-
}
|
|
3285
|
-
const xUserId = tweetData.user?.id_str || tweetData.authorId || tweetData.author?.id || tweetData.user_id;
|
|
3286
|
-
const xHandle = tweetData.user?.screen_name || tweetData.author?.username || tweetData.author?.name || pending.handle.replace("@", "");
|
|
3287
|
-
if (!xUserId) {
|
|
3288
|
-
return fail("Could not extract X user ID from tweet data.");
|
|
3289
|
-
}
|
|
3290
|
-
const verificationPayload = {
|
|
3291
|
-
protocol: PROTOCOL_ID,
|
|
3292
|
-
type: "x-verification",
|
|
3293
|
-
identityKey: pending.identityKey,
|
|
3294
|
-
xHandle: `@${xHandle}`,
|
|
3295
|
-
xUserId,
|
|
3296
|
-
tweetId,
|
|
3297
|
-
tweetUrl,
|
|
3298
|
-
signature: pending.signature,
|
|
3299
|
-
verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3300
|
-
};
|
|
3301
|
-
let result = { txid: null, funded: "pending-server-support" };
|
|
3302
|
-
let onChainStored = false;
|
|
3303
|
-
try {
|
|
3304
|
-
result = await buildRealOverlayTransaction(verificationPayload, TOPICS.X_VERIFICATION);
|
|
3305
|
-
onChainStored = true;
|
|
3306
|
-
} catch (err) {
|
|
3307
|
-
console.error(`[x-verify] On-chain storage failed: ${err.message}`);
|
|
3308
|
-
console.error("[x-verify] Storing verification locally.");
|
|
3309
|
-
}
|
|
3310
|
-
const verifications = loadXVerifications();
|
|
3311
|
-
verifications.push({
|
|
3312
|
-
...verificationPayload,
|
|
3313
|
-
txid: result.txid
|
|
3314
|
-
});
|
|
3315
|
-
saveXVerifications(verifications);
|
|
3316
|
-
fs13.unlinkSync(PATHS.pendingXVerification);
|
|
3317
|
-
return ok({
|
|
3318
|
-
verified: true,
|
|
3319
|
-
identityKey: pending.identityKey,
|
|
3320
|
-
xHandle: `@${xHandle}`,
|
|
3321
|
-
xUserId,
|
|
3322
|
-
tweetId,
|
|
3323
|
-
txid: result.txid,
|
|
3324
|
-
funded: result.funded,
|
|
3325
|
-
onChainStored,
|
|
3326
|
-
note: onChainStored ? void 0 : "Stored locally. On-chain anchoring pending server topic manager deployment."
|
|
3327
|
-
});
|
|
3328
|
-
}
|
|
3329
|
-
async function cmdXVerifications() {
|
|
3330
|
-
const verifications = loadXVerifications();
|
|
3331
|
-
return ok({ verifications, count: verifications.length });
|
|
3332
|
-
}
|
|
3333
|
-
async function cmdXLookup(query) {
|
|
3334
|
-
try {
|
|
3335
|
-
const lookupQuery = query ? query.startsWith("@") ? { xHandle: query } : { identityKey: query } : { type: "list" };
|
|
3336
|
-
const response = await lookupOverlay(LOOKUP_SERVICES.X_VERIFICATIONS, lookupQuery);
|
|
3337
|
-
return ok({ verifications: response.outputs || response || [], query: lookupQuery });
|
|
3338
|
-
} catch {
|
|
3339
|
-
return ok({ verifications: [], query, note: "X verification lookup service may not be deployed yet." });
|
|
3340
|
-
}
|
|
3341
|
-
}
|
|
3342
|
-
async function cmdXEngagementQueue() {
|
|
3343
|
-
if (!fs13.existsSync(PATHS.xEngagementQueue)) {
|
|
3344
|
-
return ok({ queue: [], count: 0 });
|
|
3345
|
-
}
|
|
3346
|
-
const queue = readJsonl(PATHS.xEngagementQueue).filter((e) => e.status === "pending");
|
|
3347
|
-
return ok({ queue, count: queue.length });
|
|
3348
|
-
}
|
|
3349
|
-
async function cmdXEngagementFulfill(requestId, proofUrl) {
|
|
3350
|
-
if (!requestId) return fail("Usage: x-engagement-fulfill <requestId> [proofUrl]");
|
|
3351
|
-
if (!fs13.existsSync(PATHS.xEngagementQueue)) {
|
|
3352
|
-
return fail("No engagement queue found.");
|
|
3353
|
-
}
|
|
3354
|
-
const queue = readJsonl(PATHS.xEngagementQueue);
|
|
3355
|
-
const entryIndex = queue.findIndex((e) => e.requestId === requestId);
|
|
3356
|
-
if (entryIndex === -1) {
|
|
3357
|
-
return fail(`Request ${requestId} not found in queue.`);
|
|
3358
|
-
}
|
|
3359
|
-
queue[entryIndex].status = "fulfilled";
|
|
3360
|
-
queue[entryIndex].fulfilledAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3361
|
-
queue[entryIndex].proofUrl = proofUrl || null;
|
|
3362
|
-
fs13.writeFileSync(PATHS.xEngagementQueue, queue.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
3363
|
-
return ok({
|
|
3364
|
-
fulfilled: true,
|
|
3365
|
-
requestId,
|
|
3366
|
-
entry: queue[entryIndex]
|
|
3367
|
-
});
|
|
3368
|
-
}
|
|
3369
|
-
var _sdk5;
|
|
3370
|
-
var init_commands2 = __esm({
|
|
3371
|
-
"src/scripts/x-verification/commands.ts"() {
|
|
3372
|
-
"use strict";
|
|
3373
|
-
init_config();
|
|
3374
|
-
init_output();
|
|
3375
|
-
init_identity();
|
|
3376
|
-
init_storage();
|
|
3377
|
-
init_transaction();
|
|
3378
|
-
_sdk5 = null;
|
|
3379
|
-
}
|
|
3380
|
-
});
|
|
3381
|
-
|
|
3382
|
-
// src/scripts/baemail/commands.ts
|
|
3383
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3384
|
-
import path4 from "node:path";
|
|
3385
|
-
import os2 from "node:os";
|
|
3386
|
-
import fs14 from "node:fs";
|
|
3387
|
-
import process2 from "node:process";
|
|
3388
|
-
async function loadBaemailConfig() {
|
|
3389
|
-
const defaults = {
|
|
3390
|
-
enabled: true,
|
|
3391
|
-
priceSats: 100,
|
|
3392
|
-
autoRefund: true,
|
|
3393
|
-
blocklist: [],
|
|
3394
|
-
maxMessageLength: 4e3,
|
|
3395
|
-
deliveryChannel: "agent-hook",
|
|
3396
|
-
tiers: {
|
|
3397
|
-
standard: 100,
|
|
3398
|
-
priority: 500,
|
|
3399
|
-
urgent: 1e3
|
|
3400
|
-
}
|
|
3401
|
-
};
|
|
3402
|
-
if (!fs14.existsSync(PATHS2.baemailConfig)) {
|
|
3403
|
-
return defaults;
|
|
3404
|
-
}
|
|
3405
|
-
try {
|
|
3406
|
-
const config = JSON.parse(fs14.readFileSync(PATHS2.baemailConfig, "utf-8"));
|
|
3407
|
-
return { ...defaults, ...config };
|
|
3408
|
-
} catch {
|
|
3409
|
-
return defaults;
|
|
3410
|
-
}
|
|
3411
|
-
}
|
|
3412
|
-
async function fetchWithTimeout2(url, options = {}) {
|
|
3413
|
-
const { timeout = 15e3 } = options;
|
|
3414
|
-
const controller = new AbortController();
|
|
3415
|
-
const id = setTimeout(() => controller.abort(), timeout);
|
|
3416
|
-
try {
|
|
3417
|
-
const response = await fetch(url, {
|
|
3418
|
-
...options,
|
|
3419
|
-
signal: controller.signal
|
|
3420
|
-
});
|
|
3421
|
-
clearTimeout(id);
|
|
3422
|
-
return response;
|
|
3423
|
-
} catch (err) {
|
|
3424
|
-
clearTimeout(id);
|
|
3425
|
-
throw err;
|
|
3426
|
-
}
|
|
3427
|
-
}
|
|
3428
|
-
async function cmdBaemailLog(limitStr) {
|
|
3429
|
-
const limit = parseInt(limitStr || "20", 10) || 20;
|
|
3430
|
-
if (!fs14.existsSync(PATHS2.baemailLog)) {
|
|
3431
|
-
return ok({ log: [], count: 0 });
|
|
3432
|
-
}
|
|
3433
|
-
const lines = fs14.readFileSync(PATHS2.baemailLog, "utf-8").split("\n").filter((l) => l.trim());
|
|
3434
|
-
const entries = lines.map((l) => {
|
|
3435
|
-
try {
|
|
3436
|
-
return JSON.parse(l);
|
|
3437
|
-
} catch {
|
|
3438
|
-
return null;
|
|
3439
|
-
}
|
|
3440
|
-
}).filter(Boolean);
|
|
3441
|
-
const recent = entries.slice(-limit).reverse();
|
|
3442
|
-
return ok({ log: recent, count: entries.length, showing: recent.length });
|
|
3443
|
-
}
|
|
3444
|
-
async function cmdBaemailSetup(priceSatsStr, prioritySats, urgentSats, channel) {
|
|
3445
|
-
const standard = parseInt(priceSatsStr, 10) || 100;
|
|
3446
|
-
const priority = parseInt(prioritySats || "", 10) || standard * 5;
|
|
3447
|
-
const urgent = parseInt(urgentSats || "", 10) || standard * 10;
|
|
3448
|
-
const config = {
|
|
3449
|
-
enabled: true,
|
|
3450
|
-
priceSats: standard,
|
|
3451
|
-
autoRefund: true,
|
|
3452
|
-
deliveryChannel: channel || "agent-hook",
|
|
3453
|
-
tiers: { standard, priority, urgent }
|
|
3454
|
-
};
|
|
3455
|
-
const dir = path4.dirname(PATHS2.baemailConfig);
|
|
3456
|
-
if (!fs14.existsSync(dir)) fs14.mkdirSync(dir, { recursive: true });
|
|
3457
|
-
fs14.writeFileSync(PATHS2.baemailConfig, JSON.stringify(config, null, 2));
|
|
3458
|
-
return ok({ message: `Baemail setup complete.`, config });
|
|
3459
|
-
}
|
|
3460
|
-
async function cmdBaemailConfig() {
|
|
3461
|
-
const config = await loadBaemailConfig();
|
|
3462
|
-
return ok(config);
|
|
3463
|
-
}
|
|
3464
|
-
async function cmdBaemailBlock(pubkey) {
|
|
3465
|
-
if (!pubkey) return fail("Usage: baemail-block <pubkey>");
|
|
3466
|
-
let blocklist = [];
|
|
3467
|
-
if (fs14.existsSync(PATHS2.baemailBlocklist)) {
|
|
3468
|
-
try {
|
|
3469
|
-
blocklist = JSON.parse(fs14.readFileSync(PATHS2.baemailBlocklist, "utf-8"));
|
|
3470
|
-
} catch {
|
|
3471
|
-
blocklist = [];
|
|
3472
|
-
}
|
|
3473
|
-
}
|
|
3474
|
-
if (!blocklist.includes(pubkey)) blocklist.push(pubkey);
|
|
3475
|
-
fs14.writeFileSync(PATHS2.baemailBlocklist, JSON.stringify(blocklist, null, 2));
|
|
3476
|
-
return ok({ blocked: true, pubkey, count: blocklist.length });
|
|
3477
|
-
}
|
|
3478
|
-
async function cmdBaemailUnblock(pubkey) {
|
|
3479
|
-
if (!pubkey) return fail("Usage: baemail-unblock <pubkey>");
|
|
3480
|
-
let blocklist = [];
|
|
3481
|
-
if (fs14.existsSync(PATHS2.baemailBlocklist)) {
|
|
3482
|
-
try {
|
|
3483
|
-
blocklist = JSON.parse(fs14.readFileSync(PATHS2.baemailBlocklist, "utf-8"));
|
|
3484
|
-
} catch {
|
|
3485
|
-
blocklist = [];
|
|
3486
|
-
}
|
|
3487
|
-
}
|
|
3488
|
-
blocklist = blocklist.filter((p) => p !== pubkey);
|
|
3489
|
-
fs14.writeFileSync(PATHS2.baemailBlocklist, JSON.stringify(blocklist, null, 2));
|
|
3490
|
-
return ok({ unblocked: true, pubkey, count: blocklist.length });
|
|
3491
|
-
}
|
|
3492
|
-
async function cmdBaemailRefund(requestId) {
|
|
3493
|
-
if (!requestId) return fail("Usage: baemail-refund <requestId>");
|
|
3494
|
-
if (!fs14.existsSync(PATHS2.baemailLog)) {
|
|
3495
|
-
return fail("No baemail log found");
|
|
3496
|
-
}
|
|
3497
|
-
const lines = fs14.readFileSync(PATHS2.baemailLog, "utf-8").split("\n").filter((l) => l.trim());
|
|
3498
|
-
const entries = lines.map((l, idx) => {
|
|
3499
|
-
try {
|
|
3500
|
-
return { ...JSON.parse(l), _lineIdx: idx };
|
|
3501
|
-
} catch {
|
|
3502
|
-
return null;
|
|
3503
|
-
}
|
|
3504
|
-
}).filter(Boolean);
|
|
3505
|
-
const entry = entries.find((e) => e.requestId === requestId);
|
|
3506
|
-
if (!entry) {
|
|
3507
|
-
return fail(`Request ${requestId} not found in baemail log`);
|
|
3508
|
-
}
|
|
3509
|
-
if (entry.deliverySuccess) {
|
|
3510
|
-
return fail("This delivery was successful \u2014 no refund needed");
|
|
3511
|
-
}
|
|
3512
|
-
if (entry.refundStatus === "completed") {
|
|
3513
|
-
return fail("Refund already processed for this request");
|
|
3514
|
-
}
|
|
3515
|
-
const { identityKey, privKey: rootKey } = await loadIdentity();
|
|
3516
|
-
const walletIdentityRaw = fs14.readFileSync(PATHS2.walletIdentity, "utf-8");
|
|
3517
|
-
const walletIdentity = JSON.parse(walletIdentityRaw);
|
|
3518
|
-
let sdk;
|
|
3519
|
-
try {
|
|
3520
|
-
sdk = await import("@bsv/sdk");
|
|
3521
|
-
} catch {
|
|
3522
|
-
return fail("Cannot load @bsv/sdk for refund transaction");
|
|
3523
|
-
}
|
|
3524
|
-
const { Transaction: Transaction3, P2PKH, PrivateKey: PrivateKey2, PublicKey, Hash } = sdk;
|
|
3525
|
-
const refundSats = entry.paidSats - 1;
|
|
3526
|
-
if (refundSats < 1) {
|
|
3527
|
-
return fail("Amount too small to refund");
|
|
3528
|
-
}
|
|
3529
|
-
const senderPubKey = PublicKey.fromString(entry.from);
|
|
3530
|
-
const refundAddress = senderPubKey.toAddress(NETWORK).toString();
|
|
3531
|
-
try {
|
|
3532
|
-
const { address } = await deriveWalletAddress(rootKey);
|
|
3533
|
-
const wocNet = NETWORK === "mainnet" ? "main" : "test";
|
|
3534
|
-
const utxosResp = await fetchWithTimeout2(`https://api.whatsonchain.com/v1/bsv/${wocNet}/address/${address}/unspent/all`);
|
|
3535
|
-
const data = await utxosResp.json();
|
|
3536
|
-
const utxos = data.result || [];
|
|
3537
|
-
if (!utxos || utxos.length === 0) {
|
|
3538
|
-
return fail(`No UTXOs available for refund at ${address}`);
|
|
3539
|
-
}
|
|
3540
|
-
const tx = new Transaction3();
|
|
3541
|
-
let totalInput = 0;
|
|
3542
|
-
for (const utxo of utxos) {
|
|
3543
|
-
if (totalInput >= refundSats + 50) break;
|
|
3544
|
-
tx.addInput({
|
|
3545
|
-
sourceTXID: utxo.tx_hash,
|
|
3546
|
-
sourceOutputIndex: utxo.tx_pos,
|
|
3547
|
-
sourceSatoshis: utxo.value,
|
|
3548
|
-
script: new P2PKH().lock(rootKey.toPublicKey().toAddress(NETWORK)).toHex(),
|
|
3549
|
-
unlockingScriptTemplate: new P2PKH().unlock(rootKey)
|
|
3550
|
-
});
|
|
3551
|
-
totalInput += utxo.value;
|
|
3552
|
-
}
|
|
3553
|
-
if (totalInput < refundSats + 10) {
|
|
3554
|
-
return fail("Insufficient funds for refund");
|
|
3555
|
-
}
|
|
3556
|
-
tx.addOutput({
|
|
3557
|
-
satoshis: refundSats,
|
|
3558
|
-
lockingScript: new P2PKH().lock(refundAddress)
|
|
3559
|
-
});
|
|
3560
|
-
const fee = 10;
|
|
3561
|
-
const change = totalInput - refundSats - fee;
|
|
3562
|
-
if (change > 1) {
|
|
3563
|
-
tx.addOutput({
|
|
3564
|
-
satoshis: change,
|
|
3565
|
-
lockingScript: new P2PKH().lock(rootKey.toPublicKey().toAddress(NETWORK))
|
|
3566
|
-
});
|
|
3567
|
-
}
|
|
3568
|
-
await tx.sign();
|
|
3569
|
-
const arcUrl = process2["env"].BSV_ARC_URL;
|
|
3570
|
-
let broadcastResp;
|
|
3571
|
-
if (arcUrl) {
|
|
3572
|
-
broadcastResp = await fetchWithTimeout2(`${arcUrl.replace(/\/$/, "")}/v1/tx`, {
|
|
3573
|
-
method: "POST",
|
|
3574
|
-
headers: { "Content-Type": "application/json" },
|
|
3575
|
-
body: JSON.stringify({ rawTx: tx.toHex() })
|
|
3576
|
-
});
|
|
3577
|
-
} else {
|
|
3578
|
-
broadcastResp = await fetchWithTimeout2(`https://api.whatsonchain.com/v1/bsv/${wocNet}/tx/raw`, {
|
|
3579
|
-
method: "POST",
|
|
3580
|
-
headers: { "Content-Type": "application/json" },
|
|
3581
|
-
body: JSON.stringify({ txhex: tx.toHex() })
|
|
3582
|
-
});
|
|
3583
|
-
}
|
|
3584
|
-
if (!broadcastResp.ok) {
|
|
3585
|
-
const errBody = await broadcastResp.text();
|
|
3586
|
-
return fail(`Broadcast failed: ${errBody}`);
|
|
3587
|
-
}
|
|
3588
|
-
const txid = tx.id("hex");
|
|
3589
|
-
const updatedLines = lines.map((l, idx) => {
|
|
3590
|
-
if (idx === entry._lineIdx) {
|
|
3591
|
-
const updated = { ...JSON.parse(l), refundStatus: "completed", refundTxid: txid, refundedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
3592
|
-
return JSON.stringify(updated);
|
|
3593
|
-
}
|
|
3594
|
-
return l;
|
|
3595
|
-
});
|
|
3596
|
-
fs14.writeFileSync(PATHS2.baemailLog, updatedLines.join("\n") + "\n");
|
|
3597
|
-
return ok({
|
|
3598
|
-
refunded: true,
|
|
3599
|
-
requestId,
|
|
3600
|
-
refundSats,
|
|
3601
|
-
refundAddress,
|
|
3602
|
-
txid,
|
|
3603
|
-
note: `Refunded ${refundSats} sats to sender`
|
|
3604
|
-
});
|
|
3605
|
-
} catch (err) {
|
|
3606
|
-
return fail(`Refund failed: ${err.message}`);
|
|
3607
|
-
}
|
|
3608
|
-
}
|
|
3609
|
-
var __filename2, __dirname2, PATHS2;
|
|
3610
|
-
var init_commands3 = __esm({
|
|
3611
|
-
"src/scripts/baemail/commands.ts"() {
|
|
3612
|
-
"use strict";
|
|
3613
|
-
init_output();
|
|
3614
|
-
init_identity();
|
|
3615
|
-
init_config();
|
|
3616
|
-
__filename2 = fileURLToPath2(import.meta.url);
|
|
3617
|
-
__dirname2 = path4.dirname(__filename2);
|
|
3618
|
-
PATHS2 = {
|
|
3619
|
-
walletIdentity: path4.join(os2.homedir(), ".openclaw", "bsv-wallet", "wallet-identity.json"),
|
|
3620
|
-
baemailLog: path4.join(os2.homedir(), ".openclaw", "openclaw-overlay", "baemail-deliveries.jsonl"),
|
|
3621
|
-
baemailConfig: path4.join(os2.homedir(), ".openclaw", "openclaw-overlay", "baemail-config.json"),
|
|
3622
|
-
baemailBlocklist: path4.join(os2.homedir(), ".openclaw", "openclaw-overlay", "baemail-blocklist.json")
|
|
3623
|
-
};
|
|
3624
|
-
}
|
|
3625
|
-
});
|
|
3626
|
-
|
|
3627
3139
|
// src/cli-main.ts
|
|
3628
3140
|
var cli_main_exports = {};
|
|
3629
3141
|
async function main() {
|
|
@@ -3642,10 +3154,7 @@ async function main() {
|
|
|
3642
3154
|
discovery: ["discover [--service <type>] [--agent <name>]", "advertise-ship <domain> <topic>", "advertise-slap <domain> <service>"],
|
|
3643
3155
|
payments: ["pay <pubkey> <sats> [desc]", "verify <beef>", "accept <beef> <prefix> <suffix> <senderKey> [desc]"],
|
|
3644
3156
|
messaging: ["send <key> <type> <json>", "inbox", "ack", "poll", "connect"],
|
|
3645
|
-
"service-requests": ["request-service <key> <serviceId> <sats> [input]", "service-queue", "respond-service <reqId> <key> <serviceId> <result>"]
|
|
3646
|
-
research: ["research-queue", "research-respond <reqId>"],
|
|
3647
|
-
"x-verification": ["x-verify-start <handle>", "x-verify-complete <handle>", "x-verifications", "x-lookup <handle>", "x-engagement-queue", "x-engagement-fulfill <reqId> <result>"],
|
|
3648
|
-
baemail: ["baemail-setup <price> <xHandle> <forwardEmail> <greeting>", "baemail-config", "baemail-block <sender>", "baemail-unblock <sender>", "baemail-log [limit]", "baemail-refund <msgId>"]
|
|
3157
|
+
"service-requests": ["request-service <key> <serviceId> <sats> [input]", "service-queue", "respond-service <reqId> <key> <serviceId> <result>"]
|
|
3649
3158
|
}
|
|
3650
3159
|
});
|
|
3651
3160
|
break;
|
|
@@ -3730,60 +3239,15 @@ async function main() {
|
|
|
3730
3239
|
case "request-service":
|
|
3731
3240
|
await cmdRequestService(args[0], args[1], args[2], args[3]);
|
|
3732
3241
|
break;
|
|
3733
|
-
case "research-respond":
|
|
3734
|
-
await cmdResearchRespond(args[0]);
|
|
3735
|
-
break;
|
|
3736
|
-
case "research-queue":
|
|
3737
|
-
await cmdResearchQueue();
|
|
3738
|
-
break;
|
|
3739
3242
|
case "service-queue":
|
|
3740
3243
|
await cmdServiceQueue();
|
|
3741
3244
|
break;
|
|
3742
3245
|
case "respond-service":
|
|
3743
3246
|
await cmdRespondService(args[0], args[1], args[2], args.slice(3).join(" "));
|
|
3744
3247
|
break;
|
|
3745
|
-
// X Account Verification
|
|
3746
|
-
case "x-verify-start":
|
|
3747
|
-
await cmdXVerifyStart(args[0]);
|
|
3748
|
-
break;
|
|
3749
|
-
case "x-verify-complete":
|
|
3750
|
-
await cmdXVerifyComplete(args[0]);
|
|
3751
|
-
break;
|
|
3752
|
-
case "x-verifications":
|
|
3753
|
-
await cmdXVerifications();
|
|
3754
|
-
break;
|
|
3755
|
-
case "x-lookup":
|
|
3756
|
-
await cmdXLookup(args[0]);
|
|
3757
|
-
break;
|
|
3758
|
-
// X Engagement Service
|
|
3759
|
-
case "x-engagement-queue":
|
|
3760
|
-
await cmdXEngagementQueue();
|
|
3761
|
-
break;
|
|
3762
|
-
case "x-engagement-fulfill":
|
|
3763
|
-
await cmdXEngagementFulfill(args[0], args[1]);
|
|
3764
|
-
break;
|
|
3765
|
-
// Baemail Service
|
|
3766
|
-
case "baemail-setup":
|
|
3767
|
-
await cmdBaemailSetup(args[0], args[1], args[2], args[3]);
|
|
3768
|
-
break;
|
|
3769
|
-
case "baemail-config":
|
|
3770
|
-
await cmdBaemailConfig();
|
|
3771
|
-
break;
|
|
3772
|
-
case "baemail-block":
|
|
3773
|
-
await cmdBaemailBlock(args[0]);
|
|
3774
|
-
break;
|
|
3775
|
-
case "baemail-unblock":
|
|
3776
|
-
await cmdBaemailUnblock(args[0]);
|
|
3777
|
-
break;
|
|
3778
|
-
case "baemail-log":
|
|
3779
|
-
await cmdBaemailLog(args[0]);
|
|
3780
|
-
break;
|
|
3781
|
-
case "baemail-refund":
|
|
3782
|
-
await cmdBaemailRefund(args[0]);
|
|
3783
|
-
break;
|
|
3784
3248
|
default:
|
|
3785
3249
|
fail(
|
|
3786
|
-
`Unknown command: ${command || "(none)"}. Commands: setup, identity, address, balance, import, refund, register, unregister, services, advertise, readvertise, remove, discover, pay, verify, accept, send, inbox, ack, poll, connect, request-service,
|
|
3250
|
+
`Unknown command: ${command || "(none)"}. Commands: setup, identity, address, balance, import, refund, register, unregister, services, advertise, readvertise, remove, discover, pay, verify, accept, send, inbox, ack, poll, connect, request-service, service-queue, respond-service`
|
|
3787
3251
|
);
|
|
3788
3252
|
}
|
|
3789
3253
|
} catch (err) {
|
|
@@ -3809,8 +3273,6 @@ var init_cli_main = __esm({
|
|
|
3809
3273
|
init_request();
|
|
3810
3274
|
init_respond();
|
|
3811
3275
|
init_queue();
|
|
3812
|
-
init_commands2();
|
|
3813
|
-
init_commands3();
|
|
3814
3276
|
[, , command, ...args] = process.argv;
|
|
3815
3277
|
main();
|
|
3816
3278
|
}
|