From 7e8604fc56ea959679da8e0da39ca2d0cccc09b9 Mon Sep 17 00:00:00 2001 From: LIU9293 Date: Sat, 28 Feb 2026 04:14:12 +0000 Subject: [PATCH 1/5] fix: ignore Discord thread messages that mention other bots --- packages/ims/discord/client.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/ims/discord/client.ts b/packages/ims/discord/client.ts index d5330e0..6601f71 100644 --- a/packages/ims/discord/client.ts +++ b/packages/ims/discord/client.ts @@ -376,6 +376,12 @@ function isBotMentioned(message: any, botUserId: string): boolean { return content.includes(`<@${botUserId}>`) || content.includes(`<@!${botUserId}>`); } +function shouldDropForOtherBotMentions(message: any, isCurrentBotMentioned: boolean): boolean { + const mentionedUsers = Array.from(message?.mentions?.users?.values?.() ?? []); + const mentionsAnyBot = mentionedUsers.some((user: any) => Boolean(user?.bot)); + return mentionsAnyBot && !isCurrentBotMentioned; +} + async function renameDiscordThread( channelId: string, threadId: string, @@ -464,6 +470,20 @@ async function startDiscordRuntimeInternal(reason: string): Promise { const threadId = message.channel.id; const text = message.content.trim(); + const mentioned = isBotMentioned(message, client.user.id); + if (shouldDropForOtherBotMentions(message, mentioned)) { + log.debug(formatIncomingDropMessage("not_mentioned_and_inactive"), { + platform: "discord", + channelId: parentId, + threadId, + messageId: message.id, + isTopLevel: false, + mentioned, + activeThread: false, + reason: "mentioned_other_bot", + }); + return; + } if (await maybeHandleLauncherCommand({ text, message, @@ -472,7 +492,6 @@ async function startDiscordRuntimeInternal(reason: string): Promise { })) { return; } - const mentioned = isBotMentioned(message, client.user.id); const active = isThreadActive(parentId, threadId, processorId); const normalizedText = mentioned ? cleanBotMention(text, client.user.id) : text; const threadSession = loadSession(parentId, threadId); From 152f93e52ca758c56aff3f6b232fb90817392c34 Mon Sep 17 00:00:00 2001 From: LIU9293 Date: Sat, 28 Feb 2026 04:16:47 +0000 Subject: [PATCH 2/5] fix: align mention routing guard across Discord and Lark --- packages/ims/discord/client.ts | 7 +++---- packages/ims/lark/client.ts | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/ims/discord/client.ts b/packages/ims/discord/client.ts index 6601f71..d18c59c 100644 --- a/packages/ims/discord/client.ts +++ b/packages/ims/discord/client.ts @@ -376,10 +376,9 @@ function isBotMentioned(message: any, botUserId: string): boolean { return content.includes(`<@${botUserId}>`) || content.includes(`<@!${botUserId}>`); } -function shouldDropForOtherBotMentions(message: any, isCurrentBotMentioned: boolean): boolean { +function shouldDropForOtherMentions(message: any, isCurrentBotMentioned: boolean): boolean { const mentionedUsers = Array.from(message?.mentions?.users?.values?.() ?? []); - const mentionsAnyBot = mentionedUsers.some((user: any) => Boolean(user?.bot)); - return mentionsAnyBot && !isCurrentBotMentioned; + return mentionedUsers.length > 0 && !isCurrentBotMentioned; } async function renameDiscordThread( @@ -471,7 +470,7 @@ async function startDiscordRuntimeInternal(reason: string): Promise { const threadId = message.channel.id; const text = message.content.trim(); const mentioned = isBotMentioned(message, client.user.id); - if (shouldDropForOtherBotMentions(message, mentioned)) { + if (shouldDropForOtherMentions(message, mentioned)) { log.debug(formatIncomingDropMessage("not_mentioned_and_inactive"), { platform: "discord", channelId: parentId, diff --git a/packages/ims/lark/client.ts b/packages/ims/lark/client.ts index bba96fa..b9482ee 100644 --- a/packages/ims/lark/client.ts +++ b/packages/ims/lark/client.ts @@ -678,6 +678,10 @@ function isBotMentionedInText(rawText: string, botOpenId: string): boolean { return pattern.test(rawText); } +function shouldDropForOtherMentions(mentions: string[], isCurrentBotMentioned: boolean): boolean { + return mentions.length > 0 && !isCurrentBotMentioned; +} + type LarkIncomingEnvelope = { type?: string; challenge?: string; @@ -1086,6 +1090,17 @@ async function processLarkIncomingEvent(event: LarkIncomingEvent, processorAppId const isMentioned = botOpenId ? (mentions.includes(botOpenId) || isBotMentionedInText(rawText, botOpenId)) : false; + if (shouldDropForOtherMentions(mentions, isMentioned)) { + logLarkEvent("Lark inbound ignored: message mentions another target", { + channelId, + threadId, + messageId, + mentionCount: mentions.length, + isMentioned, + reason: "mentioned_other_target", + }); + return; + } const active = isThreadActive(channelId, threadId, processorId); const threadSession = loadSession(channelId, threadId); const text = stripLarkMentionMarkup(rawText); From 98094fea5c962242c3a387087f70b26b917b2032 Mon Sep 17 00:00:00 2001 From: LIU9293 Date: Sat, 28 Feb 2026 04:21:01 +0000 Subject: [PATCH 3/5] refactor: centralize cross-platform mention routing policy --- packages/core/kernel/runtime-facade.ts | 4 +++ packages/core/model/raw-inbound-event.ts | 1 + packages/ims/discord/client.ts | 23 +++----------- packages/ims/lark/client.ts | 17 ++--------- packages/ims/shared/inbound-policy.test.ts | 34 +++++++++++++++++++++ packages/ims/shared/inbound-policy.ts | 5 +++ packages/ims/slack/message-router.ts | 25 ++------------- packages/ims/slack/slack-inbound-adapter.ts | 1 + 8 files changed, 53 insertions(+), 57 deletions(-) create mode 100644 packages/ims/shared/inbound-policy.test.ts diff --git a/packages/core/kernel/runtime-facade.ts b/packages/core/kernel/runtime-facade.ts index b770929..afeed6e 100644 --- a/packages/core/kernel/runtime-facade.ts +++ b/packages/core/kernel/runtime-facade.ts @@ -86,6 +86,7 @@ export class KernelRuntimeFacade { threadOwnerMessage: event.threadOwnerMessage, threadParticipantBotCount: event.threadParticipantBotCount, isTopLevel: event.isTopLevel, + hasAnyMention: event.hasAnyMention ?? event.mentionedBot, mentionedBot: event.mentionedBot, activeThread: event.activeThread, normalizedText: event.normalizedText, @@ -106,6 +107,7 @@ export class KernelRuntimeFacade { threadOwnerMessage: event.threadOwnerMessage, threadParticipantBotCount: event.threadParticipantBotCount, isTopLevel: event.isTopLevel, + hasAnyMention: event.hasAnyMention ?? event.mentionedBot, mentionedBot: event.mentionedBot, activeThread: event.activeThread, normalizedText: event.normalizedText, @@ -165,6 +167,7 @@ export class KernelRuntimeFacade { threadOwnerMessage: true, threadParticipantBotCount: 1, isTopLevel: false, + hasAnyMention: false, mentionedBot: true, activeThread: true, rawText: selection, @@ -269,6 +272,7 @@ export class KernelRuntimeFacade { threadOwnerMessage: true, threadParticipantBotCount: 1, isTopLevel: false, + hasAnyMention: false, mentionedBot: true, activeThread: true, rawText: text, diff --git a/packages/core/model/raw-inbound-event.ts b/packages/core/model/raw-inbound-event.ts index 0d2ff12..1949d54 100644 --- a/packages/core/model/raw-inbound-event.ts +++ b/packages/core/model/raw-inbound-event.ts @@ -13,6 +13,7 @@ export type RawInboundEvent = Readonly<{ threadOwnerMessage: boolean; threadParticipantBotCount: number; isTopLevel: boolean; + hasAnyMention?: boolean; mentionedBot: boolean; activeThread: boolean; rawText: string; diff --git a/packages/ims/discord/client.ts b/packages/ims/discord/client.ts index d18c59c..55ce908 100644 --- a/packages/ims/discord/client.ts +++ b/packages/ims/discord/client.ts @@ -376,11 +376,6 @@ function isBotMentioned(message: any, botUserId: string): boolean { return content.includes(`<@${botUserId}>`) || content.includes(`<@!${botUserId}>`); } -function shouldDropForOtherMentions(message: any, isCurrentBotMentioned: boolean): boolean { - const mentionedUsers = Array.from(message?.mentions?.users?.values?.() ?? []); - return mentionedUsers.length > 0 && !isCurrentBotMentioned; -} - async function renameDiscordThread( channelId: string, threadId: string, @@ -470,19 +465,7 @@ async function startDiscordRuntimeInternal(reason: string): Promise { const threadId = message.channel.id; const text = message.content.trim(); const mentioned = isBotMentioned(message, client.user.id); - if (shouldDropForOtherMentions(message, mentioned)) { - log.debug(formatIncomingDropMessage("not_mentioned_and_inactive"), { - platform: "discord", - channelId: parentId, - threadId, - messageId: message.id, - isTopLevel: false, - mentioned, - activeThread: false, - reason: "mentioned_other_bot", - }); - return; - } + const hasAnyMention = (message?.mentions?.users?.size ?? 0) > 0; if (await maybeHandleLauncherCommand({ text, message, @@ -507,6 +490,7 @@ async function startDiscordRuntimeInternal(reason: string): Promise { threadOwnerMessage: threadSession?.threadOwnerUserId === message.author.id, threadParticipantBotCount: getThreadParticipantBotIds(parentId, threadId).length, isTopLevel: false, + hasAnyMention, mentionedBot: mentioned, activeThread: active, rawText: text, @@ -578,8 +562,9 @@ async function startDiscordRuntimeInternal(reason: string): Promise { threadOwnerMessage: true, threadParticipantBotCount: getThreadParticipantBotIds(parentId, thread.id).length, isTopLevel: false, + hasAnyMention: true, mentionedBot: true, - activeThread: false, + activeThread: false, rawText: message.content, normalizedText: topLevelText, receivedAtMs: Date.now(), diff --git a/packages/ims/lark/client.ts b/packages/ims/lark/client.ts index b9482ee..76639d9 100644 --- a/packages/ims/lark/client.ts +++ b/packages/ims/lark/client.ts @@ -678,10 +678,6 @@ function isBotMentionedInText(rawText: string, botOpenId: string): boolean { return pattern.test(rawText); } -function shouldDropForOtherMentions(mentions: string[], isCurrentBotMentioned: boolean): boolean { - return mentions.length > 0 && !isCurrentBotMentioned; -} - type LarkIncomingEnvelope = { type?: string; challenge?: string; @@ -1090,17 +1086,7 @@ async function processLarkIncomingEvent(event: LarkIncomingEvent, processorAppId const isMentioned = botOpenId ? (mentions.includes(botOpenId) || isBotMentionedInText(rawText, botOpenId)) : false; - if (shouldDropForOtherMentions(mentions, isMentioned)) { - logLarkEvent("Lark inbound ignored: message mentions another target", { - channelId, - threadId, - messageId, - mentionCount: mentions.length, - isMentioned, - reason: "mentioned_other_target", - }); - return; - } + const hasAnyMention = mentions.length > 0; const active = isThreadActive(channelId, threadId, processorId); const threadSession = loadSession(channelId, threadId); const text = stripLarkMentionMarkup(rawText); @@ -1117,6 +1103,7 @@ async function processLarkIncomingEvent(event: LarkIncomingEvent, processorAppId threadOwnerMessage: threadSession?.threadOwnerUserId === senderOpenId, threadParticipantBotCount: getThreadParticipantBotIds(channelId, threadId).length, isTopLevel: topLevelMessage, + hasAnyMention, mentionedBot: isMentioned, activeThread: active, rawText, diff --git a/packages/ims/shared/inbound-policy.test.ts b/packages/ims/shared/inbound-policy.test.ts new file mode 100644 index 0000000..ef0c8f0 --- /dev/null +++ b/packages/ims/shared/inbound-policy.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from "bun:test"; +import { defaultInboundPolicy } from "./inbound-policy"; + +describe("defaultInboundPolicy", () => { + it("drops thread messages that mention another target", () => { + const decision = defaultInboundPolicy({ + selfMessage: false, + threadOwnerMessage: true, + threadParticipantBotCount: 2, + isTopLevel: false, + hasAnyMention: true, + mentionedBot: false, + activeThread: true, + normalizedText: "<@other> handle this", + }); + + expect(decision).toEqual({ kind: "ignore", reason: "not_mentioned_and_inactive" }); + }); + + it("keeps active-thread owner follow-ups without mentions", () => { + const decision = defaultInboundPolicy({ + selfMessage: false, + threadOwnerMessage: true, + threadParticipantBotCount: 2, + isTopLevel: false, + hasAnyMention: false, + mentionedBot: false, + activeThread: true, + normalizedText: "continue", + }); + + expect(decision).toEqual({ kind: "message", text: "continue" }); + }); +}); diff --git a/packages/ims/shared/inbound-policy.ts b/packages/ims/shared/inbound-policy.ts index ed0c614..d0876b0 100644 --- a/packages/ims/shared/inbound-policy.ts +++ b/packages/ims/shared/inbound-policy.ts @@ -5,6 +5,7 @@ export function defaultInboundPolicy(params: { threadOwnerMessage: boolean; threadParticipantBotCount: number; isTopLevel: boolean; + hasAnyMention: boolean; mentionedBot: boolean; activeThread: boolean; normalizedText: string; @@ -14,6 +15,10 @@ export function defaultInboundPolicy(params: { return { kind: "ignore", reason: "self_message" }; } + if (!params.isTopLevel && params.hasAnyMention && !params.mentionedBot) { + return { kind: "ignore", reason: "not_mentioned_and_inactive" }; + } + if (!params.isTopLevel && !params.mentionedBot) { if (!params.activeThread) { return { kind: "ignore", reason: "not_mentioned_and_inactive" }; diff --git a/packages/ims/slack/message-router.ts b/packages/ims/slack/message-router.ts index 11fd68a..eadd326 100644 --- a/packages/ims/slack/message-router.ts +++ b/packages/ims/slack/message-router.ts @@ -118,15 +118,6 @@ function extractIncomingMessageData(message: any): IncomingMessageData | null { }; } -function shouldDropForOtherMentions(text: string, isMention: boolean): boolean { - return extractMentionedUserIds(text).length > 0 && !isMention; -} - -function tokenLast6(token?: string): string | undefined { - if (!token) return undefined; - return token.slice(-6); -} - async function maybeRefreshWorkspaceForMention(params: { deps: RouterDeps; channelId: string; @@ -275,6 +266,7 @@ export function registerSlackMessageRouter(deps: RouterDeps): void { || (Boolean(identity.botId) && (messageBotId === identity.botId || messageBotProfileId === identity.botId)); const mentionedUserIds = extractMentionedUserIds(text); + const hasAnyMention = mentionedUserIds.length > 0; const isMention = currentBotUserId ? mentionedUserIds.includes(currentBotUserId) : false; const cleanText = stripBotMention(text, currentBotUserId); logSlackTrace("Slack mention parse", { @@ -313,6 +305,7 @@ export function registerSlackMessageRouter(deps: RouterDeps): void { threadOwnerMessage, threadParticipantBotCount, isTopLevel, + hasAnyMention, mentionedBot: isMention, activeThread: threadActive, rawText: text, @@ -347,20 +340,6 @@ export function registerSlackMessageRouter(deps: RouterDeps): void { }); } - if (shouldDropForOtherMentions(text, isMention)) { - log.info("[DROP] Mentions other user", { - channelId, - threadId, - messageId, - imName: workspaceAuth?.workspaceName ?? deps.getChannelWorkspaceName(channelId) ?? "unknown", - botTokenLast6: tokenLast6(workspaceAuth?.botToken), - botUserId: currentBotUserId || "unknown", - mentionedUserIds, - isMention, - }); - return; - } - if (await maybeHandleLauncherCommand({ deps, cleanText, diff --git a/packages/ims/slack/slack-inbound-adapter.ts b/packages/ims/slack/slack-inbound-adapter.ts index 25ae8cc..1746af0 100644 --- a/packages/ims/slack/slack-inbound-adapter.ts +++ b/packages/ims/slack/slack-inbound-adapter.ts @@ -10,6 +10,7 @@ export class SlackInboundAdapter implements InboundAdapter { threadOwnerMessage: event.threadOwnerMessage, threadParticipantBotCount: event.threadParticipantBotCount, isTopLevel: event.isTopLevel, + hasAnyMention: event.hasAnyMention ?? event.mentionedBot, mentionedBot: event.mentionedBot, activeThread: event.activeThread, normalizedText: event.normalizedText, From a8859cea3cd9a7a718ac125ea5fedc736b5019fc Mon Sep 17 00:00:00 2001 From: LIU9293 Date: Sat, 28 Feb 2026 04:30:03 +0000 Subject: [PATCH 4/5] refactor: remove unused thread participant bot count --- packages/core/kernel/runtime-facade.ts | 4 ---- packages/core/model/raw-inbound-event.ts | 1 - packages/core/test/runtime-e2e.test.ts | 4 ---- packages/core/test/runtime-resilience-e2e.test.ts | 1 - packages/ims/discord/client.ts | 15 ++++++--------- packages/ims/lark/client.ts | 2 -- packages/ims/shared/inbound-policy.test.ts | 2 -- packages/ims/shared/inbound-policy.ts | 1 - packages/ims/slack/client.ts | 2 -- packages/ims/slack/message-router.test.ts | 2 -- packages/ims/slack/message-router.ts | 4 ---- packages/ims/slack/slack-inbound-adapter.ts | 1 - 12 files changed, 6 insertions(+), 33 deletions(-) diff --git a/packages/core/kernel/runtime-facade.ts b/packages/core/kernel/runtime-facade.ts index afeed6e..efa0c8b 100644 --- a/packages/core/kernel/runtime-facade.ts +++ b/packages/core/kernel/runtime-facade.ts @@ -84,7 +84,6 @@ export class KernelRuntimeFacade { evaluate: (event) => defaultInboundPolicy({ selfMessage: event.selfMessage, threadOwnerMessage: event.threadOwnerMessage, - threadParticipantBotCount: event.threadParticipantBotCount, isTopLevel: event.isTopLevel, hasAnyMention: event.hasAnyMention ?? event.mentionedBot, mentionedBot: event.mentionedBot, @@ -105,7 +104,6 @@ export class KernelRuntimeFacade { const decision = defaultInboundPolicy({ selfMessage: event.selfMessage, threadOwnerMessage: event.threadOwnerMessage, - threadParticipantBotCount: event.threadParticipantBotCount, isTopLevel: event.isTopLevel, hasAnyMention: event.hasAnyMention ?? event.mentionedBot, mentionedBot: event.mentionedBot, @@ -165,7 +163,6 @@ export class KernelRuntimeFacade { userId, selfMessage: false, threadOwnerMessage: true, - threadParticipantBotCount: 1, isTopLevel: false, hasAnyMention: false, mentionedBot: true, @@ -270,7 +267,6 @@ export class KernelRuntimeFacade { userId: context.userId, selfMessage: false, threadOwnerMessage: true, - threadParticipantBotCount: 1, isTopLevel: false, hasAnyMention: false, mentionedBot: true, diff --git a/packages/core/model/raw-inbound-event.ts b/packages/core/model/raw-inbound-event.ts index 1949d54..0fe95be 100644 --- a/packages/core/model/raw-inbound-event.ts +++ b/packages/core/model/raw-inbound-event.ts @@ -11,7 +11,6 @@ export type RawInboundEvent = Readonly<{ userId: string; selfMessage: boolean; threadOwnerMessage: boolean; - threadParticipantBotCount: number; isTopLevel: boolean; hasAnyMention?: boolean; mentionedBot: boolean; diff --git a/packages/core/test/runtime-e2e.test.ts b/packages/core/test/runtime-e2e.test.ts index 9f39035..7bc9959 100644 --- a/packages/core/test/runtime-e2e.test.ts +++ b/packages/core/test/runtime-e2e.test.ts @@ -73,7 +73,6 @@ function toInboundEvent(params: { userId: params.userId, selfMessage: false, threadOwnerMessage: true, - threadParticipantBotCount: 1, isTopLevel: params.isTopLevel ?? false, mentionedBot: params.mentionedBot ?? true, activeThread: params.activeThread ?? true, @@ -319,7 +318,6 @@ describe("core runtime e2e", () => { userId: "UE2E-dis", selfMessage: false, threadOwnerMessage: true, - threadParticipantBotCount: 1, isTopLevel: false, mentionedBot: true, activeThread: true, @@ -358,7 +356,6 @@ describe("core runtime e2e", () => { userId: "UE2E-lark", selfMessage: false, threadOwnerMessage: true, - threadParticipantBotCount: 1, isTopLevel: true, mentionedBot: false, activeThread: false, @@ -378,7 +375,6 @@ describe("core runtime e2e", () => { userId: "UE2E-lark", selfMessage: false, threadOwnerMessage: true, - threadParticipantBotCount: 1, isTopLevel: false, mentionedBot: true, activeThread: true, diff --git a/packages/core/test/runtime-resilience-e2e.test.ts b/packages/core/test/runtime-resilience-e2e.test.ts index b1f0df0..6704f26 100644 --- a/packages/core/test/runtime-resilience-e2e.test.ts +++ b/packages/core/test/runtime-resilience-e2e.test.ts @@ -146,7 +146,6 @@ function toInboundEvent(params: { userId: params.userId, selfMessage: false, threadOwnerMessage: true, - threadParticipantBotCount: 1, isTopLevel: false, mentionedBot: true, activeThread: true, diff --git a/packages/ims/discord/client.ts b/packages/ims/discord/client.ts index 55ce908..11f3e66 100644 --- a/packages/ims/discord/client.ts +++ b/packages/ims/discord/client.ts @@ -15,7 +15,6 @@ import { } from "@/config"; import { findReplyThreadIdByStatusMessageTs } from "@/config/local/sessions"; import { - getThreadParticipantBotIds, isThreadActive, loadSession, markThreadActive, @@ -488,7 +487,6 @@ async function startDiscordRuntimeInternal(reason: string): Promise { userId: message.author.id, selfMessage: false, threadOwnerMessage: threadSession?.threadOwnerUserId === message.author.id, - threadParticipantBotCount: getThreadParticipantBotIds(parentId, threadId).length, isTopLevel: false, hasAnyMention, mentionedBot: mentioned, @@ -556,14 +554,13 @@ async function startDiscordRuntimeInternal(reason: string): Promise { rawChannelId: parentId, threadId: thread.id, replyThreadId: thread.id, - messageId: message.id, - userId: message.author.id, - selfMessage: false, - threadOwnerMessage: true, - threadParticipantBotCount: getThreadParticipantBotIds(parentId, thread.id).length, - isTopLevel: false, + messageId: message.id, + userId: message.author.id, + selfMessage: false, + threadOwnerMessage: true, + isTopLevel: false, hasAnyMention: true, - mentionedBot: true, + mentionedBot: true, activeThread: false, rawText: message.content, normalizedText: topLevelText, diff --git a/packages/ims/lark/client.ts b/packages/ims/lark/client.ts index 76639d9..8dec6ca 100644 --- a/packages/ims/lark/client.ts +++ b/packages/ims/lark/client.ts @@ -20,7 +20,6 @@ import { } from "@/config"; import { findReplyThreadIdByStatusMessageTs } from "@/config/local/sessions"; import { - getThreadParticipantBotIds, isThreadActive, loadSession, markThreadActive, @@ -1101,7 +1100,6 @@ async function processLarkIncomingEvent(event: LarkIncomingEvent, processorAppId userId: senderOpenId, selfMessage: isSelfMessage, threadOwnerMessage: threadSession?.threadOwnerUserId === senderOpenId, - threadParticipantBotCount: getThreadParticipantBotIds(channelId, threadId).length, isTopLevel: topLevelMessage, hasAnyMention, mentionedBot: isMentioned, diff --git a/packages/ims/shared/inbound-policy.test.ts b/packages/ims/shared/inbound-policy.test.ts index ef0c8f0..95e3815 100644 --- a/packages/ims/shared/inbound-policy.test.ts +++ b/packages/ims/shared/inbound-policy.test.ts @@ -6,7 +6,6 @@ describe("defaultInboundPolicy", () => { const decision = defaultInboundPolicy({ selfMessage: false, threadOwnerMessage: true, - threadParticipantBotCount: 2, isTopLevel: false, hasAnyMention: true, mentionedBot: false, @@ -21,7 +20,6 @@ describe("defaultInboundPolicy", () => { const decision = defaultInboundPolicy({ selfMessage: false, threadOwnerMessage: true, - threadParticipantBotCount: 2, isTopLevel: false, hasAnyMention: false, mentionedBot: false, diff --git a/packages/ims/shared/inbound-policy.ts b/packages/ims/shared/inbound-policy.ts index d0876b0..846a2f2 100644 --- a/packages/ims/shared/inbound-policy.ts +++ b/packages/ims/shared/inbound-policy.ts @@ -3,7 +3,6 @@ import type { InboundDecision } from "@/core/model/inbound-decision"; export function defaultInboundPolicy(params: { selfMessage: boolean; threadOwnerMessage: boolean; - threadParticipantBotCount: number; isTopLevel: boolean; hasAnyMention: boolean; mentionedBot: boolean; diff --git a/packages/ims/slack/client.ts b/packages/ims/slack/client.ts index 7eea353..4027580 100644 --- a/packages/ims/slack/client.ts +++ b/packages/ims/slack/client.ts @@ -9,7 +9,6 @@ import { } from "@/config"; import { markdownToSlack, splitForSlack, truncateForSlack } from "./formatter"; import { - getThreadParticipantBotIds, isThreadActive, loadSession, } from "@/config/local/sessions"; @@ -482,7 +481,6 @@ export function setupMessageHandlers(): void { const session = loadSession(channelId, threadId); return session?.threadOwnerUserId === userId; }, - getThreadParticipantBotCount: (channelId, threadId) => getThreadParticipantBotIds(channelId, threadId).length, isThreadActive, postGeneralSettingsLauncher: postSlackGeneralSettingsLauncher, describeSettingsIssues: describeSlackSettingsIssues, diff --git a/packages/ims/slack/message-router.test.ts b/packages/ims/slack/message-router.test.ts index b100566..e44b04e 100644 --- a/packages/ims/slack/message-router.test.ts +++ b/packages/ims/slack/message-router.test.ts @@ -15,7 +15,6 @@ function createDeps(overrides: Partial {}, setChannelWorkspaceAuth: () => {}, isThreadOwner: () => false, - getThreadParticipantBotCount: () => 1, isThreadActive: () => false, postGeneralSettingsLauncher: async () => {}, describeSettingsIssues: () => [], @@ -243,7 +242,6 @@ describe("registerSlackMessageRouter", () => { }, isThreadActive: () => true, isThreadOwner: () => true, - getThreadParticipantBotCount: () => 2, handleInboundEvent, }); diff --git a/packages/ims/slack/message-router.ts b/packages/ims/slack/message-router.ts index eadd326..2278bee 100644 --- a/packages/ims/slack/message-router.ts +++ b/packages/ims/slack/message-router.ts @@ -26,7 +26,6 @@ type RouterDeps = { auth: { workspaceId?: string; workspaceName?: string; botToken?: string; [key: string]: unknown } | undefined ) => void; isThreadOwner: (channelId: string, threadId: string, userId: string) => boolean; - getThreadParticipantBotCount: (channelId: string, threadId: string) => number; isThreadActive: (channelId: string, threadId: string, botId: string) => boolean; postGeneralSettingsLauncher: (channelId: string, userId: string, client: any) => Promise; describeSettingsIssues: (channelId: string) => string[]; @@ -290,7 +289,6 @@ export function registerSlackMessageRouter(deps: RouterDeps): void { const runtimeBotId = contextBotToken ?? workspaceAuth?.botToken ?? "default"; const isTopLevel = threadId === messageId; const threadOwnerMessage = deps.isThreadOwner(channelId, threadId, userId); - const threadParticipantBotCount = deps.getThreadParticipantBotCount(channelId, threadId); const threadActive = deps.isThreadActive(channelId, threadId, runtimeBotId); const inboundEvent: RawInboundEvent = { platform: "slack", @@ -303,7 +301,6 @@ export function registerSlackMessageRouter(deps: RouterDeps): void { userId, selfMessage, threadOwnerMessage, - threadParticipantBotCount, isTopLevel, hasAnyMention, mentionedBot: isMention, @@ -321,7 +318,6 @@ export function registerSlackMessageRouter(deps: RouterDeps): void { mentionedUserIds, isMention, threadOwnerMessage, - threadParticipantBotCount, threadActive, flowType: flowResult.type, flowReason: flowResult.type === "ignore" ? flowResult.reason : undefined, diff --git a/packages/ims/slack/slack-inbound-adapter.ts b/packages/ims/slack/slack-inbound-adapter.ts index 1746af0..eb3cebd 100644 --- a/packages/ims/slack/slack-inbound-adapter.ts +++ b/packages/ims/slack/slack-inbound-adapter.ts @@ -8,7 +8,6 @@ export class SlackInboundAdapter implements InboundAdapter { return defaultInboundPolicy({ selfMessage: event.selfMessage, threadOwnerMessage: event.threadOwnerMessage, - threadParticipantBotCount: event.threadParticipantBotCount, isTopLevel: event.isTopLevel, hasAnyMention: event.hasAnyMention ?? event.mentionedBot, mentionedBot: event.mentionedBot, From b331c29641ba321e4073e64082f8e7f09a2925e7 Mon Sep 17 00:00:00 2001 From: LIU9293 Date: Sat, 28 Feb 2026 04:32:46 +0000 Subject: [PATCH 5/5] chore: bump version to 0.1.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f26b60a..03a1e05 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ode", - "version": "0.1.16", + "version": "0.1.17", "description": "Coding anywhere with your coding agents connected", "module": "packages/core/index.ts", "type": "module",