fix(gateway): route Mattermost replies to thread roots - #33470
Conversation
teknium1
left a comment
There was a problem hiding this comment.
Thanks for covering the outbound paths. Current main has already landed most of this routing work in 5a0e0d35b94fefae4ff6463c24f53e348f4679e6 (merged PR #46885), including metadata propagation for text, files, and image batches.
Problems
- The remaining gap is typing:
gateway/run.py:16796passes thread metadata, butplugins/platforms/mattermost/adapter.py:392-395still posts onlychannel_id. - The PR's
adapter.py:313-314unconditionally emitsroot_idwhen metadata hasthread_id, bypassing thereply_modeguard. Current main intentionally gates thread roots in_thread_root_for_sendatadapter.py:169-176. - The stale patch also replaces current
_post_preserving_threadcalls with raw_api_postcalls, which would discard the notify-only broken-root handling atadapter.py:189-215.
Suggested changes
- Salvage only the typing payload change onto current main, using the existing thread-mode-gated resolver and retaining the current delivery-hygiene helpers.
- Add an
reply_mode="off"metadata regression test.
Automated hermes-sweeper review.
| payload["root_id"] = resolved_root | ||
| # Mattermost requires root_id to be the thread root post, not a | ||
| # nested reply. Gateway callers pass that root in metadata. | ||
| if isinstance(metadata, dict) and metadata.get("thread_id"): |
There was a problem hiding this comment.
metadata.thread_id must remain subject to reply_mode == "thread". As written, this emits root_id even when the configured reply mode is off; current main's _thread_root_for_send deliberately gates that behavior.
| elif reply_to and self._reply_mode == "thread": | ||
| payload["root_id"] = await self._resolve_root_id(reply_to) | ||
|
|
||
| data = await self._api_post("posts", payload) |
There was a problem hiding this comment.
Do not replace the current _post_preserving_thread path with raw _api_post when rebasing. Main now preserves a notify-only fallback for confirmed broken thread roots; salvage the typing change without removing that later delivery-hygiene behavior.
What does this PR do?
Fixes Mattermost thread routing for outbound replies and attachments.
Mattermost requires
root_idto be the root post of a thread. The gateway already passes that root throughmetadata["thread_id"], but the Mattermost adapter did not consistently use it across outbound paths. For replies inside an existing thread,reply_tocan be a nested post id, which can make replies, files, image batches, and typing indicators land outside the intended Mattermost thread or use the wrong post id.This change makes Mattermost outbound delivery prefer
metadata["thread_id"]for thread routing and applies it consistently to text replies, file/image/audio/video uploads, batched image posts, and typing indicators.Related Issue
No issue filed.
Type of Change
Changes Made
plugins/platforms/mattermost/adapter.pymetadata["thread_id"].metadata["thread_id"]overreply_towhen settingroot_id._resolve_root_id(reply_to)behavior forreply_to-only threaded sends.metadatathrough media helper methods.root_idtosend_multiple_images()batch posts.parent_idto thread-scoped typing indicators.tests/gateway/test_mattermost.pyHow to Test
scripts/run_tests.sh tests/gateway/test_mattermost.py.Checklist
Code
Documentation & Housekeeping
cli-config.yaml.exampleupdate N/ACONTRIBUTING.mdorAGENTS.mdupdate N/ATest Notes
scripts/run_tests.sh tests/gateway/test_mattermost.pycould not complete in my local venv because pytest was invoked with--timeoutargs whilepytest-timeoutwas not installed there..venv/bin/python -m pytest tests/gateway/test_mattermost.py -o addopts="-m 'not integration'"->51 passed.