feat(feishu): render markdown tables as native Card JSON 2.0 table components#40445
Open
highland0971 wants to merge 2 commits into
Open
feat(feishu): render markdown tables as native Card JSON 2.0 table components#40445highland0971 wants to merge 2 commits into
highland0971 wants to merge 2 commits into
Conversation
Routes GFM table content to Feishu Card JSON 2.0 interactive cards with native `table` components instead of degrading to plain text. Key features: - Native table component rendering (tag:table with header_style) - Conservative routing: only table content → interactive card, non-table content keeps post/text path (zero regression) - Card splitting: max 5 tables per card per Feishu API docs, auto-splits into multiple cards with paragraph-boundary awareness - Triple fallback: send() exception + response + edit_message + _feishu_send_with_retry all cover interactive→text degradation - page_size=5 per Feishu official docs ([1,10] range) Verified: 229 tests pass (24 new + 205 existing, zero regression). Deployed and E2E-tested on production Feishu workspace. Combines the best of NousResearch#33310 (card splitting framework) and NousResearch#38453 (native table parsing), avoiding the pitfalls of both: - NousResearch#33310's markdown-table rendering → native table components - NousResearch#38453's aggressive all-interactive routing → conservative routing
tonydwb
reviewed
Jun 6, 2026
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Comment — New integration behavior
Adds Feishu markdown table rendering as native Card JSON 2.0 table components (228 additions, 44 deletions). This changes how markdown tables are serialized in the Feishu gateway.
Observations
- 44 deletions suggest table rendering logic was restructured, not just added to
- The Card JSON 2.0 conversion appears to be a new mapping layer
Suggestions for formal review
- Add a test with a representative markdown table (including edge cases: empty cells, colspan, rowspan) and assert the generated Card JSON structure
- Verify that tables previously rendered via the old path still look correct in Feishu
- Document the Card JSON 2.0 schema differences from previous versions
Once edge-case tests are confirmed, this should be ready for APPROVE.
Reviewed by Hermes Agent
…JSON 2.0 schema docs Addresses review feedback from tonydwb on PR NousResearch#40445: 1. Edge case tests (empty cells, markdown formatting, column mismatch, wide tables, header-only tables, non-table pipe lines, empty content) 2. Regression tests (plain text path unchanged, markdown hints still use post type, Card JSON conforms to Feishu schema) 3. Card JSON 2.0 schema documentation (v1.0 vs v2.0 differences, table component spec, wide_screen_mode, data_type: markdown)
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
This PR routes GFM markdown table content to Feishu Card JSON 2.0 interactive cards with native
tablecomponents (tag: "table"), replacing the current behavior that force-degrades ALL table-bearing messages to plain text.Problem
Feishu post-type
mdelements do not render markdown tables — the message appears blank. The current fix (#20275) force-degrades the ENTIRE message to plain text (msg_type="text"), losing all formatting (headings, bold, code blocks).Solution
Three-layer architecture combining the best of existing community PRs:
tablecomponent (columns, rows, header_style, page_size=5)Key design decisions
tag:markdownelements, this PR parses GFM tables into Feishu's nativetag:tablecomponent with proper header styling (grey background, bold).Changes
gateway/platforms/feishu.py(~310 lines changed)_parse_markdown_table()— GFM table lines → Feishutablecomponent JSON_split_content_and_tables()— line scanner producing mixed[{md}, {table}, {md}]elements_split_content_by_table_limit()— split by 5-table card limit with paragraph boundary awareness_build_table_card_payload()— build Card JSON 2.0 with mixed elements_build_outbound_payloads()— multi-card expansion for >5 tables_POST_CONTENT_INVALID_REexpanded to match interactive card errorssend()/edit_message()/_feishu_send_with_retry— all extended to coverinteractivemsg_typeTesting
Comparison with existing PRs
Closes #9549. Closes #19035.
Supersedes #33310 and #38453 by combining their strengths while avoiding their weaknesses.