Skip to content

feat(feishu): render markdown tables as CardKit v2 native table components - #48807

Open
vvv-cyber wants to merge 1 commit into
NousResearch:mainfrom
vvv-cyber:feat/feishu-table-cardkit-v2
Open

feat(feishu): render markdown tables as CardKit v2 native table components#48807
vvv-cyber wants to merge 1 commit into
NousResearch:mainfrom
vvv-cyber:feat/feishu-table-cardkit-v2

Conversation

@vvv-cyber

Copy link
Copy Markdown

Problem

Feishu/Lark's post-type md tag does not support markdown table syntax (| col | col |). The current adapter detects markdown tables and forces them to plain text (_MARKDOWN_TABLE_REtext msg_type), losing all table structure. Users see raw pipe-delimited text instead of a formatted table.

Closes #9549

Solution

Detect markdown tables in outbound content and convert them to CardKit v2 interactive cards with native table components, while non-table text renders as markdown elements within the same card.

Changes

gateway/platforms/feishu.py (+177/-9):

  1. _MARKDOWN_TABLE_LINE_RE / _MARKDOWN_TABLE_DIVIDER_RE — table row and separator detection
  2. _parse_markdown_table(text) — splits content into [{"type": "text"/"table", ...}] segments
  3. _build_table_card(headers, rows) — builds CardKit v2 table component (columns + rows dict-list, strips ** bold markers, sets header_style)
  4. _build_interactive_card_with_tables(text) — assembles schema: "2.0" card: table segments → table elements, text segments → markdown elements
  5. _build_outbound_payload() — routes table content to interactive msg_type; non-table content unchanged

tests/gateway/test_feishu.py (+106): 11 unit tests covering table parsing, card structure, bold stripping, row normalization, and mixed text/table content.

Behavior

Input Before After
Markdown with table Plain text (pipe-delimited) CardKit v2 interactive card with native table
Markdown without table post/text (unchanged) post/text (unchanged)
Mixed text + table All plain text Markdown elements + table component in one card

Example CardKit v2 output

```json
{
"schema": "2.0",
"config": {"wide_screen_mode": true},
"body": {
"elements": [
{"tag": "markdown", "content": "Some intro text"},
{
"tag": "table",
"columns": [
{"name": "col_0", "display_name": "Name", "data_type": "text", "width": "auto"},
{"name": "col_1", "display_name": "Age", "data_type": "text", "width": "auto"}
],
"rows": [
{"col_0": "Alice", "col_1": "30"},
{"col_0": "Bob", "col_1": "25"}
],
"header_style": {"bold": true, "text_align": "left", "text_size": "normal"}
}
]
}
}
```

Notes

  • Non-table messages are completely unaffected — no change to the post/text path
  • Bold markers (**, __) in headers/cells are stripped (CardKit v2 text data_type doesn't support markdown syntax; header_style.bold: true handles header emphasis
  • Multiple tables in one message each become separate elements
  • The existing is kept for backward compatibility

Testing

11 passed in 1.51s
  • (5 tests): no-table, simple table, mixed content, bold headers, multiple tables
  • (3 tests): card structure, bold stripping, row normalization
  • (3 tests): no-table returns None, table returns card, mixed content

References

@alt-glitch alt-glitch added type/feature New feature or request comp/gateway Gateway runner, session dispatch, delivery platform/feishu Feishu / Lark adapter P3 Low — cosmetic, nice to have duplicate This issue or pull request already exists labels Jun 19, 2026
@alt-glitch

alt-glitch commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Correction: this PR was updated to the active Feishu plugin-adapter path with shared validated table parsing and rejection fallbacks. It is related to #12114 and #61496, not a duplicate of the retired gateway-path proposal.

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Approved

  • 2 files changed, +283/-9 lines — renders markdown tables as CardKit v2 native table components in Feishu
  • Adds markdown table parser with proper cell alignment; clean feature enhancement

Reviewed by Hermes Agent

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for addressing a real Feishu rendering gap. Current main still routes detected tables to plain text at plugins/platforms/feishu/adapter.py:4524-4534.

Problems

  • The PR targets gateway/platforms/feishu.py, which was renamed to plugins/platforms/feishu/adapter.py by 5600105478ffde29d7566b45421b100eaa29c4ef; the added test imports target the removed module path.
  • The added line matcher recognizes any pipe-delimited line as a table, unlike main's current header-plus-divider detection at plugins/platforms/feishu/adapter.py:158-160. Please avoid converting standalone pipe text into interactive tables.
  • Main's API-rejection fallback is restricted to post messages at plugins/platforms/feishu/adapter.py:1913-1936 and :1963-1970; the proposed interactive path needs an equivalent tested fallback or a documented fail-closed rationale.

Suggested changes

  • Rebase the implementation concept onto the bundled Feishu plugin path, require a validated GFM divider before table conversion, and cover rejected interactive payload handling for send and edit.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 14, 2026
@vvv-cyber
vvv-cyber force-pushed the feat/feishu-table-cardkit-v2 branch from 2d2729c to ab550ae Compare July 15, 2026 14:31
@vvv-cyber

Copy link
Copy Markdown
Author

Ported the implementation to the bundled Feishu plugin architecture on current main and addressed the automated review:

  • moved active code to plugins/platforms/feishu/adapter.py
  • added a shared, strict GFM header+separator parser
  • preserved table-looking examples inside fenced code blocks
  • added native CardKit v2 table components with mixed markdown/table ordering
  • added send and edit fallbacks from rejected interactive cards to original plain text
  • added focused regression coverage

Verification: 237 passed; Ruff passed.

@alt-glitch alt-glitch added comp/plugins Plugin system and bundled plugins and removed duplicate This issue or pull request already exists comp/gateway Gateway runner, session dispatch, delivery sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Jul 16, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #12114 and #61496. This PR now implements the active plugin-adapter path with shared validated table parsing and rejection fallbacks, so it is no longer a duplicate of the retired gateway-path proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have platform/feishu Feishu / Lark adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feishu] Markdown tables not rendering in Feishu messages

4 participants