


























@@ -123,6 +123,7 @@ import {
123123evaluateTelegramGroupBaseAccess,
124124evaluateTelegramGroupPolicyAccess,
125125} from "./group-access.js";
126+import { resolveTelegramGroupHistoryContextMode } from "./group-history-context.js";
126127import { migrateTelegramGroupConfig } from "./group-migration.js";
127128import {
128129resolveTelegramCommandIngressAuthorization,
@@ -1173,12 +1174,76 @@ export const registerTelegramHandlers = ({
11731174is_reply_target: flags?.replyTarget === true ? true : undefined,
11741175});
117511761177+const buildMentionOnlyGroupHistoryPredicate = (params: {
1178+ctx: TelegramContext;
1179+msg: Message;
1180+threadId?: number;
1181+}): ((node: TelegramCachedMessageNode) => boolean) => {
1182+const runtimeCfg = telegramDeps.getRuntimeConfig();
1183+const isForum =
1184+params.msg.chat.type === "supergroup" &&
1185+Boolean(params.msg.chat.is_forum || params.msg.is_topic_message);
1186+const senderId = params.msg.from?.id != null ? String(params.msg.from.id) : undefined;
1187+const sessionState = resolveTelegramSessionState({
1188+chatId: params.msg.chat.id,
1189+isGroup: true,
1190+ isForum,
1191+messageThreadId: params.msg.message_thread_id,
1192+resolvedThreadId: params.threadId,
1193+ senderId,
1194+ runtimeCfg,
1195+});
1196+const conversationId = buildTelegramGroupPeerId(params.msg.chat.id, params.threadId);
1197+const mentionRegexes = buildMentionRegexes(runtimeCfg, sessionState.agentId, {
1198+provider: "telegram",
1199+ conversationId,
1200+providerPolicy: telegramCfg.mentionPatterns,
1201+});
1202+const botUsername = params.ctx.me?.username?.trim().toLowerCase();
1203+const botId = params.ctx.me?.id;
1204+return (node) => {
1205+if (botId != null && node.sourceMessage.from?.id === botId) {
1206+return true;
1207+}
1208+const replyFromId = node.sourceMessage.reply_to_message?.from?.id;
1209+if (
1210+botId != null &&
1211+replyFromId === botId &&
1212+!isTelegramForumServiceMessage(node.sourceMessage.reply_to_message)
1213+) {
1214+return true;
1215+}
1216+const messageTextParts = getTelegramTextParts(node.sourceMessage);
1217+const hasAnyMention = messageTextParts.entities.some((ent) => ent.type === "mention");
1218+const explicitlyMentioned = botUsername
1219+ ? hasBotMention(node.sourceMessage, botUsername)
1220+ : false;
1221+return matchesMentionWithExplicit({
1222+text: messageTextParts.text,
1223+ mentionRegexes,
1224+explicit: {
1225+ hasAnyMention,
1226+isExplicitlyMentioned: explicitlyMentioned,
1227+canResolveExplicit: Boolean(botUsername),
1228+},
1229+});
1230+};
1231+};
1232+11761233const buildPromptContextForMessage = async (
1234+ctx: TelegramContext,
11771235msg: Message,
11781236replyChainNodes: TelegramCachedMessageNode[],
11791237options?: TelegramMessageContextOptions,
11801238mediaByMessageId?: ReadonlyMap<string, TelegramMediaRef>,
11811239): Promise<TelegramPromptContextEntry[]> => {
1240+const isGroup = msg.chat.type === "group" || msg.chat.type === "supergroup";
1241+const groupHistoryContextMode = isGroup
1242+ ? resolveTelegramGroupHistoryContextMode(telegramCfg)
1243+ : "recent";
1244+if (isGroup && groupHistoryContextMode === "none") {
1245+return [];
1246+}
11821247const messageId = typeof msg.message_id === "number" ? String(msg.message_id) : undefined;
11831248const currentNode = await messageCache.get({
11841249 accountId,
@@ -1198,6 +1263,9 @@ export const registerTelegramHandlers = ({
11981263 ...(options?.promptContextMinTimestampMs !== undefined
11991264 ? { minTimestampMs: options.promptContextMinTimestampMs }
12001265 : {}),
1266+ ...(isGroup && groupHistoryContextMode === "mention-only"
1267+ ? { includeNode: buildMentionOnlyGroupHistoryPredicate({ ctx, msg, threadId }) }
1268+ : {}),
12011269});
12021270return conversationContext.length > 0
12031271 ? [
@@ -1314,6 +1382,7 @@ export const registerTelegramHandlers = ({
13141382}
13151383}
13161384const promptContext = await buildPromptContextForMessage(
1385+params.ctx,
13171386params.msg,
13181387replyChainNodes,
13191388params.options,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。