fix(msteams): isolate thread sessions, outbound targeting, and attachment resolution#59294
fix(msteams): isolate thread sessions, outbound targeting, and attachment resolution#59294atharva-getboon wants to merge 12 commits intoopenclaw:mainfrom
Conversation
…ion/history/store
Greptile SummaryThis PR fixes cross-thread context bleed in the MS Teams channel by introducing per-thread session keys, thread-scoped history, and outbound Key changes:
Confidence Score: 3/5
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9213f05201
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…ape <> in bot name regex
…read-aware debounce key
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eaee7238d8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…name breaking /slash commands
bd5109a to
35d331d
Compare
There was a problem hiding this comment.
💡 Codex Review
After this change, entry.text can start with preserved mentions (for example @Alice /status), so hasControlCommand(entry.text, cfg) returns false and the message is incorrectly debounced. That lets mention-prefixed slash commands be coalesced with subsequent messages in the debounce window, which can delay or alter command handling compared to the previous non-debounced path. The debounce gate should check entry.commandText (or another mention-stripped form) so command messages still bypass debounce reliably.
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…tion-prefixed slash commands
…olation-58615 # Conflicts: # extensions/msteams/src/inbound.ts # extensions/msteams/src/monitor-handler/inbound-media.test.ts # extensions/msteams/src/monitor-handler/inbound-media.ts # extensions/msteams/src/monitor-handler/message-handler.ts
|
@BradGroux @steipete @vincentkoc PTAL 🙏 |
|
Please don’t spam-ping multiple maintainers at once. Be patient, or join our community Discord for help: https://discord.gg/clawd |
|
I am linking a newly opened follow-up issue here because I think it may be related but not fully covered by #58615. Related issue:
Why I think this PR is relevant but may not be the whole story:
So if this PR fixes:
that is excellent and likely necessary. But I would still recommend verifying one additional negative case before considering this whole class closed:
If the answer is no after this PR, then great, this PR may implicitly cover more than #58615. If not, #66771 may remain as a follow-up bug around old-session reselection / binding / target-session resolution. |
|
Adding production confirmation for this PR. Running OpenClaw v2026.4.21 in a multi-channel MS Teams deployment (11 channels, mix of DMs and threads). Without the thread session isolation this PR introduces, we observe two consistent symptoms:
The combined fix (per-thread session + Happy to test against our deployment if that helps land this. Thanks @atharva-getboon for the work. |
|
Codex review: needs changes before merge. Summary Reproducibility: yes. #58615 gives a concrete two-thread Teams reproduction, and current main still has a code-level reproduction for rapid same-sender messages because debounce and pending-history keys omit the Teams thread id. Next step before merge Security Review findings
Review detailsBest possible solution: Rebase or replace this PR with a narrow MS Teams-only change on current main that preserves shipped Do we have a high-confidence way to reproduce the issue? Yes. #58615 gives a concrete two-thread Teams reproduction, and current main still has a code-level reproduction for rapid same-sender messages because debounce and pending-history keys omit the Teams thread id. Is this the best way to solve the issue? No. The direction is useful, but the patch is stale and its thread-binding gate is not the narrowest maintainable fix because OpenClaw's effective policy supports channel/account overrides and default-enabled behavior. Full review comments:
Overall correctness: patch is incorrect Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 40f2bf395059. |
…re-suffixed bases (openclaw#66771) When the inbound message handler reuses a `route.sessionKey` that was already thread-qualified by a prior turn (e.g. cached resolve-route hit, or the cache-miss return at src/routing/resolve-route.ts:696 whose object reference is then mutated in-place by message-handler.ts:489), naively appending the current thread id compounds into `…:thread:OLD:thread:NEW` and routes the turn to a malformed lane that splits same-thread context across turns. Strip any trailing `:thread:<id>+` segments from the base before delegating to resolveThreadSessionKeys. Thread ids never contain ':' so the segment boundary is unambiguous; the '+' covers pathological doubly-suffixed bases already in caches/persisted sessions from prior runs. This is defense-in-depth at the helper level, complementary to the larger handler refactor in openclaw#59294 (still open since 2026-04-01). Even after that or a routing-cache fix lands, making the helper itself idempotent prevents any future caller hygiene regression from re-introducing the bug. Adds four regression tests under a new "idempotency against pre-suffixed bases" describe block in message-handler.thread-session.test.ts: - already-thread-suffixed base + new thread → single clean suffix - doubly-thread-suffixed (already-malformed) base → collapsed to one - same-thread re-application is a fixed point - stale thread suffix + top-level inbound → bare base Closes openclaw#66771.
Summary
Fixes #58615 — msteams channel threads share the same session key, causing cross-thread context bleed.
resolveThreadSessionKeys(), gated bysession.threadBindings.enabledconfighistoryKeyis now thread-aware sobuildPendingHistoryContextFromMapdoesn't mix channel-level and thread-level historybuildActivity()setsactivity.replyToIdbefore any early returns so proactive sends (text + file attachments via SharePoint/OneDrive) land in the correct threadstripMSTeamsBotMentionTag()strips only the bot's<at>tag — other user mentions are preserved as@Namein agent context. A separatecommandText(all mentions stripped) is used for slash command detection to avoid regressions.toLowerCase()across session key, history key, and conversation store key derivationsreplyToIdwhen thread bindings enabled, preventing cross-thread message mergingAI-Assisted PR 🤖
Test plan
pnpm tsgo) cleanpnpm check) cleanpnpm build) cleanstripMSTeamsBotMentionTag(10 cases)buildActivityreplyToId thread targeting (3 cases)activity.replyToIdland in correct Teams thread🤖 Generated with Claude Code