feat(channels): rich-text markdown rendering for feishu and dingtalk - #99
Open
skywclouds wants to merge 2 commits into
Open
feat(channels): rich-text markdown rendering for feishu and dingtalk#99skywclouds wants to merge 2 commits into
skywclouds wants to merge 2 commits into
Conversation
Add markdown_render.py with a hand-written parser (zero new deps) that covers headings, bold, inline code, fenced/indented/toplevel code blocks, lists, quotes, links, tables, and thematic breaks. Feishu: messages containing markdown are rendered as post rich text with code_block tags; plain text falls back to the original text msgtype. DingTalk: messages containing markdown are sent as native markdown with automatic code-fence insertion (ensure_code_fences) so toplevel code (def/class/import) is properly rendered by DingTalk's markdown engine. Key fixes during development: - Fix infinite loop in _parse_inline_recursive when multiple inline code segments were present (code placeholder regex used text[pos:] causing relative match.end() to never advance pos past the second placeholder). This caused 95% CPU spin -> health check failure -> app crash loop. - Add 4-space indented code block support. - Add toplevel code block detection (def/class/import/from/async def/@decorator) with conservative continuation heuristics (indent lines, # comments, assignments, function calls). - Add toplevel code start to has_markdown detection so code-only messages are routed through the rich-text path. Config: CHANNEL_RICH_RENDER_ENABLED (default true) gates the feature; setting it to false restores the original plain-text behavior. Tests: 1450 passed, ruff clean.
Collaborator
|
#99 目前有一个需要修改的 P1 问题、 位置:
```python
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
split_markdown_by_lines now tracks fenced code block state. When a split point falls inside a code fence, the previous chunk is closed and the next chunk reopens the fence with the original language, so every chunk is self-contained valid Markdown. Fixes broken code fences on feishu post and dingtalk markdown when messages exceed the channel length limit. Adds 9 regression tests covering overlong fenced blocks, language preservation, content recovery, tilde fences, and adapter-level chunk validation.
Contributor
Author
|
感谢详细的 review,P1 问题已修复并推送(commit 204e4c7)。 修复方案重写了 split_markdown_by_lines()(backend/app/channels/markdown_render.py:551),新增围栏代码块状态跟踪:
回归测试新增 9 项测试覆盖该场景:
验证
关于您提到的其余几点确认如下:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
为飞书和钉钉渠道的出站消息增加 Markdown 富文本渲染能力。新增零依赖手写 Markdown 解析器,飞书走 post 富文本、钉钉走原生 markdown 透传 + 围栏补全。通过全局开关 CHANNEL_RICH_RENDER_ENABLED(默认开启)控制,关闭后回退纯文本行为。
动机
此前飞书和钉钉的出站消息均以纯 text 类型发送,AI 回复中的标题、代码块、列表、粗体、行内代码等 Markdown 语法全部以纯文本呈现,可读性差。尤其是代码——缩进丢失、无等宽字体、函数体与说明文字混为一团。
改动范围
只做出站渲染,不改入站解析、不改微信/企微、不改前端控制台。
文件说明
backend/app/channels/markdown_render.py 新增:Markdown 解析器 + 飞书 post 渲染 + 钉钉围栏补全 + 分块 + title 提取
backend/app/channels/adapters/feishu.py send() 富文本化:含 markdown 走 post,纯文本走 text
backend/app/channels/adapters/dingtalk.py send() 富文本化:含 markdown 走 markdown msgtype + ensure_code_fences 围栏补全
backend/app/config.py 新增 channel_rich_render_enabled: bool = True
backend/.env.example 新增 CHANNEL_RICH_RENDER_ENABLED="true"
backend/tests/test_markdown_render.py 新增:解析器 + 渲染器 + 围栏补全 52 项单测
backend/tests/test_feishu_adapter.py 新增 7 项富文本 send 测试
backend/tests/test_channel_dingtalk.py 新增 11 项富文本 send 测试
技术方案
Markdown 解析器(markdown_render.py,零新增依赖):
飞书渲染:
钉钉渲染:
顶格代码块识别:
开关与回退
测试
风险