fix(msteams): detect implicit mentions in thread replies via conversation.id#41108
fix(msteams): detect implicit mentions in thread replies via conversation.id#41108vongohren wants to merge 4 commits intoopenclaw:mainfrom
Conversation
Teams doesn't reliably send replyToId in thread replies. Fall back to the thread root message ID extracted from conversation.id (the ;messageid=XXX suffix) when checking if the bot sent a message in that thread. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…lies The previous commit added conversation.id;messageid= as a fallback for implicit mention detection, but the lookup still failed because the sent-message cache only contained the bot's reply IDs, not the thread root ID that Teams puts in conversation.id. This commit also records the thread root message ID (conversationMessageId) when the bot sends a reply, so subsequent thread replies match correctly. Note: This fix requires ChannelMessage.Read.Group RSC permission in the Teams app manifest for thread replies to reach the bot at all. Tested and verified in production. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Greptile SummaryThis PR fixes implicit mention detection for MS Teams thread replies by adding a fallback that uses the thread-root message ID encoded in Key points:
Confidence Score: 4/5
|
| */ | ||
| function computeImplicitMention(activity: { | ||
| conversation?: { id?: string }; | ||
| replyToId?: string; | ||
| }): boolean { | ||
| const rawConversationId = activity.conversation?.id ?? ""; | ||
| const conversationId = normalizeMSTeamsConversationId(rawConversationId); | ||
| const replyToId = activity.replyToId ?? undefined; | ||
| const threadRootId = extractMSTeamsConversationMessageId(rawConversationId); | ||
| return Boolean( | ||
| conversationId && | ||
| ((replyToId && wasMSTeamsMessageSent(conversationId, replyToId)) || | ||
| (threadRootId && wasMSTeamsMessageSent(conversationId, threadRootId))), | ||
| ); | ||
| } |
There was a problem hiding this comment.
Test helper duplicates production logic instead of exercising it
The computeImplicitMention helper defined here is a re-implementation of the actual production code in message-handler.ts lines 685–693. Because the tests call this local function rather than the real code path, a regression introduced in the production implicitMention block would go completely undetected by these tests — they'd keep passing since the local re-implementation is unchanged.
Consider either:
- Exporting the implicit mention computation as a small, pure utility in
message-handler.ts(or a dedicated helper file) that both the production code and these tests can import directly, or - Testing through a lightweight version of the
handleTeamsMessageentry point using dependency injection/mocks for the debouncer and dispatcher, so the real code is exercised.
As written, these tests are effectively testing the test helper itself rather than the production implementation.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/msteams/src/monitor-handler/message-handler.implicit-mention.test.ts
Line: 26-40
Comment:
**Test helper duplicates production logic instead of exercising it**
The `computeImplicitMention` helper defined here is a re-implementation of the actual production code in `message-handler.ts` lines 685–693. Because the tests call this local function rather than the real code path, a regression introduced in the production `implicitMention` block would go completely undetected by these tests — they'd keep passing since the local re-implementation is unchanged.
Consider either:
- Exporting the implicit mention computation as a small, pure utility in `message-handler.ts` (or a dedicated helper file) that both the production code and these tests can import directly, or
- Testing through a lightweight version of the `handleTeamsMessage` entry point using dependency injection/mocks for the debouncer and dispatcher, so the real code is exercised.
As written, these tests are effectively testing the test helper itself rather than the production implementation.
How can I resolve this? If you propose a fix, please make it concise.Extract the implicit mention computation from message-handler.ts into a dedicated implicit-mention.ts module. Both the production code and the tests now import the same function, so regressions in the logic will be caught by the test suite. Addresses review feedback about test helper duplicating production logic. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
|
Hi @vongohren — thanks for the submission. I’m the new Microsoft Teams maintainer for OpenClaw. Please give me a day or two to work through the open Teams backlog. Also, join the Twitter community for daily MS Teams feedback + updates: https://x.com/i/communities/2031170403607974228 |
Summary
Fixes thread reply implicit mention detection for MS Teams. When
requireMention: true, replying to a bot message in a thread without @mention now correctly bypasses the mention gate.Two changes:
Fallback to
conversation.id;messageid=for implicit mention — Teams doesn't reliably sendreplyToId, but it does encode the thread root message ID inconversation.id. The existingextractMSTeamsConversationMessageId()function already parses this; now it's wired into the implicit mention check.Cache thread root ID on send — The
conversation.id;messageid=points to the thread root (the user's original message), not the bot's reply. So we also record the thread root ID in the sent-message cache when the bot replies, enabling the lookup to succeed.Important: RSC required
This fix also requires
ChannelMessage.Read.GroupRSC permission in the Teams app manifest. Without RSC, Teams doesn't deliver thread replies to the bot webhook at all — the messages never reach OpenClaw. This is a Teams platform limitation documented in MicrosoftDocs/msteams-docs#4530.Test plan
extractMSTeamsConversationMessageId(all pass)Closes #38629
🤖 Generated with Claude Code