@unicitylabs/openclaw-unicity 0.5.1 → 0.5.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/package.json +1 -1
- package/src/channel.ts +34 -5
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -242,7 +242,41 @@ export const unicityChannelPlugin = {
|
|
|
242
242
|
|
|
243
243
|
ctx.log?.info(`[${ctx.account.accountId}] Subscribing to DMs (pubkey: ${sphere.identity?.chainPubkey?.slice(0, 16)}...)`);
|
|
244
244
|
|
|
245
|
+
// Track DM start time and seen IDs to skip historical replays from the relay.
|
|
246
|
+
// The SDK fires onDirectMessage for every cached/replayed DM on connect.
|
|
247
|
+
const dmStartTime = Math.floor(Date.now() / 1000);
|
|
248
|
+
const seenDmIds = new Set<string>();
|
|
249
|
+
const DM_SEEN_MAX = 1000;
|
|
250
|
+
|
|
251
|
+
// Collect all known representations of "self" so we can detect echoed-back
|
|
252
|
+
// messages. The SDK's built-in self-check compares transport pubkey against
|
|
253
|
+
// chainPubkey, but those may differ in format (33-byte compressed vs 32-byte
|
|
254
|
+
// x-only Nostr key), letting self-messages slip through.
|
|
255
|
+
const selfPubkeys = new Set<string>();
|
|
256
|
+
if (sphere.identity?.chainPubkey) selfPubkeys.add(sphere.identity.chainPubkey);
|
|
257
|
+
const myNostrPubkey = sphere.groupChat?.getMyPublicKey?.() ?? null;
|
|
258
|
+
if (myNostrPubkey) selfPubkeys.add(myNostrPubkey);
|
|
259
|
+
|
|
245
260
|
const unsub = sphere.communications.onDirectMessage((msg) => {
|
|
261
|
+
// Skip messages from self (own DMs echoed back by the relay)
|
|
262
|
+
if (selfPubkeys.has(msg.senderPubkey)) return;
|
|
263
|
+
|
|
264
|
+
// Deduplicate: skip already-processed messages (relays may deliver dupes)
|
|
265
|
+
if (msg.id && seenDmIds.has(msg.id)) return;
|
|
266
|
+
if (msg.id) {
|
|
267
|
+
seenDmIds.add(msg.id);
|
|
268
|
+
if (seenDmIds.size > DM_SEEN_MAX) {
|
|
269
|
+
const first = seenDmIds.values().next().value!;
|
|
270
|
+
seenDmIds.delete(first);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Skip historical messages replayed on connect
|
|
275
|
+
if (msg.timestamp && msg.timestamp < dmStartTime) {
|
|
276
|
+
ctx.log?.debug(`[${ctx.account.accountId}] Skipping historical DM (ts=${msg.timestamp} < start=${dmStartTime})`);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
246
280
|
// Immediately signal that we're composing a reply
|
|
247
281
|
sphere.communications.sendComposingIndicator(msg.senderPubkey)
|
|
248
282
|
.catch((err: unknown) => ctx.log?.error(`[${ctx.account.accountId}] Composing indicator failed: ${err}`));
|
|
@@ -457,11 +491,6 @@ export const unicityChannelPlugin = {
|
|
|
457
491
|
replyToId?: string;
|
|
458
492
|
};
|
|
459
493
|
|
|
460
|
-
// Nostr pubkey for self-message detection and reply-to-self detection.
|
|
461
|
-
// Group messages use the 32-byte x-only Nostr pubkey (event.pubkey),
|
|
462
|
-
// NOT the 33-byte compressed chainPubkey.
|
|
463
|
-
const myNostrPubkey = sphere.groupChat?.getMyPublicKey?.() ?? null;
|
|
464
|
-
|
|
465
494
|
// Detect if a group message is a reply to one of the agent's own messages.
|
|
466
495
|
// Used to set WasMentioned so the mention gate treats replies-to-self as
|
|
467
496
|
// implicit mentions (same pattern Discord uses for thread replies).
|