fix(feishu): route markdown tables through post+tag:md, fix streaming edit fallback - #53453
fix(feishu): route markdown tables through post+tag:md, fix streaming edit fallback#53453Zjrua wants to merge 1 commit into
Conversation
…ce-text Feishu's post + tag:md element now renders GFM tables natively. The historic _MARKDOWN_TABLE_RE workaround (commit 8e18d10) force-downgraded the entire message to msg_type: text whenever a table appeared, which stripped formatting from every other markdown element in the same reply and displayed raw pipe-delimited source code. Changes: - Merge table pattern into _MARKDOWN_HINT_RE so tables route to post like all other markdown content. Remove the now-unused _MARKDOWN_TABLE_RE. - Remove the force-text branch in _build_outbound_payload(). - Add text→post fallback in edit_message() for the streaming edge case: when the first chunk is sent as text (no table visible yet) and the final content now routes to text, Feishu rejects the msg_type change on update. Retry as post so the message stays readable. Closes NousResearch#52786, NousResearch#52046, NousResearch#23938, NousResearch#9549, NousResearch#18704 Co-authored-by: WuTianyi <wtyopenclaw@gmail.com>
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved
Feishu markdown table and heading level fixes are well-scoped and targeted. The changes route tables through the post+tag:md path and normalize heading levels, which are common pain points for Feishu message formatting.
Reviewed by Hermes Agent
teknium1
left a comment
There was a problem hiding this comment.
Thanks for isolating the force-text table workaround; the core routing change is supported by current main, where plugins/platforms/feishu/adapter.py:4524-4534 still returns text before markdown detection for _MARKDOWN_TABLE_RE.
Problems
plugins/platforms/feishu/adapter.py:1857in d443e16 only retries when the attempted update istext. The reported stream transition is a previously text message whose final table content is classified aspost; that post update bypasses this new branch. Retrying post after the inverse post-to-text failure does not cover the stated case.- The new fallback test in
tests/gateway/test_feishu.pyin d443e16 uses plain final content and validates text → post retry, not a final table/post update after an earlier text stream message.
Suggested changes
- Preserve the table-routing change, but rework the stream type-transition behavior around the actual text-origin → post-final case and add a regression test for it.
Automated hermes-sweeper review.
| fallback_request = self._build_update_message_request(message_id=message_id, request_body=fallback_body) | ||
| fallback_response = await asyncio.to_thread(self._client.im.v1.message.update, fallback_request) | ||
| result = self._finalize_send_result(fallback_response, "update failed") | ||
| if not result.success and msg_type == "text": |
There was a problem hiding this comment.
This guard covers a post-origin message becoming plain text, but the PR description’s failure is the reverse: a text streaming message whose final table is classified as post. That attempted update has msg_type == "post", so this fallback is skipped; please handle or re-scope that actual transition.
|
Closing this PR — the core table-routing change (removing the The streaming edit fallback (text→post on update rejection) is a separate concern; I'll revisit it if it becomes reproducible on current main. Thanks for the review feedback! |
Bug
Markdown tables in Feishu messages render as raw pipe-delimited source code instead of being rendered as proper tables. When a table appears in a message, the entire message is downgraded to
msg_type: text, stripping all markdown formatting (bold, headings, code blocks, lists) from the same reply.Related issues: #52786, #52046, #23938, #18704, #9549, #21866, #25452
Root cause
Commit
8e18d1031(Apr 2026) added_MARKDOWN_TABLE_REto forcemsg_type: textfor any content containing a markdown table. This was correct at the time — Feishu's postmdelement did not render tables, and sending table content as post caused blank messages.However, Feishu's post +
tag: mdelement now renders GFM tables natively. The workaround is obsolete and actively harmful: it downgrades the entire message to plain text, displaying raw|pipe-delimited source code and stripping all other formatting.Fix
1. Route tables through post (core fix)
Merge the table-detection pattern into
_MARKDOWN_HINT_REso tables are treated like any other markdown content — routed topost+tag: md. Remove the now-unused_MARKDOWN_TABLE_REand its force-text branch in_build_outbound_payload().2. Streaming edit fallback (edge case no other PR handles)
During streaming, the first chunk may not yet contain a table (partial content), so it's sent as
text. When the full content arrives andedit_message()detects the table,_build_outbound_payloadreturnspost. But Feishu does not allow changingmsg_typeon message update, so the edit fails and the message stays as raw markdown source.Added a
text -> postfallback inedit_message(): when a text update fails, retry as post with markdown rendering.Prior work