Skip to content

feat(feishu): send GFM tables via Schema 2.0 interactive card#35781

Open
unstoppablesssss wants to merge 4 commits into
NousResearch:mainfrom
unstoppablesssss:main
Open

feat(feishu): send GFM tables via Schema 2.0 interactive card#35781
unstoppablesssss wants to merge 4 commits into
NousResearch:mainfrom
unstoppablesssss:main

Conversation

@unstoppablesssss

Copy link
Copy Markdown

Problem

Feishu post-type md elements do not render GFM tables. Previously, _build_outbound_payload detected tables and force-downgraded the entire message to plain text, losing all markdown formatting (headings, bold, links, code blocks).

Solution

When GFM tables are detected, send a Schema 2.0 interactive card (msg_type="interactive") instead. The JSON 2.0 tag: markdown component supports CommonMark tables natively, preserving all surrounding formatting.

Changes

  • New _build_interactive_card_payload(content) — builds a Schema 2.0 card with header + body.elements
  • Modified _build_outbound_payload() — returns ("interactive", card_payload) when tables are detected, instead of force-text
  • Long content is split into multiple tag: markdown elements (~4K chars each) with newline-aware breaks

Testing

Verified with uv run python -c '...':

  • _MARKDOWN_TABLE_RE.search(content) matches correctly
  • Card payload has "schema": "2.0" and correct body.elements structure
  • Sent via hermes send to Feishu — table renders natively in Schema 2.0 card
  • Telemetry relay: confirmed via gateway log

Feishu post-type 'md' elements do not render GFM tables. Previously,
_build_outbound_payload detected tables and forced a plain-text fallback,
which lost ALL markdown formatting (headings, bold, links, etc.).

Now _convert_gfm_tables_to_list() runs in send() and edit_message() BEFORE
the outbound payload is built, converting GFM tables to bullet-list items:
- Header row: - **col1** · **col2**
- Data rows:  - **col1** val1 · **col2** val2

Tables inside fenced code blocks are left untouched.
After conversion, _MARKDOWN_TABLE_RE no longer matches, so the message
goes through the normal post (md) pipeline with all formatting preserved.
The post-type 'md' renderer does not support GFM tables. Previously the
adapter detected tables and force-downgraded the whole message to plain
text (losing all formatting).

Now _build_outbound_payload returns msg_type='interactive' with a
Schema 2.0 interactive card payload when GFM tables are detected.
The JSON 2.0 tag:markdown component renders CommonMark tables natively,
preserving surrounding formatting.
@unstoppablesssss unstoppablesssss requested a review from a team May 31, 2026 08:42
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery platform/feishu Feishu / Lark adapter labels May 31, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #33310 (and part of the saturated Feishu markdown rendering cluster: #23861, #32488, #27469, #12114). Same approach: Schema 2.0 interactive card with tag: markdown for GFM tables. Also note: this PR includes unrelated files (state.db, hermes_cli/tools_config.py, web/package-lock.json) that should be removed.

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

Labels

comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have platform/feishu Feishu / Lark adapter type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants