-
-
Notifications
You must be signed in to change notification settings - Fork 54.3k
Description
Problem Description
The renderMode: "card" configuration is not being respected when sending messages through the Feishu outbound adapter (extensions/feishu/src/outbound.ts). This causes markdown tables to be filtered out or not displayed correctly in the Feishu client.
Expected Behavior
When renderMode: "card" is configured, outbound messages should be sent as interactive cards (using sendMarkdownCardFeishu()) which support markdown table rendering via the markdown tag, just like reply messages do.
Actual Behavior
Outbound messages are always sent as post messages (using sendMessageFeishu()) regardless of the renderMode configuration. Post messages use the md tag which does not support markdown tables, causing table content to be filtered out.
Root Cause
The reply-dispatcher.ts correctly uses renderMode to decide between sendMarkdownCardFeishu() and sendMessageFeishu():
// extensions/feishu/src/reply-dispatcher.ts:145-196
const useCard = renderMode === "card" || (renderMode === "auto" && shouldUseCard(text));
if (useCard) {
await sendMarkdownCardFeishu({ ... });
} else {
await sendMessageFeishu({ ... });
}However, outbound.ts always calls sendMessageFeishu() and ignores the renderMode configuration entirely.
Impact
- Inconsistent behavior: Reply messages respect
renderMode, but outbound messages don't - Missing feature: Users cannot enable markdown table support for outbound messages (e.g., via
openclaw message sendor tool calls) - Configuration ignored: Setting
renderMode: "card"has no effect on outbound messages
Steps to Reproduce
- Configure Feishu with
renderMode: "card":{ "channels": { "feishu": { "renderMode": "card", "markdown": { "tables": "off" } } } } - Send a message containing a markdown table:
openclaw message send --channel feishu --to "ou_xxx" "## 商品清单
| 名称 | 数量 | 单价 |
|---|---|---|
| 苹果 | 10 | 3.5元 |
| 香蕉 | 5 | 2.0元 |
3. Observe that the table content is not displayed in the Feishu client (only title and summary text appear)
## Solution
The fix adds `renderMode` checking to `outbound.ts` to match the behavior of `reply-dispatcher.ts`:
```typescript
sendText: async ({ cfg, to, text, accountId }) => {
// Check if card mode is enabled
const accountConfig = accountId
? ((cfg.channels?.feishu as Record<string, unknown>)?.accounts as Record<string, unknown>)?.[accountId] as Record<string, unknown> | undefined
: ((cfg.channels?.feishu as Record<string, unknown>)?.accounts as Record<string, unknown>)?.default as Record<string, unknown> | undefined;
const renderMode = accountConfig?.renderMode ?? (cfg.channels?.feishu as Record<string, unknown>)?.renderMode ?? "auto";
// Use card mode when renderMode is "card" to support markdown tables
if (renderMode === "card") {
const result = await sendMarkdownCardFeishu({ cfg, to, text, accountId: accountId ?? undefined });
return { channel: "feishu", ...result };
}
const result = await sendMessageFeishu({ cfg, to, text, accountId: accountId ?? undefined });
return { channel: "feishu", ...result };
}
Technical Details
Feishu Message Types:
posttype withmdtag: Does NOT support markdown tablesinteractivetype withmarkdowntag: DOES support markdown tables
Functions:
sendMessageFeishu(): Sendsposttype (md tag, no tables)sendMarkdownCardFeishu(): Sendsinteractivetype (markdown tag, supports tables)
Related Configuration
The renderMode option is documented in the config schema (extensions/feishu/src/config-schema.ts:135) and used in reply-dispatcher.ts, but was missing from outbound.ts.
Related Files
extensions/feishu/src/outbound.ts- Fix appliedextensions/feishu/src/reply-dispatcher.ts- Already implements renderMode correctlyextensions/feishu/src/config-schema.ts:135- Config schema definition