Skip to content

feat(gateway/feishu): render markdown tables via interactive card - #35906

Open
eaglewa wants to merge 1 commit into
NousResearch:mainfrom
eaglewa:feat/feishu-render-tables-as-card
Open

feat(gateway/feishu): render markdown tables via interactive card#35906
eaglewa wants to merge 1 commit into
NousResearch:mainfrom
eaglewa:feat/feishu-render-tables-as-card

Conversation

@eaglewa

@eaglewa eaglewa commented May 31, 2026

Copy link
Copy Markdown

Summary

Feishu post / lark_md elements cannot render GFM markdown tables — the
message arrives blank on the client. _build_outbound_payload therefore
downgraded any table content to plain text, losing the table formatting.

The interactive-card markdown component (card schema 2.0) does render
tables, so this routes table content to an interactive card instead. Non-table
content is unchanged:

  • markdown (headings/bold/lists/code) → post (renders fine today)
  • plain text → text
  • table content → interactive card 2.0 markdown (new)

send() falls back to plain text if a card payload is rejected by the API, so
a malformed card can never drop the message.

Tests

tests/gateway/test_feishu_card_rendering.py:

  • table content → interactive card 2.0 markdown (content preserved verbatim)
  • a table embedded in surrounding prose still routes to a card
  • non-table markdown still routes to post (unchanged)
  • plain text stays text (unchanged)

Feishu 'post' / 'lark_md' elements cannot render GFM markdown tables — the
message arrives blank on the client — so `_build_outbound_payload`
previously downgraded any table content to plain text, losing the table.

The interactive-card 'markdown' component (card schema 2.0) does render
tables, so route table content to a card instead. Non-table content is
unchanged (markdown -> post, plain -> text). `send()` falls back to plain
text if the card payload is rejected, so a malformed card never drops the
message.
@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 #12114 (canonical Feishu markdown table rendering PR). This is part of the 70+ PR cluster tracked by #27469. Competing with open PRs #32455, #31038, #23494, and others. Please check #27469 for consolidation status before proceeding.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the focused table-rendering contribution. The underlying issue remains: current main routes detected tables to plain text at plugins/platforms/feishu/adapter.py:4524-4533.

Problems

  • The patch changes gateway/platforms/feishu.py, but 5600105478ffde29d7566b45421b100eaa29c4ef moved the active adapter to plugins/platforms/feishu/adapter.py; this needs a port rather than a direct merge.
  • The new interactive exception fallback does not cover unsuccessful API responses: the adjacent response fallback remains restricted to msg_type == "post" at plugins/platforms/feishu/adapter.py:1924-1936.
  • edit_message() also consumes _build_outbound_payload() (plugins/platforms/feishu/adapter.py:1958), but its fallback is post-only at :1963-1971.

Suggested changes

  • Port the implementation and tests to the bundled plugin path.
  • Cover interactive send exceptions, unsuccessful responses, and edit rejection with plain-text fallback tests.

Automated hermes-sweeper review.

)
except Exception as exc:
if msg_type != "post" or not _POST_CONTENT_INVALID_RE.search(str(exc)):
if msg_type == "interactive":

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This handles exceptions, but the response-based fallback immediately below remains limited to msg_type == "post". If Feishu rejects an interactive card by returning an unsuccessful response rather than raising, send() still returns failure; extend that guard and add coverage for this response path.

@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 13, 2026
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 sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades 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.

4 participants