Skip to content

feat(feishu): implement markdown message handling and optimization#1604

Merged
zerob13 merged 2 commits into
devfrom
feishu
May 11, 2026
Merged

feat(feishu): implement markdown message handling and optimization#1604
zerob13 merged 2 commits into
devfrom
feishu

Conversation

@zhangmo8
Copy link
Copy Markdown
Collaborator

@zhangmo8 zhangmo8 commented May 11, 2026

before:

668b02a56fc8648aaeaa9945ade90d65

after:

765c4928136a3c1aededc2080e0fa592

Summary by CodeRabbit

  • New Features

    • Feishu messaging now supports markdown-style posts with automatic optimization for improved platform compatibility and readability
    • Ability to send, update, and edit delivered messages
    • Improved handling of large content via intelligent chunking and formatting adjustments
  • Tests

    • Updated test suite to validate markdown-based delivery, update semantics, chunking behavior, and fallback/update scenarios

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 447f05bc-ef6a-495c-9443-3edb2fed3673

📥 Commits

Reviewing files that changed from the base of the PR and between 148a632 and 976d20f.

📒 Files selected for processing (1)
  • src/main/presenter/remoteControlPresenter/feishu/feishuClient.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/presenter/remoteControlPresenter/feishu/feishuClient.ts

📝 Walkthrough

Walkthrough

Adds Feishu markdown delivery: a new markdown optimizer, FeishuClient methods to send/update 'post' markdown messages, FeishuRuntime updated to optimize and use markdown APIs across message flows, and tests adjusted to mock/assert the markdown APIs.

Changes

Feishu Markdown Message Support

Layer / File(s) Summary
Markdown Optimization Utility
src/main/presenter/remoteControlPresenter/feishu/feishuMarkdown.ts
Extracts/restores fenced code blocks, conditionally demotes headings, applies spacing for headings/tables, compresses blank lines, strips unsupported image refs, and exports optimizeMarkdownForFeishu.
FeishuClient Markdown Methods
src/main/presenter/remoteControlPresenter/feishu/feishuClient.ts
Adds createMarkdownPayload helper; sendMarkdown to chunk and send msg_type: 'post' messages (reply-in-thread or new message) and return last message_id; updateMarkdown to update existing messages with post payload.
FeishuRuntime Integration
src/main/presenter/remoteControlPresenter/feishu/feishuRuntime.ts
Imports optimizeMarkdownForFeishu and replaces plain-text sendText/updateText calls with optimized sendMarkdown/updateMarkdown across replies, terminal/timeout/fallback paths, segment synchronization, and outbound action delivery.
Test Harness & Assertions
test/main/presenter/remoteControlPresenter/feishuRuntime.test.ts
Mocks sendMarkdown/updateMarkdown in harness and updates assertions across streaming, chunking, segment ordering, timeout, and error-card tests to verify markdown APIs and negative update cases.

Sequence Diagram(s)

sequenceDiagram
  participant Client as FeishuClient
  participant Runtime as FeishuRuntime
  participant Optimizer as optimizeMarkdownForFeishu
  Runtime->>Optimizer: provide raw text segments
  Optimizer-->>Runtime: return optimized markdown
  Runtime->>Client: sendMarkdown(target, chunk) / updateMarkdown(messageId, chunk)
  Client-->>Runtime: returns message_id or void
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • yyhhyyyyyy

Poem

🐰 Behold! The markdown flows like spring's sweet stream,
Through Feishu's posts we weave a formatting dream—
Bold headings bow, blank lines compress with grace,
Code fences hide, then return to their place,
And every chunk lands tidy in its space. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: implementing markdown message handling and optimization for Feishu, which aligns with the core modifications across feishuClient, feishuMarkdown, feishuRuntime, and tests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feishu

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/presenter/remoteControlPresenter/feishu/feishuRuntime.ts (1)

716-726: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Delete stale chunks before the resend fallback.

When an earlier optimized chunk changes, this branch re-sends the whole segment and replaces messageIds, but the old existing.messageIds are never removed. That leaves stale chunks visible alongside the replacement copy.

♻️ Suggested fix
     ) {
+      for (const messageId of existing.messageIds) {
+        if (messageId) {
+          await this.deps.client.deleteMessage(messageId)
+        }
+      }
+
       const messageIds: Array<string | null> = []
       for (const chunk of nextChunks) {
         const messageId = await this.deps.client.sendMarkdown(target, chunk)
         messageIds.push(messageId ?? null)
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/presenter/remoteControlPresenter/feishu/feishuRuntime.ts` around
lines 716 - 726, The resend branch re-sends nextChunks into a fresh messageIds
array but never removes the old existing.messageIds, leaving stale messages
visible; before re-sending, iterate existing.messageIds and delete each non-null
id (e.g. await this.deps.client.deleteMessage(id)) handling nulls and awaiting
all deletions, then proceed to send chunks with this.deps.client.sendMarkdown
and replace existing.messageIds with the new messageIds. Ensure deletions are
awaited/aggregated (Promise.all) and that you update the stored message id list
after successful resend.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/presenter/remoteControlPresenter/feishu/feishuClient.ts`:
- Around line 32-37: The createMarkdownPayload helper currently returns an
object shaped as { zh_cn: { content: ... } } but must be wrapped in a post
object per Feishu/Lark IM v1 schema; update the createMarkdownPayload function
so it returns JSON.stringify({ post: { zh_cn: { content: [[{ tag: 'md', text }]]
} } }) so sendMarkdown and updateMarkdown receive the correct payload for
msg_type: 'post' (zh_cn.title can remain omitted).

---

Outside diff comments:
In `@src/main/presenter/remoteControlPresenter/feishu/feishuRuntime.ts`:
- Around line 716-726: The resend branch re-sends nextChunks into a fresh
messageIds array but never removes the old existing.messageIds, leaving stale
messages visible; before re-sending, iterate existing.messageIds and delete each
non-null id (e.g. await this.deps.client.deleteMessage(id)) handling nulls and
awaiting all deletions, then proceed to send chunks with
this.deps.client.sendMarkdown and replace existing.messageIds with the new
messageIds. Ensure deletions are awaited/aggregated (Promise.all) and that you
update the stored message id list after successful resend.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6e8bc384-cbe8-491e-a96f-c0e9d94a1887

📥 Commits

Reviewing files that changed from the base of the PR and between 38269ff and 148a632.

📒 Files selected for processing (4)
  • src/main/presenter/remoteControlPresenter/feishu/feishuClient.ts
  • src/main/presenter/remoteControlPresenter/feishu/feishuMarkdown.ts
  • src/main/presenter/remoteControlPresenter/feishu/feishuRuntime.ts
  • test/main/presenter/remoteControlPresenter/feishuRuntime.test.ts

Comment thread src/main/presenter/remoteControlPresenter/feishu/feishuClient.ts
Comment on lines +94 to +97
export function optimizeMarkdownForFeishu(text: string, cardVersion = 2): string {
try {
let r = optimizeMarkdownStyleCore(text, cardVersion)
r = stripInvalidImageKeys(r)
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve fenced code examples when stripping image keys.

optimizeMarkdownStyleCore() protects fenced blocks, but stripInvalidImageKeys() runs afterwards on the restored markdown. A code sample containing ![...](...) will be rewritten, so code snippets are no longer preserved verbatim.

@zerob13 zerob13 merged commit 7440b76 into dev May 11, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants