fix(msteams): proactive messaging, EADDRINUSE fix, tool status, adaptive cards#23226
Closed
TarogStar wants to merge 9 commits intoopenclaw:mainfrom
Closed
fix(msteams): proactive messaging, EADDRINUSE fix, tool status, adaptive cards#23226TarogStar wants to merge 9 commits intoopenclaw:mainfrom
TarogStar wants to merge 9 commits intoopenclaw:mainfrom
Conversation
820df6f to
443d26a
Compare
…upport - Show interim status messages during tool execution (e.g. "Checking email...") that auto-delete when the real reply starts streaming - Add GET /health endpoint before JWT auth middleware for monitoring - Handle adaptive card action invokes for Copilot Studio responses - Extend MSTeamsTurnContext with optional updateActivity/deleteActivity Co-Authored-By: Claude Opus 4.6 <[email protected]>
The provider promise resolved before expressApp.listen() finished binding, causing the channel manager to interpret it as "provider exited" and trigger auto-restart — which failed with EADDRINUSE. Now awaits the listening callback before resolving, rejects on fatal bind errors (EADDRINUSE/EACCES), logs error codes inline, and calls closeAllConnections() on shutdown to release keep-alive sockets. Also generalises adaptive card queue keys from copilot-studio-specific names to plugin-agnostic ones so any plugin can use the mechanism. Refs: openclaw#22169 Co-Authored-By: Claude Opus 4.6 <[email protected]>
Tests for registerMSTeamsHandlers: - Action.Execute invokes store data in global queue and send invoke response - Synthetic text generated from verb/action with 'approved' fallback - Activity properties restored after routing (even on handler error) - Action.Submit detected via empty text + value object - Normal messages with text bypass Action.Submit path - Multiple invokes accumulate in queue in order Tests for /health endpoint: - Returns correct JSON shape (status, channel, port, startedAt) - Accessible before JWT auth middleware (other routes blocked) Co-Authored-By: Claude Opus 4.6 <[email protected]>
Teams Bot Framework SDK has no native API for bots to react to messages with emoji. Emulate it by sending the configured ack emoji as a temporary status message that gets deleted when the reply starts streaming or a tool status replaces it. Uses resolveAckReaction() and shouldAckReaction() from the plugin SDK for config-consistent behavior with Discord, Slack, and Telegram. Respects messages.ackReaction (emoji), messages.ackReactionScope (gating), and messages.statusReactions.enabled (master switch). Refs: openclaw#11361 Co-Authored-By: Claude Opus 4.6 <[email protected]>
…law#22169) The channel manager interprets a resolved promise as "provider exited" and triggers auto-restart with exponential backoff. For webhook-based providers like msteams, this causes an EADDRINUSE loop because the previous server is still bound to the port. Hold the promise pending until the abort signal fires, matching the contract used by other webhook providers (e.g. BlueBubbles). Co-Authored-By: Claude Opus 4.6 <[email protected]>
…cation Bot Framework revokes the webhook TurnContext proxy after the HTTP request handler returns. With slow local LLMs, the agent response arrives well after that, causing "Cannot perform 'set' on a proxy that has been revoked" errors that silently drop replies. Switch thread replies and adaptive card delivery to use adapter.continueConversation() which creates a fresh context independent of the webhook lifecycle. This matches the pattern already used for top-level replies. For thread replies, set replyToId on outgoing activities to maintain correct threading in channels. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Save the conversation reference in onMembersAdded so proactive messaging (e.g. cron announcements) works even before the user sends their first message. Previously the reference was only stored on the first inbound message. Co-Authored-By: Claude Opus 4.6 <[email protected]>
The onReplyStart typing callback was still using the webhook TurnContext, causing "proxy revoked" errors after the reply was already delivered. Switch to adapter.continueConversation() to match the reply and adaptive card delivery paths. Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Remove dead `context` param from sendMSTeamsMessages and createMSTeamsReplyDispatcher - Extract duplicated globalThis queue insertion into shared pushPendingCardInvoke helper - Add size cap (50) to global invoke queue to prevent unbounded growth - Use fixed synthetic text for adaptive card actions instead of interpolating untrusted input - Handle missing abortSignal in monitor.ts to avoid forever-pending promise - Fix test types for makeTurnContext activity properties Co-Authored-By: Claude Opus 4.6 <[email protected]>
443d26a to
f5034de
Compare
7 tasks
|
This pull request has been automatically marked as stale due to inactivity. |
|
Closing due to inactivity. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
adapter.continueConversation()instead of the short-lived webhook TurnContextChange Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
replyToIdon proactive messagesSecurity Impact (required)
NoNoNo(same Bot Framework API, just via proactive messaging path)NoNoRepro + Verification
Environment
gateway.mode: "local",channels.msteams.blockStreamingCoalesce: { minChars: 300, maxChars: 800, idleMs: 1500 }Steps
Expected
Actual (before fix)
Evidence
Log output after fix (zero errors, clean dispatch):
Before fix: logs showed 5+ EADDRINUSE restart attempts and proxy revocation errors on every reply.
All 165 msteams tests pass.
pnpm build && pnpm checkclean.Human Verification (required)
Compatibility / Migration
YesNoNoFailure Recovery (if this breaks)
extensions/msteams/src/directoryRisks and Mitigations
__openclaw_pending_card_invokes) could grow unbounded if invokes are never consumedOpus 4.6 assisted
Greptile Summary
Refactors MS Teams integration to use proactive messaging for all replies, typing indicators, and adaptive card sends, eliminating proxy revocation errors with slow LLMs (>15s responses). Also fixes EADDRINUSE restart loop by keeping provider promise pending until abort signal fires.
TurnContext(revoked after HTTP request) toadapter.continueConversation()for all outbound operations/healthendpoint for monitoring (accessible before JWT auth)Confidence Score: 4/5
Last reviewed commit: d94f5a4
(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!