@openclaw/nostr 2026.7.2-beta.2 → 2026.7.2-beta.3
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/api.js +11 -5
- package/dist/{channel-B51rExHD.js → channel-DgBHZ53s.js} +27 -18
- package/dist/channel-plugin-api.js +1 -1
- package/dist/inbound-direct-dm-runtime-DHn9NoYN.js +2 -0
- package/dist/setup-api.js +1 -1
- package/dist/setup-plugin-api.js +2 -2
- package/dist/{setup-surface-B52P4uo2.js → setup-surface-BF7_7BEx.js} +2 -2
- package/npm-shrinkwrap.json +3 -3
- package/package.json +4 -4
- package/dist/inbound-direct-dm-runtime-EdLLVtkh.js +0 -2
package/dist/api.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { o as resolveNostrAccount } from "./setup-surface-
|
|
1
|
+
import { o as resolveNostrAccount } from "./setup-surface-BF7_7BEx.js";
|
|
2
2
|
import { getPluginRuntimeGatewayRequestScope } from "./runtime-api.js";
|
|
3
3
|
import { n as NostrProfileSchema } from "./config-schema-CelPzg1N.js";
|
|
4
|
-
import { a as setNostrRuntime, i as getNostrRuntime, n as nostrPlugin, o as contentToProfile, r as publishNostrProfile, t as getNostrProfileState } from "./channel-
|
|
4
|
+
import { a as setNostrRuntime, i as getNostrRuntime, n as nostrPlugin, o as contentToProfile, r as publishNostrProfile, t as getNostrProfileState } from "./channel-DgBHZ53s.js";
|
|
5
5
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, readStringValue } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { SimplePool } from "nostr-tools";
|
|
@@ -115,9 +115,9 @@ async function importProfileFromRelays(opts) {
|
|
|
115
115
|
relaysQueried
|
|
116
116
|
};
|
|
117
117
|
const bestEvent = events.reduce((current, candidate) => candidate.event.created_at > current.event.created_at ? candidate : current);
|
|
118
|
-
let
|
|
118
|
+
let parsedContent;
|
|
119
119
|
try {
|
|
120
|
-
|
|
120
|
+
parsedContent = JSON.parse(bestEvent.event.content);
|
|
121
121
|
} catch {
|
|
122
122
|
return {
|
|
123
123
|
ok: false,
|
|
@@ -126,9 +126,15 @@ async function importProfileFromRelays(opts) {
|
|
|
126
126
|
sourceRelay: bestEvent.relay
|
|
127
127
|
};
|
|
128
128
|
}
|
|
129
|
+
if (typeof parsedContent !== "object" || parsedContent === null || Array.isArray(parsedContent)) return {
|
|
130
|
+
ok: false,
|
|
131
|
+
error: "Profile event content must be a JSON object",
|
|
132
|
+
relaysQueried,
|
|
133
|
+
sourceRelay: bestEvent.relay
|
|
134
|
+
};
|
|
129
135
|
return {
|
|
130
136
|
ok: true,
|
|
131
|
-
profile: sanitizeProfileUrls(contentToProfile(
|
|
137
|
+
profile: sanitizeProfileUrls(contentToProfile(parsedContent)),
|
|
132
138
|
event: {
|
|
133
139
|
id: bestEvent.event.id,
|
|
134
140
|
pubkey: bestEvent.event.pubkey,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as resolveDefaultNostrAccountId, c as validatePrivateKey, i as listNostrAccountIds, n as nostrSetupWizard, o as resolveNostrAccount, s as normalizePubkey, t as nostrSetupAdapter } from "./setup-surface-
|
|
1
|
+
import { a as resolveDefaultNostrAccountId, c as validatePrivateKey, i as listNostrAccountIds, n as nostrSetupWizard, o as resolveNostrAccount, s as normalizePubkey, t as nostrSetupAdapter } from "./setup-surface-BF7_7BEx.js";
|
|
2
2
|
import { a as collectStatusIssuesFromLastError, i as buildChannelConfigSchema, n as NostrProfileSchema, o as createDefaultChannelRuntimeState, r as DEFAULT_ACCOUNT_ID, s as formatPairingApproveHint, t as NostrConfigSchema } from "./config-schema-CelPzg1N.js";
|
|
3
3
|
import { i as DEFAULT_RELAYS } from "./setup-adapter-DEU3o8MF.js";
|
|
4
4
|
import { t as normalizeNostrStateAccountId } from "./state-account-id-CvBZ9s6P.js";
|
|
@@ -275,6 +275,16 @@ function contentToProfile(content) {
|
|
|
275
275
|
return profile;
|
|
276
276
|
}
|
|
277
277
|
//#endregion
|
|
278
|
+
//#region extensions/nostr/src/relay-publish.ts
|
|
279
|
+
const CONNECTION_FAILURE_PREFIX = "connection failure: ";
|
|
280
|
+
async function publishNostrEventToRelay(pool, relay, event) {
|
|
281
|
+
const publishPromise = pool.publish([relay], event)[0];
|
|
282
|
+
if (!publishPromise) throw new Error(`Failed to create publish promise for relay ${relay}`);
|
|
283
|
+
const result = await publishPromise;
|
|
284
|
+
if (result.startsWith(CONNECTION_FAILURE_PREFIX)) throw new Error(result.slice(20));
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
287
|
+
//#endregion
|
|
278
288
|
//#region extensions/nostr/src/nostr-profile.ts
|
|
279
289
|
/**
|
|
280
290
|
* Nostr Profile Management (NIP-01 kind:0)
|
|
@@ -323,7 +333,7 @@ async function publishProfileEvent(pool, relays, event) {
|
|
|
323
333
|
const timeoutPromise = new Promise((_, reject) => {
|
|
324
334
|
timer = setTimeout(() => reject(/* @__PURE__ */ new Error("timeout")), RELAY_PUBLISH_TIMEOUT_MS);
|
|
325
335
|
});
|
|
326
|
-
await Promise.race([
|
|
336
|
+
await Promise.race([publishNostrEventToRelay(pool, relay, event), timeoutPromise]);
|
|
327
337
|
successes.push(relay);
|
|
328
338
|
} catch (err) {
|
|
329
339
|
const errorMessage = formatErrorMessage(err);
|
|
@@ -820,7 +830,7 @@ async function startNostrBus(options) {
|
|
|
820
830
|
return;
|
|
821
831
|
}
|
|
822
832
|
const replyTo = async (text) => {
|
|
823
|
-
await sendEncryptedDm(pool, sk, event.pubkey, text, relays, metrics, circuitBreakers, healthTracker, onError);
|
|
833
|
+
await sendEncryptedDm(pool, sk, event.pubkey, text, relays, metrics, circuitBreakers, healthTracker, onError, event.id);
|
|
824
834
|
};
|
|
825
835
|
const rejectIfGlobalRateLimited = () => {
|
|
826
836
|
updateRateLimiterSizeMetric();
|
|
@@ -918,7 +928,7 @@ async function startNostrBus(options) {
|
|
|
918
928
|
abort: relayAbort.signal
|
|
919
929
|
});
|
|
920
930
|
const sendDm = async (toPubkey, text) => {
|
|
921
|
-
await sendEncryptedDm(pool, sk, toPubkey, text, relays, metrics, circuitBreakers, healthTracker, onError);
|
|
931
|
+
return await sendEncryptedDm(pool, sk, toPubkey, text, relays, metrics, circuitBreakers, healthTracker, onError);
|
|
922
932
|
};
|
|
923
933
|
const publishProfile$1 = async (profile) => {
|
|
924
934
|
const lastPublishedAt = (await readNostrProfileState({ accountId }))?.lastPublishedAt ?? void 0;
|
|
@@ -971,11 +981,14 @@ async function startNostrBus(options) {
|
|
|
971
981
|
/**
|
|
972
982
|
* Send an encrypted DM to a pubkey
|
|
973
983
|
*/
|
|
974
|
-
async function sendEncryptedDm(pool, sk, toPubkey, text, relays, metrics, circuitBreakers, healthTracker, onError) {
|
|
984
|
+
async function sendEncryptedDm(pool, sk, toPubkey, text, relays, metrics, circuitBreakers, healthTracker, onError, replyToEventId) {
|
|
985
|
+
const ciphertext = encrypt(sk, toPubkey, text);
|
|
986
|
+
const tags = [["p", toPubkey]];
|
|
987
|
+
if (replyToEventId) tags.push(["e", replyToEventId]);
|
|
975
988
|
const reply = finalizeEvent({
|
|
976
989
|
kind: 4,
|
|
977
|
-
content:
|
|
978
|
-
tags
|
|
990
|
+
content: ciphertext,
|
|
991
|
+
tags,
|
|
979
992
|
created_at: Math.floor(Date.now() / 1e3)
|
|
980
993
|
}, sk);
|
|
981
994
|
const sortedRelays = healthTracker.getSortedRelays(relays);
|
|
@@ -985,15 +998,13 @@ async function sendEncryptedDm(pool, sk, toPubkey, text, relays, metrics, circui
|
|
|
985
998
|
if (cb && !cb.canAttempt()) continue;
|
|
986
999
|
const startTime = Date.now();
|
|
987
1000
|
try {
|
|
988
|
-
|
|
989
|
-
if (publishPromises.length === 0) throw new Error(`Failed to create publish promise for relay ${relay}`);
|
|
990
|
-
await publishPromises[0];
|
|
1001
|
+
await publishNostrEventToRelay(pool, relay, reply);
|
|
991
1002
|
const latency = Date.now() - startTime;
|
|
992
1003
|
cb?.recordSuccess();
|
|
993
1004
|
healthTracker.recordSuccess(relay, latency);
|
|
994
|
-
return;
|
|
1005
|
+
return reply.id;
|
|
995
1006
|
} catch (err) {
|
|
996
|
-
lastError = err;
|
|
1007
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
997
1008
|
const latency = Date.now() - startTime;
|
|
998
1009
|
cb?.recordFailure();
|
|
999
1010
|
healthTracker.recordFailure(relay);
|
|
@@ -1109,10 +1120,9 @@ const startNostrGatewayAccount = async (ctx) => {
|
|
|
1109
1120
|
ctx.log?.warn?.(`[${account.accountId}] dropping Nostr DM after preflight drift (${senderPubkey}, ${resolvedAccess.senderAccess.reasonCode})`);
|
|
1110
1121
|
return;
|
|
1111
1122
|
}
|
|
1112
|
-
const {
|
|
1113
|
-
await
|
|
1123
|
+
const { dispatchInboundDirectDm } = await import("./inbound-direct-dm-runtime-DHn9NoYN.js");
|
|
1124
|
+
await dispatchInboundDirectDm({
|
|
1114
1125
|
cfg: ctx.cfg,
|
|
1115
|
-
runtime,
|
|
1116
1126
|
channel: "nostr",
|
|
1117
1127
|
channelLabel: "Nostr",
|
|
1118
1128
|
accountId: account.accountId,
|
|
@@ -1216,10 +1226,9 @@ const nostrOutboundAdapter = {
|
|
|
1216
1226
|
});
|
|
1217
1227
|
const message = core.channel.text.convertMarkdownTables(text ?? "", tableMode);
|
|
1218
1228
|
const normalizedTo = normalizePubkey(to);
|
|
1219
|
-
await bus.sendDm(normalizedTo, message);
|
|
1220
1229
|
return attachChannelToResult("nostr", {
|
|
1221
1230
|
to: normalizedTo,
|
|
1222
|
-
messageId:
|
|
1231
|
+
messageId: await bus.sendDm(normalizedTo, message)
|
|
1223
1232
|
});
|
|
1224
1233
|
}
|
|
1225
1234
|
};
|
|
@@ -1339,7 +1348,7 @@ const nostrPlugin = createChatChannelPlugin({
|
|
|
1339
1348
|
targetResolver: {
|
|
1340
1349
|
looksLikeId: (input) => {
|
|
1341
1350
|
const trimmed = input.trim();
|
|
1342
|
-
return trimmed.startsWith("npub1") || /^[0-9a-fA-F]{64}$/.test(trimmed);
|
|
1351
|
+
return trimmed.startsWith("npub1") || trimmed.startsWith("NPUB1") || /^[0-9a-fA-F]{64}$/.test(trimmed);
|
|
1343
1352
|
},
|
|
1344
1353
|
hint: "<npub|hex pubkey|nostr:npub...>"
|
|
1345
1354
|
},
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as nostrPlugin } from "./channel-
|
|
1
|
+
import { n as nostrPlugin } from "./channel-DgBHZ53s.js";
|
|
2
2
|
export { nostrPlugin };
|
package/dist/setup-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as nostrSetupWizard, t as nostrSetupAdapter } from "./setup-surface-
|
|
1
|
+
import { n as nostrSetupWizard, t as nostrSetupAdapter } from "./setup-surface-BF7_7BEx.js";
|
|
2
2
|
export { nostrSetupAdapter, nostrSetupWizard };
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -43,7 +43,7 @@ function resolveSetupNostrAccount(params) {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
function looksLikeNostrPrivateKey(privateKey) {
|
|
46
|
-
return privateKey.startsWith("nsec1") || /^[0-9a-fA-F]{64}$/.test(privateKey);
|
|
46
|
+
return privateKey.startsWith("nsec1") || privateKey.startsWith("NSEC1") || /^[0-9a-fA-F]{64}$/.test(privateKey);
|
|
47
47
|
}
|
|
48
48
|
const nostrSetupAdapter = createNostrSetupAdapter({
|
|
49
49
|
resolveAccountId: (cfg, accountId) => accountId?.trim() || resolveDefaultSetupNostrAccountId(cfg),
|
|
@@ -51,7 +51,7 @@ const nostrSetupAdapter = createNostrSetupAdapter({
|
|
|
51
51
|
});
|
|
52
52
|
const nostrSetupWizard = createDelegatedSetupWizardProxy({
|
|
53
53
|
channel,
|
|
54
|
-
loadWizard: async () => (await import("./setup-surface-
|
|
54
|
+
loadWizard: async () => (await import("./setup-surface-BF7_7BEx.js").then((n) => n.r)).nostrSetupWizard,
|
|
55
55
|
status: { ...createStandardChannelSetupStatus({
|
|
56
56
|
channelLabel: "Nostr",
|
|
57
57
|
configuredLabel: t("wizard.channels.statusConfigured"),
|
|
@@ -24,7 +24,7 @@ var __exportAll = (all, no_symbols) => {
|
|
|
24
24
|
*/
|
|
25
25
|
function validatePrivateKey(key) {
|
|
26
26
|
const trimmed = key.trim();
|
|
27
|
-
if (trimmed.startsWith("nsec1")) {
|
|
27
|
+
if (trimmed.startsWith("nsec1") || trimmed.startsWith("NSEC1")) {
|
|
28
28
|
const decoded = nip19.decode(trimmed);
|
|
29
29
|
if (decoded.type !== "nsec") throw new Error("Invalid nsec key: wrong type");
|
|
30
30
|
return decoded.data;
|
|
@@ -45,7 +45,7 @@ function getPublicKeyFromPrivate(privateKey) {
|
|
|
45
45
|
*/
|
|
46
46
|
function normalizePubkey(input) {
|
|
47
47
|
const trimmed = input.trim();
|
|
48
|
-
if (trimmed.startsWith("npub1")) {
|
|
48
|
+
if (trimmed.startsWith("npub1") || trimmed.startsWith("NPUB1")) {
|
|
49
49
|
const decoded = nip19.decode(trimmed);
|
|
50
50
|
if (decoded.type !== "npub" || typeof decoded.data !== "string") throw new Error("Invalid npub key");
|
|
51
51
|
return decoded.data.toLowerCase();
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/nostr",
|
|
3
|
-
"version": "2026.7.2-beta.
|
|
3
|
+
"version": "2026.7.2-beta.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@openclaw/nostr",
|
|
9
|
-
"version": "2026.7.2-beta.
|
|
9
|
+
"version": "2026.7.2-beta.3",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"nostr-tools": "2.23.9",
|
|
12
12
|
"zod": "4.4.3"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"openclaw": ">=2026.7.2-beta.
|
|
15
|
+
"openclaw": ">=2026.7.2-beta.3"
|
|
16
16
|
},
|
|
17
17
|
"peerDependenciesMeta": {
|
|
18
18
|
"openclaw": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/nostr",
|
|
3
|
-
"version": "2026.7.2-beta.
|
|
3
|
+
"version": "2026.7.2-beta.3",
|
|
4
4
|
"description": "OpenClaw Nostr channel plugin for NIP-04 encrypted direct messages.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"zod": "4.4.3"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"openclaw": ">=2026.7.2-beta.
|
|
15
|
+
"openclaw": ">=2026.7.2-beta.3"
|
|
16
16
|
},
|
|
17
17
|
"peerDependenciesMeta": {
|
|
18
18
|
"openclaw": {
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
"minHostVersion": ">=2026.4.10"
|
|
51
51
|
},
|
|
52
52
|
"compat": {
|
|
53
|
-
"pluginApi": ">=2026.7.2-beta.
|
|
53
|
+
"pluginApi": ">=2026.7.2-beta.3"
|
|
54
54
|
},
|
|
55
55
|
"build": {
|
|
56
|
-
"openclawVersion": "2026.7.2-beta.
|
|
56
|
+
"openclawVersion": "2026.7.2-beta.3"
|
|
57
57
|
},
|
|
58
58
|
"release": {
|
|
59
59
|
"publishToClawHub": true,
|