From b0ef0e0ba0cbe84a776b565b5752c048584e3898 Mon Sep 17 00:00:00 2001 From: Antigravity Agent Date: Fri, 3 Jul 2026 13:19:53 +0800 Subject: [PATCH] fix(feishu): send markdown tables as post instead of forcing plain text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The _build_outbound_payload method detected markdown tables via _MARKDOWN_TABLE_RE and forced msg_type="text", which rendered tables as raw pipe-delimited text (| col | col |). This is strictly worse than sending as post — Feishu's post md tag now renders tables correctly, and the existing fallback in send_message() already catches post payload rejections and retries as plain text. The table detection regex is still used: it now triggers the post path (same as other markdown hints) instead of the text fallback. Tested with headers, lists, code blocks, tables, links, blockquotes — all render correctly in Feishu client. Refs: #21866, #27469 --- plugins/platforms/feishu/adapter.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/platforms/feishu/adapter.py b/plugins/platforms/feishu/adapter.py index ba18f22292c2..7fc484ba1de0 100644 --- a/plugins/platforms/feishu/adapter.py +++ b/plugins/platforms/feishu/adapter.py @@ -4468,13 +4468,13 @@ def _is_duplicate(self, message_id: str) -> bool: # ========================================================================= def _build_outbound_payload(self, content: str) -> tuple[str, str]: - # Feishu post-type 'md' elements do not render markdown tables; sending - # table content as post causes the message to appear blank on the client. - # Force plain text for anything that looks like a markdown table. - if _MARKDOWN_TABLE_RE.search(content): - text_payload = {"text": content} - return "text", json.dumps(text_payload, ensure_ascii=False) - if _MARKDOWN_HINT_RE.search(content): + # Send markdown content (including tables) as 'post' message type. + # Feishu's post md tag renders standard markdown; tables are also + # rendered correctly when sent via post. The previous workaround that + # forced table content to plain text (msg_type="text") produced raw + # pipe-delimited output which was strictly worse. + # Refs: #21866, #27469 + if _MARKDOWN_HINT_RE.search(content) or _MARKDOWN_TABLE_RE.search(content): return "post", _build_markdown_post_payload(content) text_payload = {"text": content} return "text", json.dumps(text_payload, ensure_ascii=False)