@unicitylabs/openclaw-unicity 0.3.1 → 0.3.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 +29 -3
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -13,6 +13,7 @@ const DEFAULT_ACCOUNT_ID = "default";
|
|
|
13
13
|
/** How long (ms) to wait after the last group message before declaring backfill complete. */
|
|
14
14
|
export const GROUP_BACKFILL_DEBOUNCE_MS = 3_000;
|
|
15
15
|
|
|
16
|
+
|
|
16
17
|
interface GroupBackfillState {
|
|
17
18
|
phase: "buffering" | "live";
|
|
18
19
|
latestMsg: {
|
|
@@ -452,6 +453,25 @@ export const unicityChannelPlugin = {
|
|
|
452
453
|
replyToId?: string;
|
|
453
454
|
};
|
|
454
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
|
+
|
|
455
475
|
function dispatchGroupMessage(msg: GroupMsg): void {
|
|
456
476
|
const senderName = msg.senderNametag ?? msg.senderPubkey.slice(0, 12);
|
|
457
477
|
const groupData = sphere.groupChat?.getGroup?.(msg.groupId);
|
|
@@ -460,6 +480,10 @@ export const unicityChannelPlugin = {
|
|
|
460
480
|
const metadataHeader = `[SenderName: ${senderName} | SenderId: ${msg.senderPubkey} | GroupId: ${msg.groupId} | GroupName: ${groupName} | IsOwner: ${isOwner} | CommandAuthorized: ${isOwner}]`;
|
|
461
481
|
const sanitizedContent = msg.content.replace(/\[(?:SenderName|SenderId|IsOwner|CommandAuthorized|GroupId|GroupName)\s*:/gi, "[BLOCKED:");
|
|
462
482
|
|
|
483
|
+
// Treat replies to the agent's own messages as implicit mentions,
|
|
484
|
+
// so the mention gate doesn't skip them (mirrors Discord's behavior).
|
|
485
|
+
const wasMentioned = isReplyToSelf(msg) || undefined;
|
|
486
|
+
|
|
463
487
|
ctx.log?.info(`[${ctx.account.accountId}] Group message from ${senderName} in ${groupName}: ${msg.content.slice(0, 80)}`);
|
|
464
488
|
|
|
465
489
|
const inboundCtx = runtime.channel.reply.finalizeInboundContext({
|
|
@@ -478,6 +502,7 @@ export const unicityChannelPlugin = {
|
|
|
478
502
|
SenderId: msg.senderPubkey,
|
|
479
503
|
IsOwner: isOwner,
|
|
480
504
|
CommandAuthorized: isOwner,
|
|
505
|
+
WasMentioned: wasMentioned,
|
|
481
506
|
});
|
|
482
507
|
|
|
483
508
|
runtime.channel.reply
|
|
@@ -489,7 +514,7 @@ export const unicityChannelPlugin = {
|
|
|
489
514
|
const text = payload.text;
|
|
490
515
|
if (!text) return;
|
|
491
516
|
try {
|
|
492
|
-
await sphere.groupChat.sendMessage(msg.groupId, text);
|
|
517
|
+
await sphere.groupChat.sendMessage(msg.groupId, text, msg.id);
|
|
493
518
|
ctx.log?.info(`[${ctx.account.accountId}] Group message sent to ${groupName}: ${text.slice(0, 80)}`);
|
|
494
519
|
} catch (err) {
|
|
495
520
|
ctx.log?.error(`[${ctx.account.accountId}] Failed to send group message to ${groupName}: ${err}`);
|
|
@@ -514,8 +539,9 @@ export const unicityChannelPlugin = {
|
|
|
514
539
|
|
|
515
540
|
// Subscribe to incoming group messages
|
|
516
541
|
const unsubGroupMessage = sphere.groupChat?.onMessage?.((msg: GroupMsg) => {
|
|
517
|
-
// Skip messages from self
|
|
518
|
-
|
|
542
|
+
// Skip messages from self (echoed back by the relay).
|
|
543
|
+
// Compare against the Nostr x-only pubkey, not chainPubkey.
|
|
544
|
+
if (myNostrPubkey && msg.senderPubkey === myNostrPubkey) return;
|
|
519
545
|
|
|
520
546
|
// Lookup or create per-group backfill state
|
|
521
547
|
let state = groupBackfillStates.get(msg.groupId);
|