DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

constraint21 /

constraint21/dsh-long-message-fold

Verified

Folds over-long user messages in the DSH Web chat: 360px preview, fading edge, Expand/Collapse toggle; short messages are untouched.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@5bd1bd9a

dsh-long-message-fold · 长消息折叠

ci license: MIT

给 DeepSeek Harness Web 的对话加一条能力:超长的用户消息自动折叠成固定高度(默认 360px ≈ 16 行),底部渐隐,点「展开全文」看完整内容,再点「收起」回去。短消息一个像素都不变。

效果

┌────────────────────────────────────────┐
│ 你:请看这段日志 …                       │
│ 2026-11-04 14:04:31 INFO  …            │
│ 2026-11-04 14:04:31 INFO  …            │
│ 2026-11-04 14:04:32 WARN  …            │
│ 2026-11-04 14:04:32 INFO  …   ⌄ 渐隐   │
│ [ 展开全文 · 128 行 ]                   │
└────────────────────────────────────────┘

为什么需要

用户往对话里贴大段日志/大文本时,一条消息就能占满整个会话视口,前面的上下文全被顶走。DSH 自带的 Turn Process Folding 只折叠「过程行」(tool-call / thinking),不折叠 user 消息正文,所以这块此前是空缺。

安装

插件走 DSH 的 Plugin Manager 安装,三种方式任选。

1. 让 agent 装(推荐)

对 DSH 说一句:

安装插件 github:constraint21/dsh-long-message-fold

agent 会调用 plugin_manager → install_bundle,审批通过后生效。

2. 本地目录

git clone https://github.com/constraint21/dsh-long-message-fold.git

然后把 install_bundle 的 target 指向该目录的绝对路径。

3. 手动(不推荐)

把包放进 profile 的 node_modules,并在 cordis.patch.yml 里 insert 一个 long-message-fold 条目。手改 profile 的 package.json / patch 容易和 Plugin Manager 的状态打架,能用前两种就别用这个。

安装后刷新 Web 页面(这个插件是纯客户端 UI,不重启 Host 也可以,但要重新加载页面资源)。

使用

没有开关,装上即生效。长消息折叠后:

  • 「展开全文 · N 行」——展开并显示总行数;
  • 「收起」——回到折叠态;
  • 拖动窗口 / 侧栏变宽后,原本溢出的消息会自动恢复成不折叠(实测高度回落),不需要手动操作。

工作原理

扩展点

候选 可行性 结论
替换 conversation.chat.node 的 user 行 需重写 pending / echo / 时间 / 复制控件整行 否决
替换 factory conversation.chat.user.content 需重写 userStack / 附件行 / bubble / JsonBlock 否决
纯 CSS + data- 属性 + document 级事件 违反插件纪律「不写组件外 DOM、不读别人 DOM」 否决
遮盖 conversation.user.text.node 的 key: 'text' 只换纯文本节点的渲染器,外层气泡/附件/控件全部保留 采用

关键事实:

  • conversation.user.text.node 在 slot catalog 里声明为 replaceRisk: "shadows-shipped-ui",README 示例就是同 key 注册来覆盖。
  • shipped 的 PlainUserText 以 priority: 100 注册;动态安装的插件条目由 runner 的 allocatePriority() 分配更小的优先级数值,而「数值更小者获胜」,所以同 key 注册即取代,无需传 priority。
  • 该 key 在 QueueDock 预览和 submission echo 里也会被调用(ellipsis: true,父级是 white-space:nowrap),因此折叠判定必须靠实测溢出,不能靠文本长度:nowrap 下高度永远是 1 行,自然不折。

渲染策略

  1. 未溢出:返回与 shipped UserTextRun 等价的 <span style="font-size:inherit;line-height:inherit">(_plainRun 的 CSS 只有这两条)。短消息、以及被 file/secret chip 分隔的文本片段,流式布局与原来完全一致。
  2. 溢出判定(useLayoutEffect + ResizeObserver):
    • 内联态:getBoundingClientRect().height(inline 元素取所有 fragment 的并集,能反映折行后的真实高度);
    • 已成块态:scrollHeight(max-height 不影响 scrollHeight,因此折叠/展开两态下判定一致,不会来回抖动)。
    • 祖先链上 display: contents 的节点没有盒子,ResizeObserver 挂到最近一个有盒子的祖先(bubble),所以侧栏/详情面板改宽度时能双向重算。
  3. 折叠态:display:block 的正文 + max-height:360px; overflow:hidden,底部用 mask-image 渐隐(不猜背景色,任何主题下都对)+ 一个 pill 按钮。
  4. 展开记忆:模块级 Map,键 = 节点起止偏移 + 文本长度 + FNV-1a 哈希,最多 400 条。虚拟列表把行卸载再挂载时展开状态不丢;不写 localStorage,刷新即复位。
  5. 实现纪律:文案走 Client locale service(ctx.locale.register(NS, { zh, en }) + slot 注册带 locale: NS 得到框架注入的 t);配色只用 --dsw-alias-* 主题 token;不 require 任何 Harness Client 包,不写组件外 DOM。

参数

client.js 顶部常量:

常量 默认 含义
MAX_HEIGHT 360 折叠后正文高度(px,约 16 行)
FADE_HEIGHT 48 底部渐隐高度
REMEMBER_LIMIT 400 展开状态记忆条数
OBSERVE_MIN_CHARS 120 短于此长度的文本不挂 ResizeObserver

改完重新加载页面即可,不需要重新安装。

兼容性

  • 依赖 slot conversation.user.text.node 与 Client 包 @deepseek-ai/dsh-client-ui-conversation(见 package.json 的 dsh.client.inject)。slot 或 shipped 实现大改时,本插件可能失效。
  • 退化是安全的:若上游把 'text' key 改名或没了 occupant,框架会用 fallback 渲染原始文本,消息显示不受影响,只是不折叠。
  • 只在 Web 平台注册(dsh.client.platform = "web");Host 半 index.js 是空实现。

卸载

Plugin Manager 里移除 @local/dsh-long-message-fold(或 plugin_manager action: remove_bundle),刷新页面后 user 消息立即恢复原样。状态只存在内存里,无残留。

开发

client.js          # 全部逻辑:slot 注册、测量、折叠渲染、locale、内联 CSS
index.js           # Host 半,空实现(纯客户端插件)
cordis.patch.yml   # bundle 补丁,insert 自身
locale/{zh,en}.json# 插件卡片标题/描述 + 按钮文案
icon.svg           # 插件卡片图标

本地自检(不装 DSH 也能跑):

node --check index.js && node --check client.js

CI(.github/workflows/ci.yml)额外校验 manifest、patch、locale、icon 与 loader id 是否一致。

注意:package.json 里 private: true 是刻意的——这个包不打算发 npm,只通过 git 或本地目录安装。

English

dsh-long-message-fold folds an over-long user message in the DeepSeek Harness Web chat to a fixed height (360px by default), fading out the bottom edge, with a one-click Expand / Collapse toggle. Short messages render exactly as before.

It shadows the shipped PlainUserText renderer by registering the same conversation.user.text.node key ('text'), so the bubble, attachments and row controls stay untouched. Folding is decided by measured overflow, not character count, which keeps QueueDock previews and submission echoes on a single line.

Install with the DSH Plugin Manager:

plugin_manager → install_bundle → target: github:constraint21/dsh-long-message-fold

Then reload the Web page. Tune MAX_HEIGHT / FADE_HEIGHT at the top of client.js. MIT licensed.

License

MIT © 2026 constraint21

—/ 5

No ratings yet

Verified DSH bundle

Commit 5bd1bd9a48f3

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout