Skip to main content
I

dsh-chat-spacing

imcaibaicai/dsh-chat-spacing

Unifies the conversation flow gap and the indent, margins, card borders and radii of expanded reasoning and tool bodies through CSS variables, with one live stepper per knob in Settings → General.

Install

dsh plugin --profile web add github:imcaibaicai/dsh-chat-spacing

README

dsh-chat-spacing

English | 简体中文

DSH 会话行距与展开边框插件:把对话流里正文、思考(沉思)、工具/运行行之间的垂直间距, 以及这些行展开后 Bodies 的左缩进、上下边距、卡片边框与圆角,全部统一到少数几个值, 并在「设置 → 通用 → 会话行距与展开边框」里实时调节。

纯浏览器端 UI 插件,装卸即回到官方默认,不改动任何官方文件。

为什么需要它

官方 bundle 的间距分多套口径,同一屏里「有的挤、有的空、有的没对齐」:

位置官方值
ChatView 会话流块之间16px
[data-turn-process-answer] 过程节点之间8px(硬编码例外)
TurnProcessNodeView 折叠态自身下边距8px
思考行展开体(thinkBody)padding: 4px 0 4px 22px
工具行展开体(read/search/web/diff/image/code 七类 body)margin: 4px 0 4px 4px(缩进 4px,与行文本 22px 没对齐)
展开体卡片边框只有 terminal / ioCard 有 0.5px,其余没有
Block 组件圆角--dsl-*-radius: 12px 各写各的
子调用树(subCalls)margin: 4px 0 2px 22px; padding-left: 8px
思考行摘要行高20px(工具行是 24px)

v0.2 把以上全部收归到五个 CSS 变量,设置行可实时改:

变量控制默认范围/步长
--dsh-csg-gap会话流间隙12px4–32 / 2
--dsh-csg-indent展开体左缩进22px(与行文本对齐)0–40 / 2
--dsh-csg-body-v展开体上下边距4px0–16 / 2
--dsh-csg-card-border展开体卡片边框宽0.5px(0 = 无边框)0–2 / 0.5
--dsh-csg-card-radius展开体卡片圆角12px0–20 / 2
(非 CSS)思考空行留1个保留 / 留1个 / 全删

注:0.5px 边框在 DPR=1 的屏幕上会被浏览器取整成 1px 实线;想要真正无边框请把 「卡片边框」调到 0。

思考空行(v0.2.1 新增)

官方 ReasoningRow 用 white-space: pre-wrap 原样渲染模型思考,而 DeepSeek 系模型 习惯在思考段间和结尾各留 2 个空行(\n\n\n)——每行约 20px,结尾那段纯属死白。 CSS 删不掉文本,所以插件用 MutationObserver 对 .lcKema_thinkBody 的文本节点做规整:

模式行为
保留不动原文
留1个(默认)段间最多 1 个空行,结尾空行全删
全删没有任何空行,段落各自换行

实现要点:只改文本节点的 nodeValue(React 重渲染会重新代入原文,observer 再次规整, 流式输出自动跟随);每个元素记住原文,切模式可精确还原。实测:沉思块到下一个元素的 间隙从约 76px 回到纯流间隙 12px。

空 markdown 占位(v0.2.2 新增)

实测发现「正文段 → 工具行」间隙比反方向大 12px。DOM 挖掘定位:助手正文块 (.hWmORq_body)末尾总挂着一个空 markdown div(assistant-step 最后一个 text block 为空),body 是 flex-column + gap,空 div 白吃一整个 gap:

<div class="hWmORq_body">
  <div class="markdown"><p>…正文…</p></div>
  <div class="markdown"></div>   <!-- 空吃 12px -->
</div>

修复一行 CSS:.hWmORq_body > :empty { display: none }。空 div 被填满时自动不再 :empty 而恢复,流式输出不受影响。实测修复后所有方向流间隙一致(12px),助手正文块 高度回到 24/48 的整数行高。

安装

dsh plugin --profile web add -w dsh-chat-spacing

等价的手动方式:把包装到 <DSH_HOME>/profiles/node_modules/dsh-chat-spacing/(package.json + lib/index.js 宿主 no-op 载体 + lib/client.js 浏览器端),并在 profile 的 cordis.patch.yml 追加:

- insert:
    - id: chat-spacing
      name: 'dsh-chat-spacing'

安装后需完全退出 DeepSeek Harness(含后台进程)→ 重新启动 → 会话页 Ctrl+Shift+R 强刷。 升级只需覆盖 lib/client.js 与 package.json;cordis.patch.yml 里已有 chat-spacing 行的无需改动,旧的 gap 设置值自动沿用。

卸载:删掉 cordis.patch.yml 里那三行 insert,或把 id 一行改成注释。重启即恢复官方间距。

设置项

「设置 → 通用」中一行(标题:会话行距与展开边框),五个步进器 + 「恢复默认」。 取值通过 DSH 的 settingsScope(namespace ui-chat-spacing,字段 gap / indent / bodyV / cardBorder / cardRadius)写入 Host 用户设置文档,重启后保留。

实测记录(2026-09-26,隔离实例 + 真实会话)

  • 流间隙:可见 flowItem 之间 margin-top 全部 12px、pitch 全部 12px(官方 16/8 混合被抹平)。
  • 展开体(stock):searchBody 无边框、ioCard 有 1px 边框,两者左缩进都是 4px(与行文本 22px 错位)。
  • 展开体(v2 默认):两者左缩进 22px、边框统一 0.5px→1px、圆角统一 12px。
  • 可调性:把 indent 改 8px、border 改 0、radius 改 4px、gap 改 20px 后全部即时跟随。

维护提示(升级 DSH 后必看)

v0.3.0 起本插件不再依赖任何 CSS-Modules 哈希前缀,升级 DSH 后通常不需要改动。 所有选择器只用了三类稳定锚点:

类型例子来源
官方自己渲染的 data-*[data-chat-flow]、[data-turn-process]、[data-turn-tail]、[data-subcalls]、[data-context-injection-body]、[data-variant="think"]组件 JSX 里硬写的属性
槽位后缀匹配[class*="_thinkBody"]、[class*="_codeBody"]、[class*="_ioCard"]只匹配 _槽位名 后缀,忽略每次构建都会变的哈希前缀
官方间距变量--dsh-chat-flow-gap官方 CSS 已经用它控制流间隙

什么时候才会失效:上游把槽位改名(例如 thinkBody → reasoningBody)或删掉上述 data-* 属性。 这时属于功能性改动,会表现为「某一块突然没被统一」,而不是像旧版那样「整份样式表静默全废」。

排查办法:在会话页打开 DevTools,document.querySelectorAll('[class*="_thinkBody"]').length 若为 0, 说明槽位改名了,到 dsh-client-ui-chat / dsh-client-ui-tool 的 lib/client.js 里搜新的槽位名再替换后缀。

v0.3.0 变更(2026-10-26)

  • 起因:DSH 0.2.1-rc.3(2026-10-23 更新)重排了 CSS-Modules 哈希,旧版 16 条业务规则全部命中 0 次, 插件「装着但完全空转」,会话间距回落官方默认(6 / 12 / 16px 分档 + 组内 16px gap)。
  • 修复:12 处哈希选择器全部换成上表的稳定锚点;THINK_BODY_SEL 同步改为 [class*="_thinkBody"]。
  • 明确降级(后缀命中面过宽、会误伤,故不再覆盖):
    • AskQuestionCard 的卡片外框(_card 后缀在当前产物里命中 71 个类名家族,会把无关卡片一起上边框);
    • GenericCommandCard 的 body 内边距(_body 后缀与助手正文 body 无法在不引回哈希的前提下区分);
    • 旧 imageLabel 槽位在当前版本已不存在。

已知边界

  • 只调整会话流与展开体。输入区(composer)、任务清单 dock 不在覆盖范围内。
  • Block 组件(ReadBlock/SearchBlock/…)的内部结构(行号列、banner 内边距)不改, 只统一外框的圆角/边框/位置。
  • 走 CSS 覆盖(!important),不修改官方文件;官方重新构建时无需回滚。

Related plugins