@openclaw/nostr 2026.5.7-beta.1 → 2026.5.9-beta.1

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 CHANGED
@@ -1,9 +1,10 @@
1
1
  import { o as resolveNostrAccount } from "./setup-surface-DxAaUTyC.js";
2
2
  import { getPluginRuntimeGatewayRequestScope } from "./runtime-api.js";
3
3
  import { n as NostrProfileSchema } from "./config-schema-DIk4jlBg.js";
4
- import { a as setNostrRuntime, i as getNostrRuntime, n as nostrPlugin, o as contentToProfile, r as publishNostrProfile, t as getNostrProfileState } from "./channel-DfEqBtUh.js";
4
+ import { a as setNostrRuntime, i as getNostrRuntime, n as nostrPlugin, o as contentToProfile, r as publishNostrProfile, t as getNostrProfileState } from "./channel-C6LnxRyg.js";
5
5
  import { z } from "openclaw/plugin-sdk/zod";
6
6
  import { SimplePool, verifyEvent } from "nostr-tools";
7
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, readStringValue } from "openclaw/plugin-sdk/text-runtime";
7
8
  import { readJsonBodyWithLimit, requestBodyErrorToText } from "openclaw/plugin-sdk/webhook-request-guards";
8
9
  import { createFixedWindowRateLimiter } from "openclaw/plugin-sdk/webhook-ingress";
9
10
  import { isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
@@ -178,17 +179,6 @@ function mergeProfiles(local, imported) {
178
179
  }
179
180
  //#endregion
180
181
  //#region extensions/nostr/src/nostr-profile-http.ts
181
- function readStringValue(value) {
182
- return typeof value === "string" ? value : void 0;
183
- }
184
- function normalizeOptionalLowercaseString(value) {
185
- if (typeof value !== "string") return;
186
- const trimmed = value.trim();
187
- return trimmed ? trimmed.toLowerCase() : void 0;
188
- }
189
- function normalizeLowercaseStringOrEmpty(value) {
190
- return normalizeOptionalLowercaseString(value) ?? "";
191
- }
192
182
  const profileRateLimiter = createFixedWindowRateLimiter({
193
183
  windowMs: 6e4,
194
184
  maxRequests: 5,
@@ -4,19 +4,19 @@ import { t as DEFAULT_RELAYS } from "./default-relays-DLwdWOTu.js";
4
4
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
5
5
  import { createScopedDmSecurityResolver, createTopLevelChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
6
6
  import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
7
+ import { createChannelMessageAdapterFromOutbound } from "openclaw/plugin-sdk/channel-message";
7
8
  import { buildPassiveChannelStatusSummary, buildTrafficStatusSummary, safeParseJsonWithSchema } from "openclaw/plugin-sdk/extension-shared";
8
9
  import { createComputedAccountStatusAdapter } from "openclaw/plugin-sdk/status-helpers";
10
+ import { z } from "openclaw/plugin-sdk/zod";
9
11
  import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
10
12
  import { attachChannelToResult } from "openclaw/plugin-sdk/channel-send-result";
11
13
  import { SimplePool, finalizeEvent, getPublicKey, verifyEvent } from "nostr-tools";
12
14
  import { decrypt, encrypt } from "nostr-tools/nip04";
13
15
  import { createDirectDmPreCryptoGuardPolicy } from "openclaw/plugin-sdk/direct-dm-guard-policy";
14
16
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
15
- import crypto from "node:crypto";
16
- import fs from "node:fs/promises";
17
17
  import os from "node:os";
18
18
  import path from "node:path";
19
- import { z } from "zod";
19
+ import { privateFileStore } from "openclaw/plugin-sdk/security-runtime";
20
20
  import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
21
21
  import { buildChannelOutboundSessionRoute, stripChannelTargetPrefix } from "openclaw/plugin-sdk/core";
22
22
  //#region extensions/nostr/src/metrics.ts
@@ -460,29 +460,22 @@ function safeParseState(raw) {
460
460
  async function readNostrBusState(params) {
461
461
  const filePath = resolveNostrStatePath(params.accountId, params.env);
462
462
  try {
463
- return safeParseState(await fs.readFile(filePath, "utf-8"));
464
- } catch (err) {
465
- if (err.code === "ENOENT") return null;
463
+ const raw = await privateFileStore(path.dirname(filePath)).readTextIfExists(path.basename(filePath));
464
+ if (raw === null) return null;
465
+ return safeParseState(raw);
466
+ } catch {
466
467
  return null;
467
468
  }
468
469
  }
469
470
  async function writeNostrBusState(params) {
470
471
  const filePath = resolveNostrStatePath(params.accountId, params.env);
471
- const dir = path.dirname(filePath);
472
- await fs.mkdir(dir, {
473
- recursive: true,
474
- mode: 448
475
- });
476
- const tmp = path.join(dir, `${path.basename(filePath)}.${crypto.randomUUID()}.tmp`);
477
472
  const payload = {
478
473
  version: STORE_VERSION,
479
474
  lastProcessedAt: params.lastProcessedAt,
480
475
  gatewayStartedAt: params.gatewayStartedAt,
481
476
  recentEventIds: (params.recentEventIds ?? []).filter((x) => typeof x === "string")
482
477
  };
483
- await fs.writeFile(tmp, `${JSON.stringify(payload, null, 2)}\n`, { encoding: "utf-8" });
484
- await fs.chmod(tmp, 384);
485
- await fs.rename(tmp, filePath);
478
+ await privateFileStore(path.dirname(filePath)).writeJson(path.basename(filePath), payload, { trailingNewline: true });
486
479
  }
487
480
  /**
488
481
  * Determine the `since` timestamp for subscription.
@@ -501,29 +494,22 @@ function safeParseProfileState(raw) {
501
494
  async function readNostrProfileState(params) {
502
495
  const filePath = resolveNostrProfileStatePath(params.accountId, params.env);
503
496
  try {
504
- return safeParseProfileState(await fs.readFile(filePath, "utf-8"));
505
- } catch (err) {
506
- if (err.code === "ENOENT") return null;
497
+ const raw = await privateFileStore(path.dirname(filePath)).readTextIfExists(path.basename(filePath));
498
+ if (raw === null) return null;
499
+ return safeParseProfileState(raw);
500
+ } catch {
507
501
  return null;
508
502
  }
509
503
  }
510
504
  async function writeNostrProfileState(params) {
511
505
  const filePath = resolveNostrProfileStatePath(params.accountId, params.env);
512
- const dir = path.dirname(filePath);
513
- await fs.mkdir(dir, {
514
- recursive: true,
515
- mode: 448
516
- });
517
- const tmp = path.join(dir, `${path.basename(filePath)}.${crypto.randomUUID()}.tmp`);
518
506
  const payload = {
519
507
  version: PROFILE_STATE_VERSION,
520
508
  lastPublishedAt: params.lastPublishedAt,
521
509
  lastPublishedEventId: params.lastPublishedEventId,
522
510
  lastPublishResults: params.lastPublishResults
523
511
  };
524
- await fs.writeFile(tmp, `${JSON.stringify(payload, null, 2)}\n`, { encoding: "utf-8" });
525
- await fs.chmod(tmp, 384);
526
- await fs.rename(tmp, filePath);
512
+ await privateFileStore(path.dirname(filePath)).writeJson(path.basename(filePath), payload, { trailingNewline: true });
527
513
  }
528
514
  //#endregion
529
515
  //#region extensions/nostr/src/seen-tracker.ts
@@ -1287,6 +1273,10 @@ const nostrPairingTextAdapter = {
1287
1273
  const nostrOutboundAdapter = {
1288
1274
  deliveryMode: "direct",
1289
1275
  textChunkLimit: 4e3,
1276
+ deliveryCapabilities: { durableFinal: {
1277
+ text: true,
1278
+ messageSendingHooks: true
1279
+ } },
1290
1280
  sendText: async ({ cfg, to, text, accountId }) => {
1291
1281
  const core = getNostrRuntime();
1292
1282
  const aid = accountId ?? resolveDefaultNostrAccountId(cfg);
@@ -1370,6 +1360,10 @@ const nostrConfigAdapter = createTopLevelChannelConfigAdapter({
1370
1360
  }
1371
1361
  }).filter(Boolean)
1372
1362
  });
1363
+ const nostrMessageAdapter = createChannelMessageAdapterFromOutbound({
1364
+ id: "nostr",
1365
+ outbound: nostrOutboundAdapter
1366
+ });
1373
1367
  const nostrPlugin = createChatChannelPlugin({
1374
1368
  base: {
1375
1369
  id: "nostr",
@@ -1418,6 +1412,7 @@ const nostrPlugin = createChatChannelPlugin({
1418
1412
  },
1419
1413
  resolveOutboundSessionRoute: (params) => resolveNostrOutboundSessionRoute(params)
1420
1414
  },
1415
+ message: nostrMessageAdapter,
1421
1416
  status: { ...createComputedAccountStatusAdapter({
1422
1417
  defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID),
1423
1418
  collectStatusIssues: (accounts) => collectStatusIssuesFromLastError("nostr", accounts),
@@ -1,2 +1,2 @@
1
- import { n as nostrPlugin } from "./channel-DfEqBtUh.js";
1
+ import { n as nostrPlugin } from "./channel-C6LnxRyg.js";
2
2
  export { nostrPlugin };
package/dist/test-api.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as nostrPlugin } from "./channel-DfEqBtUh.js";
1
+ import { n as nostrPlugin } from "./channel-C6LnxRyg.js";
2
2
  export { nostrPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/nostr",
3
- "version": "2026.5.7-beta.1",
3
+ "version": "2026.5.9-beta.1",
4
4
  "description": "OpenClaw Nostr channel plugin for NIP-04 encrypted DMs",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,15 +8,14 @@
8
8
  },
9
9
  "type": "module",
10
10
  "dependencies": {
11
- "nostr-tools": "^2.23.3",
12
- "zod": "^4.4.3"
11
+ "nostr-tools": "^2.23.3"
13
12
  },
14
13
  "devDependencies": {
15
14
  "@openclaw/plugin-sdk": "workspace:*",
16
15
  "openclaw": "workspace:*"
17
16
  },
18
17
  "peerDependencies": {
19
- "openclaw": ">=2026.5.7-beta.1"
18
+ "openclaw": ">=2026.5.9-beta.1"
20
19
  },
21
20
  "peerDependenciesMeta": {
22
21
  "openclaw": {
@@ -54,10 +53,10 @@
54
53
  "minHostVersion": ">=2026.4.10"
55
54
  },
56
55
  "compat": {
57
- "pluginApi": ">=2026.5.7-beta.1"
56
+ "pluginApi": ">=2026.5.9-beta.1"
58
57
  },
59
58
  "build": {
60
- "openclawVersion": "2026.5.7-beta.1"
59
+ "openclawVersion": "2026.5.9-beta.1"
61
60
  },
62
61
  "release": {
63
62
  "publishToClawHub": true,