diff --git a/extensions/matrix/src/types.ts b/extensions/matrix/src/types.ts index 2c12c673d17..564ad3118ce 100644 --- a/extensions/matrix/src/types.ts +++ b/extensions/matrix/src/types.ts @@ -110,7 +110,7 @@ export type CoreConfig = { }; messages?: { ackReaction?: string; - ackReactionScope?: "group-mentions" | "group-all" | "direct" | "all"; + ackReactionScope?: "group-mentions" | "group-all" | "direct" | "all" | "off" | "none"; }; [key: string]: unknown; }; diff --git a/src/config/schema.help.ts b/src/config/schema.help.ts index 94f1766e487..22c50336188 100644 --- a/src/config/schema.help.ts +++ b/src/config/schema.help.ts @@ -1361,7 +1361,7 @@ export const FIELD_HELP: Record = { "When true, suppress ⚠️ tool-error warnings from being shown to the user. The agent already sees errors in context and can retry. Default: false.", "messages.ackReaction": "Emoji reaction used to acknowledge inbound messages (empty disables).", "messages.ackReactionScope": - 'When to send ack reactions ("group-mentions", "group-all", "direct", "all").', + 'When to send ack reactions ("group-mentions", "group-all", "direct", "all", "off", "none"). "off"/"none" disables ack reactions entirely.', "messages.statusReactions": "Lifecycle status reactions that update the emoji on the trigger message as the agent progresses (queued → thinking → tool → done/error).", "messages.statusReactions.enabled": diff --git a/src/config/types.discord.ts b/src/config/types.discord.ts index d57a7b57416..531fc1106cd 100644 --- a/src/config/types.discord.ts +++ b/src/config/types.discord.ts @@ -292,6 +292,8 @@ export type DiscordAccountConfig = { * Discord supports both unicode emoji and custom emoji names. */ ackReaction?: string; + /** When to send ack reactions for this Discord account. Overrides messages.ackReactionScope. */ + ackReactionScope?: "group-mentions" | "group-all" | "direct" | "all" | "off" | "none"; /** Bot activity status text (e.g. "Watching X"). */ activity?: string; /** Bot status (online|dnd|idle|invisible). Defaults to online when presence is configured. */ diff --git a/src/config/types.messages.ts b/src/config/types.messages.ts index ff71035e168..39a5ca7da69 100644 --- a/src/config/types.messages.ts +++ b/src/config/types.messages.ts @@ -112,7 +112,7 @@ export type MessagesConfig = { /** Emoji reaction used to acknowledge inbound messages (empty disables). */ ackReaction?: string; /** When to send ack reactions. Default: "group-mentions". */ - ackReactionScope?: "group-mentions" | "group-all" | "direct" | "all"; + ackReactionScope?: "group-mentions" | "group-all" | "direct" | "all" | "off" | "none"; /** Remove ack reaction after reply is sent (default: false). */ removeAckAfterReply?: boolean; /** Lifecycle status reactions configuration. */ diff --git a/src/config/zod-schema.providers-core.ts b/src/config/zod-schema.providers-core.ts index 1079cecdaf5..f0a3a8a1f95 100644 --- a/src/config/zod-schema.providers-core.ts +++ b/src/config/zod-schema.providers-core.ts @@ -508,6 +508,9 @@ export const DiscordAccountSchema = z .optional(), responsePrefix: z.string().optional(), ackReaction: z.string().optional(), + ackReactionScope: z + .enum(["group-mentions", "group-all", "direct", "all", "off", "none"]) + .optional(), activity: z.string().optional(), status: z.enum(["online", "dnd", "idle", "invisible"]).optional(), activityType: z diff --git a/src/config/zod-schema.session.ts b/src/config/zod-schema.session.ts index c33c18f4066..648caa60f5b 100644 --- a/src/config/zod-schema.session.ts +++ b/src/config/zod-schema.session.ts @@ -152,7 +152,9 @@ export const MessagesSchema = z queue: QueueSchema, inbound: InboundDebounceSchema, ackReaction: z.string().optional(), - ackReactionScope: z.enum(["group-mentions", "group-all", "direct", "all"]).optional(), + ackReactionScope: z + .enum(["group-mentions", "group-all", "direct", "all", "off", "none"]) + .optional(), removeAckAfterReply: z.boolean().optional(), statusReactions: z .object({ diff --git a/src/discord/monitor/message-handler.preflight.types.ts b/src/discord/monitor/message-handler.preflight.types.ts index b491a231983..0cca0cb4085 100644 --- a/src/discord/monitor/message-handler.preflight.types.ts +++ b/src/discord/monitor/message-handler.preflight.types.ts @@ -30,7 +30,7 @@ export type DiscordMessagePreflightContext = { mediaMaxBytes: number; textLimit: number; replyToMode: ReplyToMode; - ackReactionScope: "all" | "direct" | "group-all" | "group-mentions"; + ackReactionScope: "all" | "direct" | "group-all" | "group-mentions" | "off" | "none"; groupPolicy: "open" | "disabled" | "allowlist"; data: DiscordMessageEvent; diff --git a/src/discord/monitor/message-handler.ts b/src/discord/monitor/message-handler.ts index fd69ff4e320..71eb38ca72f 100644 --- a/src/discord/monitor/message-handler.ts +++ b/src/discord/monitor/message-handler.ts @@ -29,7 +29,10 @@ export function createDiscordMessageHandler( groupPolicy: params.discordConfig?.groupPolicy, defaultGroupPolicy: params.cfg.channels?.defaults?.groupPolicy, }); - const ackReactionScope = params.cfg.messages?.ackReactionScope ?? "group-mentions"; + const ackReactionScope = + params.discordConfig?.ackReactionScope ?? + params.cfg.messages?.ackReactionScope ?? + "group-mentions"; const debounceMs = resolveInboundDebounceMs({ cfg: params.cfg, channel: "discord" }); const debouncer = createInboundDebouncer<{ data: DiscordMessageEvent; client: Client }>({ diff --git a/src/telegram/bot-message-context.ts b/src/telegram/bot-message-context.ts index 0c3df3570ab..fb43e53edfa 100644 --- a/src/telegram/bot-message-context.ts +++ b/src/telegram/bot-message-context.ts @@ -112,7 +112,7 @@ export type BuildTelegramMessageContextParams = { dmPolicy: DmPolicy; allowFrom?: Array; groupAllowFrom?: Array; - ackReactionScope: "off" | "group-mentions" | "group-all" | "direct" | "all"; + ackReactionScope: "off" | "none" | "group-mentions" | "group-all" | "direct" | "all"; logger: TelegramLogger; resolveGroupActivation: ResolveGroupActivation; resolveGroupRequireMention: ResolveGroupRequireMention;