clawgram 2.20.0 → 2.20.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.
- package/dist/channel.js +15 -1
- package/dist/helpers.js +42 -10
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/channel.js
CHANGED
|
@@ -801,7 +801,11 @@ const createChannelPlugin = (runtimes, pluginRuntime) => {
|
|
|
801
801
|
text,
|
|
802
802
|
message: rawMessage,
|
|
803
803
|
});
|
|
804
|
-
|
|
804
|
+
// One fetch serves two needs: the reply-to-self gate below and
|
|
805
|
+
// the parent's text for the agent (ReplyToBody), which a plain
|
|
806
|
+
// reply does not carry on its own.
|
|
807
|
+
const replyParent = await (0, helpers_1.resolveReplyParent)(rawMessage, { selfId, selfLabel });
|
|
808
|
+
const wasReplyToSelf = replyParent.isSelf;
|
|
805
809
|
const mentionDecision = (0, channel_inbound_1.resolveInboundMentionDecision)({
|
|
806
810
|
facts: {
|
|
807
811
|
canDetectMention: true,
|
|
@@ -875,6 +879,10 @@ const createChannelPlugin = (runtimes, pluginRuntime) => {
|
|
|
875
879
|
// bare text, and the fragment the person pointed at is lost.
|
|
876
880
|
ReplyToQuoteText: normalized.replyQuoteText,
|
|
877
881
|
ReplyToIsQuote: normalized.replyIsQuote,
|
|
882
|
+
// A plain reply has no highlight; core then falls back to the
|
|
883
|
+
// parent's body, which only exists if the channel fetched it.
|
|
884
|
+
ReplyToBody: replyParent.body,
|
|
885
|
+
ReplyToSender: replyParent.sender,
|
|
878
886
|
MessageThreadId: normalized.messageThreadId,
|
|
879
887
|
NativeChannelId: normalized.chatId,
|
|
880
888
|
// Trusted per-group prompt block from `groups.<id>.systemPrompt`.
|
|
@@ -1179,6 +1187,10 @@ const createChannelPlugin = (runtimes, pluginRuntime) => {
|
|
|
1179
1187
|
});
|
|
1180
1188
|
return;
|
|
1181
1189
|
}
|
|
1190
|
+
// Same fetch as the group path. In a DM the parent is as often
|
|
1191
|
+
// the agent's own message as the person's — the owner answers a
|
|
1192
|
+
// notice she sent — and neither text is available any other way.
|
|
1193
|
+
const replyParent = await (0, helpers_1.resolveReplyParent)(rawMessage, { selfId, selfLabel });
|
|
1182
1194
|
await gram.withTyping(conversationTarget, async () => {
|
|
1183
1195
|
await (0, direct_dm_1.dispatchInboundDirectDmWithRuntime)({
|
|
1184
1196
|
cfg,
|
|
@@ -1210,6 +1222,8 @@ const createChannelPlugin = (runtimes, pluginRuntime) => {
|
|
|
1210
1222
|
// direct messages too, and the fragment is not part of the text.
|
|
1211
1223
|
ReplyToQuoteText: normalized.replyQuoteText,
|
|
1212
1224
|
ReplyToIsQuote: normalized.replyIsQuote,
|
|
1225
|
+
ReplyToBody: replyParent.body,
|
|
1226
|
+
ReplyToSender: replyParent.sender,
|
|
1213
1227
|
NativeChannelId: normalized.chatId,
|
|
1214
1228
|
},
|
|
1215
1229
|
deliver: async (payload) => {
|
package/dist/helpers.js
CHANGED
|
@@ -36,6 +36,7 @@ exports.prefixReplyTextToAddress = prefixReplyTextToAddress;
|
|
|
36
36
|
exports.resolveReplyTarget = resolveReplyTarget;
|
|
37
37
|
exports.resolveChatTarget = resolveChatTarget;
|
|
38
38
|
exports.isReplyToSelfMessage = isReplyToSelfMessage;
|
|
39
|
+
exports.resolveReplyParent = resolveReplyParent;
|
|
39
40
|
exports.resolveSenderProfile = resolveSenderProfile;
|
|
40
41
|
exports.resolveSenderProfileWithTimeout = resolveSenderProfileWithTimeout;
|
|
41
42
|
exports.normalizeParseMode = normalizeParseMode;
|
|
@@ -549,27 +550,58 @@ async function resolveChatTarget(message) {
|
|
|
549
550
|
}
|
|
550
551
|
return message?.inputChat ?? message?._inputChat ?? message?.chat ?? message?._chat ?? message?.peerId;
|
|
551
552
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
553
|
+
/**
|
|
554
|
+
* The message a reply points at, fetched once.
|
|
555
|
+
*
|
|
556
|
+
* Telegram does not put the parent's text into the reply; a highlight
|
|
557
|
+
* (`quoteText`) is the only fragment that travels with it, and most replies
|
|
558
|
+
* have none. Core renders `[Replying to: …]` from the highlight or, failing
|
|
559
|
+
* that, from `ReplyToBody` — so without this fetch a plain reply reaches the
|
|
560
|
+
* agent as a bare parent id. The case that exposed it: the owner answered, in
|
|
561
|
+
* a DM, the agent's own notice about an unknown sender; the notice had been
|
|
562
|
+
* sent from another session, DMs are outside `readChats`, and the agent had
|
|
563
|
+
* no way to learn what "reply to #1011" referred to.
|
|
564
|
+
*
|
|
565
|
+
* Failure degrades to "no context" on purpose: a parent that cannot be
|
|
566
|
+
* fetched (deleted, flood-waited, transport hiccup) must not cost the
|
|
567
|
+
* message itself.
|
|
568
|
+
*/
|
|
569
|
+
async function resolveReplyParent(message, input) {
|
|
556
570
|
const replyToMessageId = message?.replyTo?.replyToMsgId ?? message?.replyToMsgId;
|
|
557
571
|
if (!replyToMessageId) {
|
|
558
|
-
return false;
|
|
572
|
+
return { isSelf: false };
|
|
559
573
|
}
|
|
560
574
|
const replied = typeof message?.getReplyMessage === "function"
|
|
561
575
|
? await message.getReplyMessage().catch(() => undefined)
|
|
562
576
|
: undefined;
|
|
563
577
|
if (!replied) {
|
|
564
|
-
return false;
|
|
565
|
-
}
|
|
566
|
-
if (replied.out === true) {
|
|
567
|
-
return true;
|
|
578
|
+
return { isSelf: false };
|
|
568
579
|
}
|
|
569
580
|
const replySenderId = replied.senderId ??
|
|
570
581
|
replied.fromId?.userId ??
|
|
571
582
|
replied.fromId?.channelId;
|
|
572
|
-
|
|
583
|
+
const isSelf = replied.out === true ||
|
|
584
|
+
(input.selfId !== undefined && replySenderId !== undefined && String(replySenderId) === input.selfId);
|
|
585
|
+
const rawText = typeof replied.message === "string" ? replied.message :
|
|
586
|
+
typeof replied.text === "string" ? replied.text :
|
|
587
|
+
"";
|
|
588
|
+
const body = rawText.trim() ? rawText : undefined;
|
|
589
|
+
const source = replied.sender ?? replied._sender;
|
|
590
|
+
const sender = isSelf
|
|
591
|
+
? (input.selfLabel ?? (input.selfId !== undefined ? input.selfId : undefined))
|
|
592
|
+
: toDisplayName({
|
|
593
|
+
firstName: typeof source?.firstName === "string" ? source.firstName : undefined,
|
|
594
|
+
lastName: typeof source?.lastName === "string" ? source.lastName : undefined,
|
|
595
|
+
username: undefined,
|
|
596
|
+
fallback: resolveActiveUsername(source) ? `@${resolveActiveUsername(source)}` : (replySenderId !== undefined ? String(replySenderId) : undefined),
|
|
597
|
+
});
|
|
598
|
+
return { isSelf, body, sender: sender || undefined };
|
|
599
|
+
}
|
|
600
|
+
async function isReplyToSelfMessage(message, selfId) {
|
|
601
|
+
if (!selfId) {
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
604
|
+
return (await resolveReplyParent(message, { selfId })).isSelf;
|
|
573
605
|
}
|
|
574
606
|
async function resolveSenderProfile(message, input) {
|
|
575
607
|
const pickProfile = (source) => {
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "clawgram",
|
|
3
3
|
"name": "Clawgram",
|
|
4
4
|
"description": "Clawgram — personal Telegram (MTProto userbot) channel for OpenClaw. Your AI assistant reads and responds as you.",
|
|
5
|
-
"version": "2.20.
|
|
5
|
+
"version": "2.20.2",
|
|
6
6
|
"configSchema": {
|
|
7
7
|
"type": "object",
|
|
8
8
|
"additionalProperties": false,
|
package/package.json
CHANGED