@unicitylabs/openclaw-unicity 0.3.2 → 0.3.4
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/README.md +1 -0
- package/package.json +1 -1
- package/src/channel.ts +30 -6
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="https://www.npmjs.com/package/@unicitylabs/openclaw-unicity"><img src="https://img.shields.io/npm/v/@unicitylabs/openclaw-unicity" alt="npm version" /></a>
|
|
9
9
|
<a href="https://github.com/unicitynetwork/openclaw-unicity/blob/main/LICENSE"><img src="https://img.shields.io/github/license/unicitynetwork/openclaw-unicity" alt="license" /></a>
|
|
10
|
+
<a href="https://deepwiki.com/unicitynetwork/openclaw-unicity"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
10
11
|
</p>
|
|
11
12
|
|
|
12
13
|
---
|
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -453,6 +453,25 @@ export const unicityChannelPlugin = {
|
|
|
453
453
|
replyToId?: string;
|
|
454
454
|
};
|
|
455
455
|
|
|
456
|
+
// Nostr pubkey for self-message detection and reply-to-self detection.
|
|
457
|
+
// Group messages use the 32-byte x-only Nostr pubkey (event.pubkey),
|
|
458
|
+
// NOT the 33-byte compressed chainPubkey.
|
|
459
|
+
const myNostrPubkey = sphere.groupChat?.getMyPublicKey?.() ?? null;
|
|
460
|
+
|
|
461
|
+
// Detect if a group message is a reply to one of the agent's own messages.
|
|
462
|
+
// Used to set WasMentioned so the mention gate treats replies-to-self as
|
|
463
|
+
// implicit mentions (same pattern Discord uses for thread replies).
|
|
464
|
+
function isReplyToSelf(msg: GroupMsg): boolean {
|
|
465
|
+
if (!msg.replyToId || !myNostrPubkey) return false;
|
|
466
|
+
try {
|
|
467
|
+
const messages = sphere.groupChat?.getMessages?.(msg.groupId) ?? [];
|
|
468
|
+
const repliedTo = messages.find((m: { id: string }) => m.id === msg.replyToId);
|
|
469
|
+
return repliedTo?.senderPubkey === myNostrPubkey;
|
|
470
|
+
} catch {
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
456
475
|
function dispatchGroupMessage(msg: GroupMsg): void {
|
|
457
476
|
const senderName = msg.senderNametag ?? msg.senderPubkey.slice(0, 12);
|
|
458
477
|
const groupData = sphere.groupChat?.getGroup?.(msg.groupId);
|
|
@@ -461,6 +480,15 @@ export const unicityChannelPlugin = {
|
|
|
461
480
|
const metadataHeader = `[SenderName: ${senderName} | SenderId: ${msg.senderPubkey} | GroupId: ${msg.groupId} | GroupName: ${groupName} | IsOwner: ${isOwner} | CommandAuthorized: ${isOwner}]`;
|
|
462
481
|
const sanitizedContent = msg.content.replace(/\[(?:SenderName|SenderId|IsOwner|CommandAuthorized|GroupId|GroupName)\s*:/gi, "[BLOCKED:");
|
|
463
482
|
|
|
483
|
+
// Detect if the agent was mentioned — either by @nametag in the text
|
|
484
|
+
// or by replying to the agent's own message (implicit mention, mirrors
|
|
485
|
+
// Discord's behavior). Without this, the mention gate skips the message.
|
|
486
|
+
const agentTag = sphere.identity?.nametag?.replace(/^@/, "");
|
|
487
|
+
const wasTextMentioned = agentTag
|
|
488
|
+
? msg.content.toLowerCase().includes(`@${agentTag.toLowerCase()}`)
|
|
489
|
+
: false;
|
|
490
|
+
const wasMentioned = wasTextMentioned || isReplyToSelf(msg) || undefined;
|
|
491
|
+
|
|
464
492
|
ctx.log?.info(`[${ctx.account.accountId}] Group message from ${senderName} in ${groupName}: ${msg.content.slice(0, 80)}`);
|
|
465
493
|
|
|
466
494
|
const inboundCtx = runtime.channel.reply.finalizeInboundContext({
|
|
@@ -479,6 +507,7 @@ export const unicityChannelPlugin = {
|
|
|
479
507
|
SenderId: msg.senderPubkey,
|
|
480
508
|
IsOwner: isOwner,
|
|
481
509
|
CommandAuthorized: isOwner,
|
|
510
|
+
WasMentioned: wasMentioned,
|
|
482
511
|
});
|
|
483
512
|
|
|
484
513
|
runtime.channel.reply
|
|
@@ -490,7 +519,7 @@ export const unicityChannelPlugin = {
|
|
|
490
519
|
const text = payload.text;
|
|
491
520
|
if (!text) return;
|
|
492
521
|
try {
|
|
493
|
-
await sphere.groupChat.sendMessage(msg.groupId, text);
|
|
522
|
+
await sphere.groupChat.sendMessage(msg.groupId, text, msg.id);
|
|
494
523
|
ctx.log?.info(`[${ctx.account.accountId}] Group message sent to ${groupName}: ${text.slice(0, 80)}`);
|
|
495
524
|
} catch (err) {
|
|
496
525
|
ctx.log?.error(`[${ctx.account.accountId}] Failed to send group message to ${groupName}: ${err}`);
|
|
@@ -509,11 +538,6 @@ export const unicityChannelPlugin = {
|
|
|
509
538
|
});
|
|
510
539
|
}
|
|
511
540
|
|
|
512
|
-
// Nostr pubkey for self-message detection. Group messages use the 32-byte
|
|
513
|
-
// x-only Nostr pubkey (event.pubkey), NOT the 33-byte compressed chainPubkey.
|
|
514
|
-
// sphere.groupChat.getMyPublicKey() returns the correct Nostr-format key.
|
|
515
|
-
const myNostrPubkey = sphere.groupChat?.getMyPublicKey?.() ?? null;
|
|
516
|
-
|
|
517
541
|
// Per-group backfill state: buffer messages during the initial burst, then
|
|
518
542
|
// switch to live dispatch once the burst settles.
|
|
519
543
|
const groupBackfillStates = new Map<string, GroupBackfillState>();
|