refactor: apply context visibility across channels

This commit is contained in:
Peter Steinberger
2026-04-03 04:34:03 +09:00
parent 35e1605147
commit 694d12a90b
34 changed files with 1279 additions and 131 deletions

View File

@@ -5,10 +5,13 @@ import {
DEFAULT_GROUP_HISTORY_LIMIT,
logInboundDrop,
evaluateSenderGroupAccessForPolicy,
filterSupplementalContextItems,
recordPendingHistoryEntryIfEnabled,
resolveChannelContextVisibilityMode,
resolveDualTextControlCommandGate,
resolveMentionGating,
resolveInboundSessionEnvelopeContext,
shouldIncludeSupplementalContext,
formatAllowlistMatchMeta,
type HistoryEntry,
} from "../../runtime-api.js";
@@ -68,6 +71,10 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
}
};
const msteamsCfg = cfg.channels?.msteams;
const contextVisibilityMode = resolveChannelContextVisibilityMode({
cfg,
channel: "msteams",
});
const historyLimit = Math.max(
0,
msteamsCfg?.historyLimit ??
@@ -98,6 +105,8 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
const attachmentPlaceholder = buildMSTeamsAttachmentPlaceholder(attachments);
const rawBody = text || attachmentPlaceholder;
const quoteInfo = extractMSTeamsQuoteInfo(attachments);
let quoteSenderId: string | undefined;
let quoteSenderName: string | undefined;
const from = activity.from;
const conversation = activity.conversation;
@@ -460,17 +469,25 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
fetchThreadReplies(graphToken, groupId, conversationId, activity.replyToId),
]);
const allMessages = parentMsg ? [parentMsg, ...replies] : replies;
const threadMessages =
groupPolicy === "allowlist"
? allMessages.filter((msg) => {
return resolveMSTeamsAllowlistMatch({
quoteSenderId = parentMsg?.from?.user?.id ?? parentMsg?.from?.application?.id ?? undefined;
quoteSenderName =
parentMsg?.from?.user?.displayName ??
parentMsg?.from?.application?.displayName ??
quoteInfo?.sender;
const { items: threadMessages } = filterSupplementalContextItems({
items: allMessages,
mode: contextVisibilityMode,
kind: "thread",
isSenderAllowed: (msg) =>
groupPolicy === "allowlist"
? resolveMSTeamsAllowlistMatch({
allowFrom: effectiveGroupAllowFrom,
senderId: msg.from?.user?.id ?? "",
senderName: msg.from?.user?.displayName,
allowNameMatching,
}).allowed;
})
: allMessages;
}).allowed
: true,
});
const formatted = formatThreadContext(threadMessages, activity.id);
if (formatted) {
threadContext = formatted;
@@ -480,6 +497,7 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
// Graceful degradation: thread history is an optional enhancement.
}
}
quoteSenderName ??= quoteInfo?.sender;
const envelopeFrom = isDirectMessage ? senderName : conversationType;
const { storePath, envelopeOptions, previousTimestamp } = resolveInboundSessionEnvelopeContext({
@@ -524,6 +542,24 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
}))
: undefined;
const commandBody = text.trim();
const quoteSenderAllowed =
quoteInfo && quoteInfo.sender
? !isChannel || groupPolicy !== "allowlist"
? true
: resolveMSTeamsAllowlistMatch({
allowFrom: effectiveGroupAllowFrom,
senderId: quoteSenderId ?? "",
senderName: quoteSenderName,
allowNameMatching,
}).allowed
: true;
const includeQuoteContext =
quoteInfo &&
shouldIncludeSupplementalContext({
mode: contextVisibilityMode,
kind: "quote",
senderAllowed: quoteSenderAllowed,
});
// Prepend thread history to the agent body so the agent has full thread context.
const bodyForAgent = threadContext
@@ -555,8 +591,8 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
OriginatingChannel: "msteams" as const,
OriginatingTo: teamsTo,
ReplyToId: activity.replyToId ?? undefined,
ReplyToBody: quoteInfo?.body,
ReplyToSender: quoteInfo?.sender,
ReplyToBody: includeQuoteContext ? quoteInfo?.body : undefined,
ReplyToSender: includeQuoteContext ? quoteInfo?.sender : undefined,
ReplyToIsQuote: quoteInfo ? true : undefined,
...mediaPayload,
});