DeepSeek Harness(DSH)的设计理念是“一切皆插件”。在默认情况下,助手回复的消息会经过宿主完整的 Markdown 渲染管线,而用户发出的消息通常保持 white-space: pre-wrap 的源码形态。这导致在对话界面中,消息格式不统一,开发者阅读或调试时需要额外解析 Markdown 语法。
dsh-markdown-bubble 是一个客户端插件,旨在将用户消息接入宿主同款的 Markdown 渲染管线。它通过官方的 keyed 槽位机制替换 conversation.chat.node 中的 user 和 steering 座位,在保持宿主样式和操作条兼容的前提下,实现用户消息的格式化显示。
核心功能¶
- 官方座位替换:通过
ctx.slots.inject注册user和steering座位,优先级为-1,停用或卸载后即恢复宿主默认渲染。 - 宿主同款渲染:直接调用
@deepseek-ai/dsh-client-ui-primitives的MarkdownText,复用解析器、语法高亮、表格渲染和 KaTeX 公式支持,不重复造轮子。 - 引用 chip 保留:调用宿主投影函数
projectUserText,将返回内容拆分为 chip 和纯文本,chip 保持可点击状态。 - 操作条与三方插件兼容:重建时间与复制按钮,保留
_actions/_action类名后缀及data-clock锚点,确保dsh-edit-turn、dsh-delete-turn等插件正常工作。 - 附件与补充块支持:图片走官方
conversation.message.images座位,文件卡、引用摘要与JsonBlock补充块与宿主保持一致。 - 软换行保留:仅对非围栏代码块的续行补 GFM 两空格硬换行,代码块内部字节保持原样,表格和缩进代码不受影响。
- 出错兜底:单条消息渲染错误会被错误边界捕获,回退为宿主原始投影,防止整条座位被槽位机制移除。
- 中英双语切换:文案复用宿主
chat字典,随系统语言自动切换。
安装与启用¶
安装过程依赖 DSH 的插件管理命令。安装后即生效,无需额外的配置项。
dsh plugin --profile web add dsh-markdown-bubble
安装命令会将依赖写入 profile 并追加到 dsh.profile.bundles。宿主通常会立即扫描到新行并热挂载,若未生效,重启进程后刷新页面即可。
典型用法¶
发一条包含 Markdown 语法的消息,气泡内将按格式渲染。
# 标题
- 列表 **加粗**
- 第二项 `行内代码`
> 引用一行
```js
const a = 1
```
注意事项与限制¶
- 待确认气泡不覆盖:本地回声与待发送 steering 由宿主
PendingSubmissionBubble/PendingSteeringBubble直接绘制,不走chat-node座位,保持纯文本。 - 队列预览不覆盖:排队消息的一行预览与 goal 命令行保持纯文本。
- 行内 chip 的折衷:当 chip 打断连排段落时,该段落会被拆分为 chip 两边的块,这是同类实现的常见取舍。
- 皮肤边界:直接针对宿主 CSS-module 类名定制用户气泡样式的皮肤不会命中本插件的气泡,但主题 token 和
.dshmb-*自定义样式正常生效。 - 多行语义:单换行按硬换行渲染,连续空格和 Tab 在代码块外会被 Markdown 折叠(代码块内除外)。
- 兼容性:插件依赖
conversation.chat.nodekeyed 槽位、data-chat-flow-kind等属性以及MarkdownText/projectUserText等接口。实测兼容 DSH 0.2.0-rc.1(web profile,Chromium)。
总结¶
该插件解决了 DSH 中用户消息与助手消息渲染不一致的问题,通过不修改宿主源码的方式,将用户消息接入标准的 Markdown 管线。它保留了引用 chip 的交互能力,并兼容现有的操作条和第三方插件。安装即用,适合需要在对话流中直接查看格式化内容的场景。
- 插件目录:dsh-markdown-bubble
- 源码仓库:dsh-markdown-bubble