clawgram 2.26.1 → 2.27.0
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.
|
@@ -79,5 +79,10 @@ function buildGroupReplyAddress(input) {
|
|
|
79
79
|
if (display && display !== "Telegram") {
|
|
80
80
|
return display;
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
// No handle and no name means no greeting, not a numeric one. The id
|
|
83
|
+
// used to be the fallback, and in a basic group — where GramJS attaches
|
|
84
|
+
// no sender profile to the message — every reply of a day opened with
|
|
85
|
+
// «890975818, …» (07.09.2026). A person does not know their own
|
|
86
|
+
// telegram id and reads it as a malfunction.
|
|
87
|
+
return undefined;
|
|
83
88
|
}
|
package/dist/inbound-pipeline.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.visibleReplyText = visibleReplyText;
|
|
4
4
|
exports.handleInboundEvent = handleInboundEvent;
|
|
5
|
+
exports.agentFacingGroupBody = agentFacingGroupBody;
|
|
5
6
|
// Входящий контур: одно событие Telegram от нормализации до ответа.
|
|
6
7
|
//
|
|
7
8
|
// Вынесено из `channel.ts` — 856 строк внутри `gateway.startAccount`, самый
|
|
@@ -252,6 +253,13 @@ async function handleInboundEvent(event, ctx) {
|
|
|
252
253
|
senderId: inboundSenderId,
|
|
253
254
|
senderUsername: normalized.senderUsername,
|
|
254
255
|
});
|
|
256
|
+
// The name of a direct-message sender who may reach the agent. The gate
|
|
257
|
+
// above stays where B5-04 put it — a blocked sender still costs no
|
|
258
|
+
// call. A group sender is looked up later, after the mention gate, for
|
|
259
|
+
// the same reason (see the group branch).
|
|
260
|
+
if (normalized.chatType === "direct" && senderMayReachAgent) {
|
|
261
|
+
await resolveNamelessSender(normalized, rawMessage, client);
|
|
262
|
+
}
|
|
255
263
|
// An attachment carries no text of its own, and dropping it as
|
|
256
264
|
// "empty" is how the assistant used to go silent on being spoken
|
|
257
265
|
// to or shown something. Read it into the body instead: for a
|
|
@@ -485,16 +493,32 @@ async function handleInboundEvent(event, ctx) {
|
|
|
485
493
|
});
|
|
486
494
|
return;
|
|
487
495
|
}
|
|
496
|
+
// Who is speaking, resolved only now — past the group gate and the
|
|
497
|
+
// mention gate, so a message the agent will not even read costs no
|
|
498
|
+
// call (B5-04). GramJS attaches `_sender` only from its entity cache,
|
|
499
|
+
// and in a basic group (or after a restart) that cache is empty: the
|
|
500
|
+
// turn then had nothing but the numeric id, the reply greeting fell
|
|
501
|
+
// back to it, and a management chat spent 07.09.2026 being addressed
|
|
502
|
+
// as «890975818, …». One source of truth for the name: the address
|
|
503
|
+
// the channel would prepend is also what the agent reads, so the
|
|
504
|
+
// model cannot greet «Вася Ш.» while the channel greets «@vasya».
|
|
505
|
+
await resolveNamelessSender(normalized, rawMessage, client);
|
|
506
|
+
const groupSenderLabel = normalized.senderDisplay || normalized.senderUsername || senderId;
|
|
507
|
+
const groupReplyAddress = (0, group_reply_address_1.buildGroupReplyAddress)({
|
|
508
|
+
senderUsername: normalized.senderUsername,
|
|
509
|
+
senderDisplay: normalized.senderDisplay,
|
|
510
|
+
senderId,
|
|
511
|
+
});
|
|
488
512
|
const { storePath, body } = buildEnvelope({
|
|
489
513
|
channel: "Telegram",
|
|
490
|
-
from:
|
|
514
|
+
from: groupSenderLabel,
|
|
491
515
|
body: text,
|
|
492
516
|
timestamp: normalized.timestamp,
|
|
493
517
|
});
|
|
494
518
|
const conversationRouteTarget = (0, helpers_1.buildConversationTarget)(normalized.chatId);
|
|
495
519
|
const ctxPayload = channelRuntime.reply.finalizeInboundContext({
|
|
496
520
|
Body: body,
|
|
497
|
-
BodyForAgent: text,
|
|
521
|
+
BodyForAgent: agentFacingGroupBody({ address: groupReplyAddress, senderId, text }),
|
|
498
522
|
RawBody: text,
|
|
499
523
|
CommandBody: text,
|
|
500
524
|
From: conversationRouteTarget,
|
|
@@ -502,7 +526,7 @@ async function handleInboundEvent(event, ctx) {
|
|
|
502
526
|
SessionKey: route.sessionKey,
|
|
503
527
|
AccountId: route.accountId ?? accountId,
|
|
504
528
|
ChatType: "group",
|
|
505
|
-
ConversationLabel:
|
|
529
|
+
ConversationLabel: groupSenderLabel,
|
|
506
530
|
SenderId: senderId,
|
|
507
531
|
SenderUsername: normalized.senderUsername,
|
|
508
532
|
SenderName: normalized.senderDisplay,
|
|
@@ -535,11 +559,6 @@ async function handleInboundEvent(event, ctx) {
|
|
|
535
559
|
OriginatingChannel: "clawgram",
|
|
536
560
|
OriginatingTo: conversationRouteTarget,
|
|
537
561
|
});
|
|
538
|
-
const groupReplyAddress = (0, group_reply_address_1.buildGroupReplyAddress)({
|
|
539
|
-
senderUsername: normalized.senderUsername,
|
|
540
|
-
senderDisplay: normalized.senderDisplay,
|
|
541
|
-
senderId,
|
|
542
|
-
});
|
|
543
562
|
(0, group_reply_address_1.rememberGroupReplyAddress)({
|
|
544
563
|
accountId: route.accountId ?? accountId,
|
|
545
564
|
chatId: normalized.chatId,
|
|
@@ -897,3 +916,51 @@ async function handleInboundEvent(event, ctx) {
|
|
|
897
916
|
});
|
|
898
917
|
}
|
|
899
918
|
}
|
|
919
|
+
/**
|
|
920
|
+
* A sender who arrived without a name or handle gets one profile lookup.
|
|
921
|
+
*
|
|
922
|
+
* GramJS attaches `_sender` only from its in-memory entity cache; a basic
|
|
923
|
+
* group's update carries no users, so after a restart the cache is empty
|
|
924
|
+
* until something else (a `participants` read) fills it. The lookup may
|
|
925
|
+
* therefore still come back empty — then the sender stays nameless, the
|
|
926
|
+
* greeting is omitted and the agent reads `id:<n>`. Callers decide *when*
|
|
927
|
+
* this runs: after every gate, never for traffic the agent will not read.
|
|
928
|
+
*/
|
|
929
|
+
async function resolveNamelessSender(normalized, rawMessage, client) {
|
|
930
|
+
if (!normalized.senderId || normalized.senderDisplay || normalized.senderUsername) {
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
const profile = await (0, helpers_1.resolveSenderProfileWithTimeout)(rawMessage, {
|
|
934
|
+
senderId: normalized.senderId,
|
|
935
|
+
client,
|
|
936
|
+
}, 1500);
|
|
937
|
+
if (profile.username) {
|
|
938
|
+
normalized.senderUsername = profile.username;
|
|
939
|
+
}
|
|
940
|
+
// `toDisplayName` answers "Telegram" when it knows nothing; that is not
|
|
941
|
+
// a name and must not become one here.
|
|
942
|
+
if (profile.display && profile.display !== "Telegram") {
|
|
943
|
+
normalized.senderDisplay = profile.display;
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* What the agent reads for a group message: `Адрес: текст`.
|
|
948
|
+
*
|
|
949
|
+
* Until 2.27.0 the turn received the bare text. Core's own Telegram channel
|
|
950
|
+
* prefixes the sender for groups (`formatInboundEnvelope`), and without that
|
|
951
|
+
* the agent could tell speakers apart only by the numeric id in metadata —
|
|
952
|
+
* which is exactly what it then used as an address. The prefix is the very
|
|
953
|
+
* address the channel would prepend to a reply (`buildGroupReplyAddress`),
|
|
954
|
+
* so what the model addresses and what the channel greets never differ —
|
|
955
|
+
* a display name in the body with a handle in the greeting would have
|
|
956
|
+
* produced «@vasya, Вася Ш., готово». No address known: `id:<n>`, marked
|
|
957
|
+
* so it is never mistaken for a name.
|
|
958
|
+
*/
|
|
959
|
+
function agentFacingGroupBody(input) {
|
|
960
|
+
const address = input.address?.trim();
|
|
961
|
+
if (address) {
|
|
962
|
+
return `${address}: ${input.text}`;
|
|
963
|
+
}
|
|
964
|
+
const id = input.senderId !== undefined ? String(input.senderId).trim() : "";
|
|
965
|
+
return id ? `id:${id}: ${input.text}` : input.text;
|
|
966
|
+
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawgram",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.27.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "clawgram",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.27.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"json5": "2.2.3",
|
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.
|
|
5
|
+
"version": "2.27.0",
|
|
6
6
|
"configSchema": {
|
|
7
7
|
"type": "object",
|
|
8
8
|
"additionalProperties": false,
|
package/package.json
CHANGED