@@ -15,22 +15,24 @@ import {
1515} from "openclaw/plugin-sdk/channel-inbound" ;
1616import { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline" ;
1717import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime" ;
18+ import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/config-runtime" ;
1819import { resolveDiscordPreviewStreamMode } from "openclaw/plugin-sdk/config-runtime" ;
1920import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime" ;
2021import { readSessionUpdatedAt , resolveStorePath } from "openclaw/plugin-sdk/config-runtime" ;
2122import { recordInboundSession } from "openclaw/plugin-sdk/conversation-runtime" ;
2223import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime" ;
24+ import { resolveChunkMode } from "openclaw/plugin-sdk/reply-chunking" ;
25+ import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-dispatch-runtime" ;
2326import {
2427 buildPendingHistoryContextFromMap ,
2528 clearHistoryEntriesIfEnabled ,
2629} from "openclaw/plugin-sdk/reply-history" ;
2730import { resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload" ;
28- import { resolveChunkMode } from "openclaw/plugin-sdk/reply-chunking" ;
29- import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-dispatch-runtime" ;
3031import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime" ;
3132import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing" ;
3233import { resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing" ;
3334import { danger , logVerbose , shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env" ;
35+ import { evaluateSupplementalContextVisibility } from "openclaw/plugin-sdk/security-runtime" ;
3436import { convertMarkdownTables } from "openclaw/plugin-sdk/text-runtime" ;
3537import { stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-runtime" ;
3638import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-runtime" ;
@@ -42,7 +44,10 @@ import { reactMessageDiscord, removeReactionDiscord } from "../send.js";
4244import { editMessageDiscord } from "../send.messages.js" ;
4345import { normalizeDiscordSlug } from "./allow-list.js" ;
4446import { resolveTimestampMs } from "./format.js" ;
45- import { buildDiscordInboundAccessContext } from "./inbound-context.js" ;
47+ import {
48+ buildDiscordInboundAccessContext ,
49+ createDiscordSupplementalContextAccessChecker ,
50+ } from "./inbound-context.js" ;
4651import type { DiscordMessagePreflightContext } from "./message-handler.preflight.js" ;
4752import {
4853 buildDiscordMediaPayload ,
@@ -257,6 +262,18 @@ export async function processDiscordMessage(
257262 channelTopic : channelInfo ?. topic ,
258263 messageBody : text ,
259264 } ) ;
265+ const contextVisibilityMode = resolveChannelContextVisibilityMode ( {
266+ cfg,
267+ channel : "discord" ,
268+ accountId,
269+ } ) ;
270+ const allowNameMatching = isDangerousNameMatchingEnabled ( discordConfig ) ;
271+ const isSupplementalContextSenderAllowed = createDiscordSupplementalContextAccessChecker ( {
272+ channelConfig,
273+ guildInfo,
274+ allowNameMatching,
275+ isGuild : isGuildMessage ,
276+ } ) ;
260277 const storePath = resolveStorePath ( cfg . session ?. store , {
261278 agentId : route . agentId ,
262279 } ) ;
@@ -296,6 +313,22 @@ export async function processDiscordMessage(
296313 } ) ;
297314 }
298315 const replyContext = resolveReplyContext ( message , resolveDiscordMessageText ) ;
316+ const replyVisibility = replyContext
317+ ? evaluateSupplementalContextVisibility ( {
318+ mode : contextVisibilityMode ,
319+ kind : "quote" ,
320+ senderAllowed : isSupplementalContextSenderAllowed ( {
321+ id : replyContext . senderId ,
322+ name : replyContext . senderName ,
323+ tag : replyContext . senderTag ,
324+ memberRoleIds : replyContext . memberRoleIds ,
325+ } ) ,
326+ } )
327+ : null ;
328+ const filteredReplyContext = replyContext && replyVisibility ?. include ? replyContext : null ;
329+ if ( replyContext && ! filteredReplyContext && isGuildMessage ) {
330+ logVerbose ( `discord: drop reply context (mode=${ contextVisibilityMode } )` ) ;
331+ }
299332 if ( forumContextLine ) {
300333 combinedBody = `${ combinedBody } \n${ forumContextLine } ` ;
301334 }
@@ -314,8 +347,22 @@ export async function processDiscordMessage(
314347 resolveTimestampMs,
315348 } ) ;
316349 if ( starter ?. text ) {
317- // Keep thread starter as raw text; metadata is provided out-of-band in the system prompt.
318- threadStarterBody = starter . text ;
350+ const starterVisibility = evaluateSupplementalContextVisibility ( {
351+ mode : contextVisibilityMode ,
352+ kind : "thread" ,
353+ senderAllowed : isSupplementalContextSenderAllowed ( {
354+ id : starter . authorId ,
355+ name : starter . authorName ?? starter . author ,
356+ tag : starter . authorTag ,
357+ memberRoleIds : starter . memberRoleIds ,
358+ } ) ,
359+ } ) ;
360+ if ( starterVisibility . include ) {
361+ // Keep thread starter as raw text; metadata is provided out-of-band in the system prompt.
362+ threadStarterBody = starter . text ;
363+ } else {
364+ logVerbose ( `discord: drop thread starter context (mode=${ contextVisibilityMode } )` ) ;
365+ }
319366 }
320367 }
321368 const parentName = threadParentName ?? "parent" ;
@@ -405,9 +452,9 @@ export async function processDiscordMessage(
405452 Surface : "discord" as const ,
406453 WasMentioned : effectiveWasMentioned ,
407454 MessageSid : message . id ,
408- ReplyToId : replyContext ?. id ,
409- ReplyToBody : replyContext ?. body ,
410- ReplyToSender : replyContext ?. sender ,
455+ ReplyToId : filteredReplyContext ?. id ,
456+ ReplyToBody : filteredReplyContext ?. body ,
457+ ReplyToSender : filteredReplyContext ?. sender ,
411458 ParentSessionKey : autoThreadContext ?. ParentSessionKey ?? threadKeys . parentSessionKey ,
412459 MessageThreadId : threadChannel ?. id ?? autoThreadContext ?. createdThreadId ?? undefined ,
413460 ThreadStarterBody : threadStarterBody ,
0 commit comments