流式安全的Markdown:解决AI聊天界面的渲染闪烁问题

anythic/ui 通过解析前修复残缺前缀,解决流式AI输出中Markdown渲染闪烁问题,并提供完整Agent界面组件库。
在AI聊天界面的流式输出场景中,Markdown解析器因假设拿到完整文档而频繁出错——未闭合的代码围栏、成对符号和残缺链接会导致布局持续闪烁。开源React组件库anythic/ui的核心方案是在解析前先"修复前缀":主动闭合开启的代码围栏、补齐不成对的加粗和斜体标记、暂时隐藏未完整的链接,确保解析器每次拿到的都是语法合法的Markdown,从而实现平滑的逐字渲染。除流式Markdown组件外,该库还提供ReasoningBlock、ToolCall、ToolApproval、CodeDiff、Terminal等面向Agent场景的完整组件,所有组件模型无关,兼容主流AI SDK,采用Tailwind v4与shadcn兼容的设计token,以MIT协议开源。
构建过AI聊天界面的开发者大多遇到过这样的场景:模型正在流式输出一段代码块,突然整个回复变成了一团巨大的等宽字体乱码;一个 ** 开启了加粗却迟迟没有闭合;一个链接渲染成了残缺的 [text](htt。等下一个 token 到达时,整个布局又瞬间跳回正常状态。这种闪烁体验在 AI 应用中极为常见,而开源 React 组件库 anythic/ui 正是围绕这个痛点而生。

问题根源:Markdown 从未为"不完整"而设计
这个问题的本质在于,Markdown 解析器天然假设自己拿到的是一份完整文档。但在流式输出的场景下,解析器每次只能拿到文档的一个前缀片段。
设想模型正在输出这样一段内容:
Here is the fix:
```ts
function add(a, b) {
return a +
此时代码围栏(code fence)是开启状态,解析器会把后续所有内容——包括尚未到达的正文文本——全部当作代码处理。随着每一个 token 的到达,布局就在"代码块"和"正常文本"之间来回翻转,造成肉眼可见的抖动。
同样的问题也发生在未闭合的加粗标记 **、斜体 _、反引号以及残缺的链接语法上。这些 Markdown 的"成对符号"在流式传输中天然处于半开状态,而传统解析器对此束手无策。
代码围栏(code fence)是 Markdown 中用三个反引号(```)或三个波浪号(~~~)包裹代码块的语法。解析器在遇到开启的围栏后,会持续将后续所有内容视为代码,直到找到对应的闭合围栏为止。在流式场景下,闭合围栏可能需要几秒钟后才会到达,这段时间内整段对话都会被错误地渲染为等宽字体的代码区域。类似地,Markdown 依赖"成对符号"来标记格式范围——加粗需要两个 ** 首尾匹配,斜体需要 _ 或 * 成对出现,超链接则依赖 [text](url) 这一完整结构。这些语法的共同特点是:解析器必须看到"闭合信号"才能正确判断格式边界,而流式输出的每一帧都是一份天然残缺的文档。
解决思路:解析前先修复前缀
anythic/ui 的核心做法并不是去改造解析器,而是在解析之前先"补全"这段不完整的前缀文本。
具体来说,它会在喂给解析器之前完成几件事:闭合开启的代码围栏、补齐不成对的 **、_ 和反引号,并且在链接的 URL 尚未完整时暂时隐藏该链接。这样一来,解析器每次拿到的始终是一段语法合法的 Markdown,回复内容就能平滑地逐步生长,而不是在不同状态间闪烁跳动。
这种"修复前缀"的策略相比"等待完整文本再渲染"要优雅得多——后者会牺牲流式输出的实时感,而前者既保留了逐字呈现的体验,又避免了视觉混乱。
在 anythic/ui 中,这一切都封装在 Markdown 组件内部,开发者只需把流式文本直接传入即可:
import { Markdown } from "@anythic/ui";
<Markdown>{streamingText}</Markdown>
无需额外配置,组件会自动处理前缀修复逻辑。
不止 Markdown:一套完整的 Agent 界面组件
当 Markdown 渲染问题被攻克后,团队继续补齐了构建 Agent 界面所需的其他拼图。这些组件覆盖了现代 AI 交互中的常见模式:
- ReasoningBlock:可折叠的"思考过程"展示,并显示模型思考耗时
- ToolCall / ToolApproval:呈现 Agent 正在执行的操作,并在危险动作前请求用户确认
- Plan:实时展示 Agent 执行步骤的清单
- CodeDiff:基于自研 Myers diff 算法展示文件变更
- Terminal:带 ANSI 颜色解析器和进度条的命令行输出
- Citation / Sources:与正文中
[1]对应的编号引用 - PromptInput / Conversation / Message:聊天界面本身的外壳组件
其中 ToolApproval 的"危险操作前确认"设计尤其值得关注——随着 Agent 自主执行能力增强,交互层面对高风险动作的拦截机制正变得越来越重要。
模型无关与样式兼容
所有组件都是模型无关(model-agnostic)的:它们只接收普通的 props,因此可以配合 Vercel AI SDK、OpenAI、Anthropic、Gemini 或自建后端使用,不绑定任何特定供应商。
样式方面采用 Tailwind v4,并使用与 shadcn 兼容的设计 token,可以直接融入现有的 shadcn 项目,暗色模式也开箱即用。这种设计降低了接入成本,让组件库更容易嵌入已有技术栈。
Myers diff 算法是 1986 年由 Eugene Myers 提出的差异比对算法,被 Git 等主流版本控制工具广泛采用,其核心目标是找出两段文本之间编辑距离最短的变更序列(即最少的插入与删除操作)。在 AI 代码编辑场景中,模型输出修改后的文件内容,前端需要将其与原文件进行对比并可视化展示变更位置。自研 Myers diff 实现意味着该组件不依赖外部 diff 库,可以针对 AI 输出的特点(如整段代码替换、大量连续插入)进行针对性优化,同时控制包体积和渲染性能。
如何上手
安装只需一条命令:
npm i @anythic/ui
项目仓库包含每个组件的截图,以及一个可以用自己的 Gemini key 在本地运行的 demo 应用。整个库采用 MIT 协议开源,开发者可自由使用与修改。
对于正在构建 AI 聊天或 Agent 界面的团队而言,流式 Markdown 的渲染稳定性往往是最先暴露、却又最容易被低估的工程细节。anythic/ui 把这一问题提炼成了一个可复用的组件方案,这类面向 AI 场景的 UI 基础设施,正逐渐成为 AI 应用开发中不可或缺的一环。
相关推荐

AGENTS.md 实战指南:让编程 Agent 真正好用
AGENTS.md 和 CLAUDE.md 能显著提升编程 Agent 表现,但研究发现用错反而让成本上升 20%。本文详解该写什么、该删什么、200 行与 32KB 的硬边界、Monorepo 嵌套规则及安全提醒。

花旗AI编程代理Devon:年省30%技术外包费,1.4万工程师已使用
花旗集团利用AI编程代理Devon,一年内削减30%技术供应商费用,1.4万工程师使用,产品发布提速30%-40%。本文分析其对IT外包行业的冲击及未来人机协作模式。

从生日派对到千亿AI帝国:新一代PayPal黑帮崛起
2015年一张生日派对合影,十年后催生Scale AI、Cognition AI等千亿估值AI公司。解析新一代PayPal黑帮的创业路径、互相投资生态,以及Peter Thiel的Founders Fund如何完成代际传承。