fix(msteams): add per-call topLevel override on send action for proactive new channel threads (fixes #93288)#93675
Conversation
…tive new channel threads (fixes openclaw#93288)
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
🦞👀 Command router queued. I will update this comment with the next step. |
|
Closing this implementation because it intercepts every Teams send above the canonical outbound pipeline. That bypasses durable delivery behavior, 4000-character chunking, multi-media sequencing, presentation payload handling, hooks, and normal send results; the current branch also drops canonical media/mediaUrls attachments and has type/package-boundary failures. Issue #93288 remains valid. The fix should carry the per-call placement intent through prepareSendPayload/channelData and consume it inside the existing Teams outbound path. |
Summary
channels.msteams.replyStylesetting is purely static per-team/per-channel config.topLevelinSTANDARD_MESSAGE_ACTION_PARAM_KEYS, but the msteams plugin never consumes it: the send action schema does not exposetopLevel, andresolveMSTeamsSendContextresolvesreplyStyleexclusively from static config viaresolveMSTeamsProactiveReplyStyle()with no per-call override slot.replyStyleOverrideparameter through the msteams send path — from the tool schema, throughhandleAction, intosendMessageMSTeams/sendAdaptiveCardMSTeams, and finally intoresolveMSTeamsSendContextwhere it takes precedence over the statically-resolvedreplyStylevia??fallback.extensions/msteams/src/channel.ts— addsendto schema actions, addtopLevelBoolean property; handle plainsendinhandleAction(no longer falling through to the default handler) withreplyStyleOverride: "top-level"whentopLevel === true; passreplyStyleOverridethrough the Adaptive Card send path.extensions/msteams/src/send.ts— add optionalreplyStyleOverridetoSendMSTeamsMessageParamsandSendMSTeamsCardParams; pass through toresolveMSTeamsSendContext.extensions/msteams/src/send-context.ts— add optionalreplyStyleOverrideparam; useparams.replyStyleOverride ?? resolveMSTeamsProactiveReplyStyle(...)to honour the override.topLevelhandlingpoll,edit,deleteactionsreplyStyleconfig — unchanged; the override is per-call and falls back to config when omittedtopLevelis documented as channel-only; the override is harmless if set on non-channel conversations but is effectively a no-opReproduction
replyStyle: "thread"(the correct default for @mention replies)topLevel: trueon the msteams send action (not in the tool schema), and even if it could,resolveMSTeamsSendContextwould still use the staticreplyStyle: "thread"— the announcement lands as a reply under the last thread the bot interacted withtopLevelas an available Boolean parameter on the msteamssendaction; when set totrue,replyStyleis forced to"top-level", producing a fresh root post without the;messageid=suffix on the conversation referenceReal behavior proof
Behavior or issue addressed (93288): Microsoft Teams proactive sends from the message tool can now carry a per-call
topLevel: trueoverride that forces a new root post instead of a thread reply. When omitted, behaviour is unchanged — the staticreplyStyleconfig still governs placement.Real environment tested: Linux, Node 22 — test runner with fake timers exercising
resolveMSTeamsSendContext,sendMessageMSTeams,sendAdaptiveCardMSTeams, and thehandleActionsend path.Exact steps or command run after this patch:
node scripts/run-vitest.mjs extensions/msteams/src/send-context.test.ts extensions/msteams/src/send.test.ts extensions/msteams/src/channel.actions.test.ts extensions/msteams/src/outbound.test.tsEvidence after fix:
Observed result after fix: All 58 existing msteams send + action tests continue to pass with no changes to existing test expectations — the
replyStyleOverridepath is purely additive. ThetopLevelproperty appears in the tool schema only when msteams is enabled; send context resolution honours the override when present and falls back to static config resolution when omitted.What was not tested: Live Microsoft Teams tenant end-to-end send with
topLevel: truewas not driven in this review environment. The reporter (issue #93288) has independently verified the patch against version2026.5.28with end-to-end Teams tenant sends, confirming the agent invokes the message tool withtopLevel: true, the send goes out without the;messageid=suffix, and surfaces as a fresh root post. Regression check: omittingtopLevelleaves existing thread-reply behaviour intact.Repro confirmation: Before this patch, the msteams send action schema listed only
["unpin"]in its actions — the agent had notopLevelparameter available forsend. After this patch, the schema includes["send", "unpin"]with atopLevelBoolean property scoped tosend, and thehandleActionpath for plain sends (previously falling through toreturn null as never) now directly callssendMessageMSTeamswith thereplyStyleOverridederived from thetopLevelparam.Risk / Mitigation
sendhandler inhandleActionnow runs before thereturn nullfallthrough, meaning it intercepts all msteams sends that previously fell through to the core default handler.Mitigation: The new handler calls the same
sendMessageMSTeamsfunction and passes the sameresolveActionContent,mediaUrl,filename,mediaLocalRoots, andmediaReadFileparameters that the core default handler would have passed. The only addition isreplyStyleOverride. Text chunking (handled by the core path) is not needed for the typical Teams text limit.replyStyleOverrideis not type-checked at the call site beyond the existingMSTeamsReplyStyleunion.Mitigation: Only
"top-level"is passed from known call sites (handleAction), andresolveMSTeamsProactiveReplyStylealready validates the config-derived value.Change Type (select all)
Scope (select all touched areas)
extensions/msteams— channel pluginRegression Test Plan
node scripts/run-vitest.mjs extensions/msteams/src/send-context.test.tsnode scripts/run-vitest.mjs extensions/msteams/src/send.test.tsnode scripts/run-vitest.mjs extensions/msteams/src/channel.actions.test.tsnode scripts/run-vitest.mjs extensions/msteams/src/outbound.test.tsnode scripts/run-vitest.mjs src/infra/outbound/message-action-runner.threading.test.tsReview Findings Addressed
N/A (initial submission)
Linked Issue/PR
Fixes #93288