refactor: centralize inbound mention policy

This commit is contained in:
Peter Steinberger
2026-04-07 07:50:09 +01:00
parent c8b7058058
commit 625fd5b3e3
31 changed files with 857 additions and 225 deletions

View File

@@ -1,3 +1,4 @@
import { resolveInboundMentionDecision } from "openclaw/plugin-sdk/channel-inbound";
import {
buildPendingHistoryContextFromMap,
clearHistoryEntriesIfEnabled,
@@ -9,7 +10,6 @@ import {
recordPendingHistoryEntryIfEnabled,
resolveChannelContextVisibilityMode,
resolveDualTextControlCommandGate,
resolveMentionGating,
resolveInboundSessionEnvelopeContext,
shouldIncludeSupplementalContext,
formatAllowlistMatchMeta,
@@ -160,7 +160,7 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
text: string;
attachments: MSTeamsAttachmentLike[];
wasMentioned: boolean;
implicitMention: boolean;
implicitMentionKinds: Array<"reply_to_bot">;
};
const handleTeamsMessageNow = async (params: MSTeamsDebounceEntry) => {
@@ -458,17 +458,24 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
channelConfig,
});
const timestamp = parseMSTeamsActivityTimestamp(activity.timestamp);
if (!isDirectMessage) {
const mentionGate = resolveMentionGating({
requireMention: Boolean(requireMention),
const mentionDecision = resolveInboundMentionDecision({
facts: {
canDetectMention: true,
wasMentioned: params.wasMentioned,
implicitMention: params.implicitMention,
shouldBypassMention: false,
});
const mentioned = mentionGate.effectiveWasMentioned;
if (requireMention && mentionGate.shouldSkip) {
implicitMentionKinds: params.implicitMentionKinds,
},
policy: {
isGroup: !isDirectMessage,
requireMention: Boolean(requireMention),
allowTextCommands: false,
hasControlCommand: false,
commandAuthorized: false,
},
});
if (!isDirectMessage) {
const mentioned = mentionDecision.effectiveWasMentioned;
if (requireMention && mentionDecision.shouldSkip) {
log.debug?.("skipping message (mention required)", {
teamId,
channelId,
@@ -647,7 +654,7 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
Surface: "msteams" as const,
MessageSid: activity.id,
Timestamp: timestamp?.getTime() ?? Date.now(),
WasMentioned: isDirectMessage || params.wasMentioned || params.implicitMention,
WasMentioned: isDirectMessage || mentionDecision.effectiveWasMentioned,
CommandAuthorized: commandAuthorized,
OriginatingChannel: "msteams" as const,
OriginatingTo: teamsTo,
@@ -796,14 +803,14 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
.filter(Boolean)
.join("\n");
const wasMentioned = entries.some((entry) => entry.wasMentioned);
const implicitMention = entries.some((entry) => entry.implicitMention);
const implicitMentionKinds = entries.flatMap((entry) => entry.implicitMentionKinds);
await handleTeamsMessageNow({
context: last.context,
rawText: combinedRawText,
text: combinedText,
attachments: [],
wasMentioned,
implicitMention,
implicitMentionKinds,
});
},
onError: (err) => {
@@ -822,9 +829,10 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
const wasMentioned = wasMSTeamsBotMentioned(activity);
const conversationId = normalizeMSTeamsConversationId(activity.conversation?.id ?? "");
const replyToId = activity.replyToId ?? undefined;
const implicitMention = Boolean(
conversationId && replyToId && wasMSTeamsMessageSent(conversationId, replyToId),
);
const implicitMentionKinds: Array<"reply_to_bot"> =
conversationId && replyToId && wasMSTeamsMessageSent(conversationId, replyToId)
? ["reply_to_bot"]
: [];
await inboundDebouncer.enqueue({
context,
@@ -832,7 +840,7 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
text,
attachments,
wasMentioned,
implicitMention,
implicitMentionKinds,
});
};
}