Conversation
… cards Fixes NousResearch#50602 Feishu's post-type 'md' elements do not support table syntax, so table-containing messages were force-sent as plain text, losing all table structure. This commit converts markdown tables to Feishu CardKit v2 table components by: 1. _parse_markdown_table — Parse markdown text into segments of non-table text and structured table data (header + rows). 2. _build_table_card — Convert table data into a CardKit v2 table component with proper column definitions, row data, and header style (bold, left-aligned). 3. _build_interactive_card_with_tables — Assemble a full schema 2.0 interactive card containing markdown text and table elements. 4. _build_outbound_payload — Send as interactive card when tables are detected, falling back to post/text as before. Cell content is stripped of markdown bold markers (**, __) since Feishu table data_type 'text' does not support inline markdown. Table header uses header_style: {bold: true} for visual emphasis.
teknium1
left a comment
There was a problem hiding this comment.
Thanks for targeting a real Feishu formatting gap: current main still routes detected tables to plain text at plugins/platforms/feishu/adapter.py:4524-4530.
Problems
_parse_markdown_table()classifies every outer-pipe line as a table (plugins/platforms/feishu/adapter.py:218) and_flush_table()emits it even when no GFM divider was present (:214). Literal pipe-delimited text will therefore become an interactive card.- The parser has no fenced-code state (
:217-245), so a code sample containing table-shaped lines is converted instead of preserved. _build_outbound_payload()is shared bysend()andedit_message()on current main (:1904,:1958), while the PR always selectsinteractivefor a recognized table (:4548-4550). The change needs an explicit streaming-preview/final-delivery contract and coverage for both paths.- The PR modifies no tests despite adding parsing and delivery behavior.
Suggested changes
- Require a validated header-plus-divider sequence, preserve fenced-code content, and add parser plus send/edit regression tests.
- Define and test how streamed previews transition to the final CardKit payload before routing edits through the new path.
Automated hermes-sweeper review.
| if len(row) > len(headers): | ||
| row[:] = row[:len(headers)] | ||
|
|
||
| segments.append({"type": "table", "headers": headers, "rows": rows}) |
There was a problem hiding this comment.
This emits a table even when table_lines contains only | literal | or otherwise lacks a GFM divider. Require a validated header-plus-divider sequence before appending a table segment; otherwise return these lines to the text segment.
| table_lines = [] | ||
|
|
||
| for line in lines: | ||
| if _MARKDOWN_TABLE_LINE_RE.match(line): |
There was a problem hiding this comment.
Table detection runs inside fenced code because this parser tracks no fence state. Preserve pipe-shaped examples inside ``` fences as text/code rather than turning them into CardKit tables.
| return "text", json.dumps(text_payload, ensure_ascii=False) | ||
| # Check for markdown tables first — if found, send as CardKit v2 interactive card | ||
| # for real table rendering instead of code blocks. | ||
| card = _build_interactive_card_with_tables(content) |
There was a problem hiding this comment.
This helper is also used by edit_message() on current main. Please make the streaming-preview versus final-card behavior explicit and test both call paths before returning an interactive payload for every detected table.
Summary
Fixes #50602
Feishu's post-type
mdelements do not support table syntax, so table-containing messages were force-sent as plain text, losing all table structure. This PR converts markdown tables to Feishu CardKit v2tablecomponents.Changes
_parse_markdown_table— Parse markdown text into segments of non-table text and structured table data (header + rows)._build_table_card— Convert table data into a CardKit v2 table component with proper column definitions, row data, and header style._build_interactive_card_with_tables— Assemble a full schema 2.0 interactive card containing markdown text and table elements._build_outbound_payload— Send asinteractivecard when tables are detected, falling back to post/text as before.Design decisions
**,__) since Feishu tabledata_type: textdoes not support inline markdownheader_style: {bold: true}for visual emphasisTesting
Verified working with Hermes v0.16.0+ plugin architecture. Tested locally with real Feishu messages containing markdown tables — renders as native CardKit table component with proper column alignment and header styling.