hermes - 💡(How to fix) Fix Feature Request: Support Card JSON 2.0 Tables in Feishu Adapter

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Fix Action

Fix / Workaround

  • Patch location: gateway/platforms/feishu.py
    • New function: _build_markdown_card_payload() (after _build_markdown_post_payload())
    • Modified: _build_outbound_payload() — table branch now returns "interactive" + Card payload
  • Regex that triggers the new path: _MARKDOWN_TABLE_RE = re.compile(r"^\|.*\|\n\|[-|: ]+\|", re.MULTILINE)

Code Example

# Current behavior (feishu.py ~line 4138):
if _MARKDOWN_TABLE_RE.search(content):
    text_payload = {"text": content}
    return "text", json.dumps(text_payload, ensure_ascii=False)  # ← tables destroyed

---

feishu:
  table_format: card   # default: "text" (current behavior for backward compat)
RAW_BUFFERClick to expand / collapse

Feature Request: Support Card JSON 2.0 Tables in Feishu Adapter

Hermes version: latest (source: gateway/platforms/feishu.py)


Problem

Feishu has two outbound message formats:

  1. post — rich text with md tag; but the md renderer does not support tables. When markdown table content is sent as post, the message renders blank on the client.

  2. interactive (Card JSON 2.0) — full Card component model including <table> with grid lines, column headers, lark_md data type, etc.

Currently, FeishuAdapter._build_outbound_payload() detects markdown tables via _MARKDOWN_TABLE_RE and forces them to plain-text mode (msg_type="text"), which destroys all formatting.

# Current behavior (feishu.py ~line 4138):
if _MARKDOWN_TABLE_RE.search(content):
    text_payload = {"text": content}
    return "text", json.dumps(text_payload, ensure_ascii=False)  # ← tables destroyed

Proposed Solution

Add a _build_markdown_card_payload() function that parses markdown (table + non-table sections) and emits a Card JSON 2.0 payload. When a markdown table is detected, return msg_type="interactive" instead of "text".

Key design decisions:

  • State machine with IDLE | IN_TABLE | TABLE_BODY states correctly separates plain-text runs from table sections
  • Mixed content (prose + tables + prose) is handled by flushing plain text before entering table mode and carrying plain lines across state transitions
  • Table structure uses columns[].data_type: {name: "lark_md"} so cell content supports inline markdown (bold, links, etc.)
  • Header style is template: "blue" with a fixed title "📊 数据概览"; can be made configurable
  • Fallback for empty content returns a valid empty Card

Working Implementation

A reference implementation has been tested against:

  • ✅ Pure text (no tables) → markdown element in Card body
  • ✅ Standard markdown table (header + separator + body rows) → table element with correct columns + rows
  • ✅ Single-row table (no separator) → table with header-only, zero data rows
  • ✅ Mixed prose + table + prose → correct element ordering: markdown, table, markdown
  • ✅ Two consecutive tables → two table elements in order
  • ✅ Empty content → valid empty Card

Relevant Code

  • Patch location: gateway/platforms/feishu.py
    • New function: _build_markdown_card_payload() (after _build_markdown_post_payload())
    • Modified: _build_outbound_payload() — table branch now returns "interactive" + Card payload
  • Regex that triggers the new path: _MARKDOWN_TABLE_RE = re.compile(r"^\|.*\|\n\|[-|: ]+\|", re.MULTILINE)

Suggested Configuration (optional future work)

A config flag would allow users to choose:

feishu:
  table_format: card   # default: "text" (current behavior for backward compat)

This would let users opt-in to Card tables without breaking any existing workflows that depend on plain-text table output.


Labels: enhancement, platform/feishu, platform/messaging

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING