@openclaw/buzz 2026.9.1-beta.1 → 2026.9.2

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.
Files changed (63) hide show
  1. package/dist/{adapter.runtime-DA6guOQ_.js → adapter.runtime-CaDdxQ2C.js} +4 -4
  2. package/dist/api.js +2 -2
  3. package/dist/{channel-BulZqShF.js → channel-Czma0_CC.js} +200 -66
  4. package/dist/channel-plugin-api.js +1 -1
  5. package/dist/{directory-config-BesCse0q.js → directory-config-B0shiBa4.js} +1 -1
  6. package/dist/directory-contract-api.js +1 -1
  7. package/dist/{message-event-CFw7gGLi.js → message-event-X_aBiM1X.js} +5 -8
  8. package/dist/qa-runner-api.js +1 -1
  9. package/dist/{room-membership-DSAkyE0a.js → room-membership-a8IHfdgL.js} +7 -5
  10. package/dist/secret-contract-DNuqbK64.js +50 -0
  11. package/dist/secret-contract-api.js +1 -1
  12. package/dist/setup-plugin-api.js +6 -3
  13. package/dist/{setup-surface-BvQgEJ7O.js → setup-surface-DDUmAluL.js} +197 -170
  14. package/dist/types-CeupBG0P.js +160 -0
  15. package/node_modules/nostr-tools/lib/cjs/index.js +21 -5
  16. package/node_modules/nostr-tools/lib/cjs/index.js.map +2 -2
  17. package/node_modules/nostr-tools/lib/cjs/nip17.js +19 -3
  18. package/node_modules/nostr-tools/lib/cjs/nip17.js.map +2 -2
  19. package/node_modules/nostr-tools/lib/cjs/nip46.js +7 -3
  20. package/node_modules/nostr-tools/lib/cjs/nip46.js.map +2 -2
  21. package/node_modules/nostr-tools/lib/cjs/nip59.js +19 -3
  22. package/node_modules/nostr-tools/lib/cjs/nip59.js.map +2 -2
  23. package/node_modules/nostr-tools/lib/cjs/nip98.js +1 -1
  24. package/node_modules/nostr-tools/lib/cjs/nip98.js.map +2 -2
  25. package/node_modules/nostr-tools/lib/cjs/nipad.js +55 -0
  26. package/node_modules/nostr-tools/lib/cjs/nipad.js.map +7 -0
  27. package/node_modules/nostr-tools/lib/cjs/nipb7.js +1003 -98
  28. package/node_modules/nostr-tools/lib/cjs/nipb7.js.map +4 -4
  29. package/node_modules/nostr-tools/lib/cjs/relay.js +1 -1
  30. package/node_modules/nostr-tools/lib/cjs/relay.js.map +2 -2
  31. package/node_modules/nostr-tools/lib/esm/index.js +21 -5
  32. package/node_modules/nostr-tools/lib/esm/index.js.map +2 -2
  33. package/node_modules/nostr-tools/lib/esm/nip17.js +19 -3
  34. package/node_modules/nostr-tools/lib/esm/nip17.js.map +2 -2
  35. package/node_modules/nostr-tools/lib/esm/nip46.js +7 -3
  36. package/node_modules/nostr-tools/lib/esm/nip46.js.map +2 -2
  37. package/node_modules/nostr-tools/lib/esm/nip59.js +19 -3
  38. package/node_modules/nostr-tools/lib/esm/nip59.js.map +2 -2
  39. package/node_modules/nostr-tools/lib/esm/nip98.js +1 -1
  40. package/node_modules/nostr-tools/lib/esm/nip98.js.map +2 -2
  41. package/node_modules/nostr-tools/lib/esm/nipad.js +34 -0
  42. package/node_modules/nostr-tools/lib/esm/nipad.js.map +7 -0
  43. package/node_modules/nostr-tools/lib/esm/nipb7.js +1009 -98
  44. package/node_modules/nostr-tools/lib/esm/nipb7.js.map +4 -4
  45. package/node_modules/nostr-tools/lib/esm/relay.js +1 -1
  46. package/node_modules/nostr-tools/lib/esm/relay.js.map +2 -2
  47. package/node_modules/nostr-tools/lib/nostr.bundle.js +21 -5
  48. package/node_modules/nostr-tools/lib/nostr.bundle.js.map +2 -2
  49. package/node_modules/nostr-tools/lib/types/nip98.d.ts +1 -1
  50. package/node_modules/nostr-tools/lib/types/nipad.d.ts +16 -0
  51. package/node_modules/nostr-tools/lib/types/nipb7.d.ts +112 -5
  52. package/node_modules/nostr-tools/lib/types/relay.d.ts +1 -1
  53. package/node_modules/nostr-tools/package.json +7 -7
  54. package/openclaw.plugin.json +346 -0
  55. package/package.json +8 -5
  56. package/dist/secret-contract-D19RiJv_.js +0 -12
  57. package/dist/types-BN_HOsnq.js +0 -101
  58. package/node_modules/nostr-tools/lib/cjs/nipb0.js +0 -1087
  59. package/node_modules/nostr-tools/lib/cjs/nipb0.js.map +0 -7
  60. package/node_modules/nostr-tools/lib/esm/nipb0.js +0 -1072
  61. package/node_modules/nostr-tools/lib/esm/nipb0.js.map +0 -7
  62. package/node_modules/nostr-tools/lib/types/nipb0.d.ts +0 -128
  63. /package/node_modules/nostr-tools/lib/types/{nipb0.test.d.ts → nip46.test.d.ts} +0 -0
@@ -0,0 +1,160 @@
1
+ import { createAccountListHelpers, mergeAccountConfig } from "openclaw/plugin-sdk/account-helpers";
2
+ import { GroupPolicySchema, MarkdownConfigSchema, buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
3
+ import { buildSecretInputSchema, resolveSecretInputString } from "openclaw/plugin-sdk/secret-input";
4
+ import { z } from "zod";
5
+ import { getPublicKey, nip19 } from "nostr-tools";
6
+ import { DEFAULT_ACCOUNT_ID, normalizeAccountId, normalizeOptionalAccountId } from "openclaw/plugin-sdk/account-id";
7
+ import { assertSecretOwnerAvailable } from "openclaw/plugin-sdk/channel-secret-owner-runtime";
8
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
+ //#region extensions/buzz/src/target.ts
10
+ const BUZZ_CHANNEL_ID_PATTERN = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89aAbB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/u;
11
+ function normalizeBuzzTarget(target) {
12
+ return target.trim().replace(/^buzz:/iu, "").replace(/^channel:/iu, "");
13
+ }
14
+ function parseBuzzTarget(target) {
15
+ const channelId = normalizeBuzzTarget(target);
16
+ if (!BUZZ_CHANNEL_ID_PATTERN.test(channelId)) throw new Error("Buzz target must be a channel UUID");
17
+ return channelId.toLowerCase();
18
+ }
19
+ function isConfiguredBuzzChannel(configuredChannelIds, channelId) {
20
+ try {
21
+ return configuredChannelIds.has(parseBuzzTarget(channelId));
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+ function buildBuzzTarget(channelId) {
27
+ return `buzz:${parseBuzzTarget(channelId)}`;
28
+ }
29
+ function looksLikeBuzzTarget(target) {
30
+ try {
31
+ parseBuzzTarget(target);
32
+ return true;
33
+ } catch {
34
+ return false;
35
+ }
36
+ }
37
+ //#endregion
38
+ //#region extensions/buzz/src/config-schema.ts
39
+ const BuzzGroupConfigSchema = z.object({
40
+ enabled: z.boolean().optional(),
41
+ requireMention: z.boolean().optional(),
42
+ groupPolicy: GroupPolicySchema.optional(),
43
+ groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional()
44
+ }).strict();
45
+ const BuzzAccountIdSchema = z.string().regex(/^(?!(?:constructor|prototype)$)[a-z0-9][a-z0-9_-]{0,63}$/u, "Buzz account IDs must be canonical lowercase account keys");
46
+ const BuzzAccountConfigSchema = z.object({
47
+ name: z.string().optional(),
48
+ enabled: z.boolean().optional(),
49
+ configWrites: z.boolean().optional(),
50
+ responsePrefix: z.string().optional(),
51
+ replyToMode: z.enum(["off", "all"]).optional(),
52
+ markdown: MarkdownConfigSchema,
53
+ relayUrl: z.string().url().and(z.string().regex(/^[wW][sS][sS]?:\/\//, "Buzz relay URL must use ws:// or wss://")).optional(),
54
+ privateKey: buildSecretInputSchema().optional(),
55
+ authTag: buildSecretInputSchema().optional(),
56
+ groupPolicy: GroupPolicySchema.optional(),
57
+ groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
58
+ groups: z.record(z.string().regex(BUZZ_CHANNEL_ID_PATTERN, "Buzz group key must be a channel UUID"), BuzzGroupConfigSchema).optional(),
59
+ historyLimit: z.number().int().min(0).max(20).optional(),
60
+ defaultTo: z.string().optional()
61
+ }).strict();
62
+ const RawBuzzConfigSchema = BuzzAccountConfigSchema.extend({
63
+ groupPolicy: GroupPolicySchema.optional().default("allowlist"),
64
+ accounts: z.record(BuzzAccountIdSchema, BuzzAccountConfigSchema).optional(),
65
+ defaultAccount: BuzzAccountIdSchema.optional()
66
+ });
67
+ const BuzzConfigSchema = buildChannelConfigSchema(RawBuzzConfigSchema);
68
+ //#endregion
69
+ //#region extensions/buzz/src/types.ts
70
+ function resolveChannelConfig(cfg) {
71
+ return cfg.channels?.buzz;
72
+ }
73
+ const { listAccountIds: listBuzzAccountIds, resolveDefaultAccountId: resolveDefaultBuzzAccountId } = createAccountListHelpers("buzz", {
74
+ normalizeAccountId,
75
+ fallbackAccountIdWhenEmpty: false,
76
+ implicitDefaultAccount: {
77
+ channelKeys: ["relayUrl", "privateKey"],
78
+ envVars: ["BUZZ_RELAY_URL", "BUZZ_PRIVATE_KEY"]
79
+ }
80
+ });
81
+ function resolveBuzzAccountConfig(params) {
82
+ const requestedId = params.accountId?.trim();
83
+ const accountId = requestedId ? normalizeOptionalAccountId(requestedId) : resolveDefaultBuzzAccountId(params.cfg);
84
+ if (!accountId || !BuzzAccountIdSchema.safeParse(accountId).success) throw new Error("Buzz account ID must be a valid account key");
85
+ const root = resolveChannelConfig(params.cfg) ?? {};
86
+ const allowEnv = accountId === DEFAULT_ACCOUNT_ID && !Object.hasOwn(root.accounts ?? {}, accountId);
87
+ const account = allowEnv ? void 0 : root.accounts?.[accountId];
88
+ const merged = mergeAccountConfig({
89
+ channelConfig: root,
90
+ accountConfig: account,
91
+ omitKeys: ["defaultAccount", ...allowEnv ? [] : [
92
+ "name",
93
+ "relayUrl",
94
+ "privateKey",
95
+ "authTag",
96
+ "groups",
97
+ "defaultTo"
98
+ ]]
99
+ });
100
+ return {
101
+ accountId,
102
+ allowEnv,
103
+ configPath: allowEnv ? "channels.buzz" : `channels.buzz.accounts.${accountId}`,
104
+ config: {
105
+ ...merged,
106
+ groupPolicy: merged.groupPolicy ?? "allowlist",
107
+ enabled: root.enabled !== false && account?.enabled !== false,
108
+ groups: normalizeBuzzGroups(merged.groups)
109
+ }
110
+ };
111
+ }
112
+ function normalizeBuzzGroups(groups) {
113
+ if (!groups) return;
114
+ return Object.fromEntries(Object.entries(groups).map(([channelId, group]) => [parseBuzzTarget(channelId), group]));
115
+ }
116
+ function decodeBuzzPrivateKey(value) {
117
+ const trimmed = value.trim();
118
+ if (/^[0-9a-f]{64}$/iu.test(trimmed)) return Uint8Array.from(Buffer.from(trimmed, "hex"));
119
+ const decoded = nip19.decode(trimmed);
120
+ if (decoded.type !== "nsec") throw new Error("Buzz private key must be nsec or 64-character hex");
121
+ return decoded.data;
122
+ }
123
+ function resolveBuzzPublicKey(privateKey) {
124
+ return getPublicKey(decodeBuzzPrivateKey(privateKey));
125
+ }
126
+ function resolveBuzzAccount(params) {
127
+ const { accountId, config, configPath, allowEnv } = resolveBuzzAccountConfig(params);
128
+ const relayUrl = config.relayUrl?.trim() || (allowEnv ? process.env.BUZZ_RELAY_URL?.trim() : "") || "";
129
+ const resolveCredential = (field) => resolveSecretInputString({
130
+ value: config[field],
131
+ path: `${configPath}.${field}`,
132
+ mode: "inspect"
133
+ });
134
+ const privateKeyResolution = resolveCredential("privateKey");
135
+ const authTagResolution = resolveCredential("authTag");
136
+ const privateKey = privateKeyResolution.value ?? (allowEnv && privateKeyResolution.status === "missing" ? process.env.BUZZ_PRIVATE_KEY?.trim() || "" : "");
137
+ const authTag = authTagResolution.value ?? (allowEnv && authTagResolution.status === "missing" ? process.env.BUZZ_AUTH_TAG?.trim() || "" : "");
138
+ let publicKey = "";
139
+ if (privateKey) try {
140
+ publicKey = resolveBuzzPublicKey(privateKey);
141
+ } catch {}
142
+ return {
143
+ accountId,
144
+ name: normalizeOptionalString(config.name) ?? "OpenClaw",
145
+ enabled: config.enabled !== false,
146
+ configured: Boolean(relayUrl && (privateKey || privateKeyResolution.ref)),
147
+ relayUrl,
148
+ privateKey,
149
+ authTag,
150
+ publicKey,
151
+ tokenStatus: privateKeyResolution.ref || authTagResolution.ref ? "configured_unavailable" : privateKey ? "available" : "missing",
152
+ config
153
+ };
154
+ }
155
+ function assertBuzzAccountAvailable(account) {
156
+ assertSecretOwnerAvailable("account", `buzz:${account.accountId}`);
157
+ if (account.tokenStatus === "configured_unavailable") throw new Error(`Buzz credentials for account "${account.accountId}" are configured but unavailable.`);
158
+ }
159
+ //#endregion
160
+ export { resolveBuzzAccountConfig as a, BuzzConfigSchema as c, isConfiguredBuzzChannel as d, looksLikeBuzzTarget as f, resolveBuzzAccount as i, BUZZ_CHANNEL_ID_PATTERN as l, parseBuzzTarget as m, decodeBuzzPrivateKey as n, resolveBuzzPublicKey as o, normalizeBuzzTarget as p, listBuzzAccountIds as r, resolveDefaultBuzzAccountId as s, assertBuzzAccountAvailable as t, buildBuzzTarget as u };
@@ -1408,7 +1408,7 @@ var Relay = class extends AbstractRelay {
1408
1408
  }
1409
1409
  static async connect(url, options) {
1410
1410
  const relay = new Relay(url, options);
1411
- await relay.connect();
1411
+ await relay.connect(options);
1412
1412
  return relay;
1413
1413
  }
1414
1414
  };
@@ -2589,13 +2589,29 @@ function wrapManyEvents(event, senderPrivateKey, recipientsPublicKeys) {
2589
2589
  return wrappeds;
2590
2590
  }
2591
2591
  function unwrapEvent(wrap, recipientPrivateKey) {
2592
- const unwrappedSeal = nip44Decrypt(wrap, recipientPrivateKey);
2593
- return nip44Decrypt(unwrappedSeal, recipientPrivateKey);
2592
+ if (wrap.kind !== GiftWrap) {
2593
+ throw new Error(`unexpected wrap kind ${wrap.kind}, expected ${GiftWrap}`);
2594
+ }
2595
+ const seal = nip44Decrypt(wrap, recipientPrivateKey);
2596
+ if (seal.kind !== Seal) {
2597
+ throw new Error(`unexpected seal kind ${seal.kind}, expected ${Seal}`);
2598
+ }
2599
+ if (!verifyEvent(seal)) {
2600
+ throw new Error("seal signature is invalid");
2601
+ }
2602
+ const rumor = nip44Decrypt(seal, recipientPrivateKey);
2603
+ if (rumor.pubkey !== seal.pubkey) {
2604
+ throw new Error(`rumor pubkey ${rumor.pubkey} does not match seal pubkey ${seal.pubkey}`);
2605
+ }
2606
+ return rumor;
2594
2607
  }
2595
2608
  function unwrapManyEvents(wrappedEvents, recipientPrivateKey) {
2596
2609
  let unwrappedEvents = [];
2597
2610
  wrappedEvents.forEach((e) => {
2598
- unwrappedEvents.push(unwrapEvent(e, recipientPrivateKey));
2611
+ try {
2612
+ unwrappedEvents.push(unwrapEvent(e, recipientPrivateKey));
2613
+ } catch (_err) {
2614
+ }
2599
2615
  });
2600
2616
  unwrappedEvents.sort((a, b) => a.created_at - b.created_at);
2601
2617
  return unwrappedEvents;
@@ -3987,7 +4003,7 @@ function validateEventTimestamp(event) {
3987
4003
  if (!event.created_at) {
3988
4004
  return false;
3989
4005
  }
3990
- return Math.round(new Date().getTime() / 1e3) - event.created_at < 60;
4006
+ return Math.abs(Math.round(new Date().getTime() / 1e3) - event.created_at) < 60;
3991
4007
  }
3992
4008
  function validateEventKind(event) {
3993
4009
  return event.kind === HTTPAuth;