dsh-tui-compact-carry:TUI 压缩进度可见,/carry 把摘要带进新会话

前言

在 DeepSeek Harness(dsh)的 TUI 里做长会话时,上下文压缩是常态:窗口满了会自动压,也可以手动 /compact。但 TUI 主界面里,自动压缩往往没有明显反馈;历史里压过几次也不直观;更常见的是 /new 开新会话后,刚压出来的全量摘要还在旧会话里,当前会话从空白重新开始。

社区插件 dsh-tui-compact-carry(维护者 sailoflight,分类:客户端)面向 仅 TUI 场景(@deepseek-harness-tui/dsh-tui):在状态行显示压缩次数与进行中进度,并在你手动 /compact 后缓存摘要,用 /carry 写入当前会话。Web / headless 没有 ctx.tuiStatus,装上不会报错但也没有状态行;命令本身两端都能跑,插件刻意只服务 TUI。

下面介绍它解决什么问题、怎么用,以及安装前需要知道的约束。

这是什么

dsh-tui-compact-carry 是零依赖的小插件(只用 Node 内置模块),通过监听 session/event 做三件事:

  1. 状态行显示已压缩次数(以及最近一次回收 token),压缩进行中显示「压缩中…(第 N 次 · Ns)」。
  2. 识别用户手动 /compact 结束后的摘要,在进程内短期缓存,状态行提示「摘要待带出」。
  3. 提供 /carry 等命令,把缓存摘要 append 到当前 agent 会话,并尽量用官方 checkpoint 标记,让 TUI 渲染成折叠的「压缩检查点」行。

它不触发压缩、不介入 /new 的切换事务;压缩仍由官方 /compact 完成,插件只「取现成的摘要 + 搬运」。

核心功能

状态行:次数与进度

能力 说明
压缩次数 监听 compaction/summary,经 ctx.tuiStatus.set('compact-carry', …) 更新状态行
进行中 compaction/start 进入进度态,summary / end 退出;约 1 秒刷新,progressMaxMs 兜底防事件丢失

自动压缩在 TUI 主界面原本几乎无声;插件把 compaction/start|end 相关信号搬到状态行,便于确认「正在压」而不是界面卡住。

手动压缩后缓存与 /carry

手动 /compact 完成后,插件按事件签名(sourceCommandId === undefined && turn == null)在 compaction/end 时置 pending,并可通过 toast 提示使用 /carry(若 ctx.get('tuiToast') 不可用则静默跳过)。

常用命令(均在希望摘要落入的会话里执行,写的是 invocation.agent.session):

命令 作用
/carry 默认 merged:带最后一条全量摘要(官方会把上一份 checkpoint 合并进新摘要)
/carry show 预览来源会话、回收量、正文前 400 字
/carry all 按序拼接每一次压缩记录
/carry last 只带最后一条(与默认 merged 语义相关,见 README)
/carry now 新建独立会话 carry-<uuid> 写入后 /resume 选择
/carry off 清除待带出 pending,不删已有会话记录
/compactstats 次数、累计回收、待带出/已带出状态

摘要缓存默认 30 分钟内有效(配置项 autoArmWindowMs);过期需重新 /compact。缓存是进程内的:压完未 /carry 就重启 TUI,需再压一次。没有可带摘要时 /carry 会报错,不会代替你执行压缩。

典型三步用法

README 给出的可复现流程:

/compact        # ① 官方手动压缩一次(拿到含最近几轮的最新全量摘要)
/new            # ② 起新会话 —— dsh-tui 原生行为,插件不参与
/carry          # ③ 在新会话里:把刚缓存的摘要写进本会话

② 与 ③ 的顺序可以调换,关键是 ③ 必须在目标会话里敲。想先看内容用 /carry show;要带全部历史用 /carry all;改主意用 /carry off。

设计约束(使用与排错时有用)

  1. 不订阅 TUI 决策事件(如 tui/session-switched)。普通插件用裸 ctx.on 订阅会被决策守卫拒绝,表现为「状态行有更新、新会话却没写入」——本插件计数、进度、缓存全部走普通 session/event。
  2. 绝不自己触发压缩。TUI 把手动压缩做成切换前必须结算的事务;插件若绕过会与 /new 赛跑,可能出现输入栏无响应等问题。离线冒烟用 engineCalls.length === 0 断言插件不碰引擎。
  3. 不参与 /new 切换。可选 autoCarryOnNew(默认关)仅监听 session/created 延迟写入,默认仍建议手动 /carry。

与宿主 session format V4(插件版本 0.6.0)对齐:/carry 写入使用 kind: 'compact-checkpoint' 或 plugin:dsh-tui-compact-carry,避免 V3 时代的 kind: 'plugin' 被拒;历史读取改用 snapshotEvents() 而非已移除的 Session.events。

安装与启用

要求:Node.js ^22.19.0 || >=24.0.0,且 dsh 已在 PATH。

方式 A:按 bundle 安装(推荐)

package.json 声明了 dsh.bundle,安装命令为:

dsh plugin --profile dsh-tui add github:sailoflight/dsh-tui-compact-carry

装完后重启该 profile 才生效(manifest/包元数据不热更新;用户自己的 cordis.patch.yml 才可热重载)。

方式 B:绝对路径挂载

零外部依赖时,可将 index.js 放到本地目录,并在 $DSH_HOME/profiles/dsh-tui/cordis.patch.yml(默认 $DSH_HOME = ~/.dsh)中 insert 一行绝对路径。README 给出了 mkdir、cp 与 YAML 示例。方式 A 与 B 二选一,同一 id 重复挂载会报 duplicate loader entry id。

维护者提供离线冒烟:node smoke.mock.mjs 或 npm test(60 项断言,含引擎门、决策事件门、V4 消息源门、会话快照门)。升级 dsh / dsh-tui 后建议先跑一遍。

配置项(节选)

在 index.js 顶部 CONFIG 可调,例如:

键 默认 含义
carryMode 'merged' 'merged' 最后一条全量,'all' 按序全部
maxCarryChars 0 注入正文上限,0 不截断
showProgress / progressMaxMs true / 900000 进度显示与兜底超时
useCheckpointMarker true true 用官方 compact-checkpoint 折叠行;false 改用插件 kind
autoCarryOnNew 默认关 新会话创建后延迟自动 carry

完整表见 GitHub README。

适用场景与注意

适合:长期在 dsh-tui 里开发智能体、依赖压缩续聊,又需要在 /new 后把刚压好的摘要接到新会话的人。

务必知晓:

  • 插件以当前 dsh 进程权限运行;安装前请阅读 GitHub 仓库 源码与 MIT 许可证,自行判断是否纳入 profile。
  • 仅 TUI 有状态行体验;Web / headless 无 tuiStatus。
  • /carry now 新建会话未 attach TUI workspace registry(仅 meta.cwd),仍可能出现在同 cwd 的 /resume 列表;伪造的 compactionId 无对应 compaction/summary 时主要影响展示层。
  • DeepSeek Harness 生态强调「一切皆插件」;SkillHub 目录页 为社区收录,与 DeepSeek / 幻方无官方从属关系。

结尾

dsh-tui-compact-carry 不替代官方压缩,而是让 TUI 里「压了几次、正在压、压完怎么带到新会话」这三件事可看见、可操作:/compact → /new(可选)→ /carry。需要细节、配置与限制表时,以仓库 README 为准。

  • 目录页:https://www.skillhub.cn/plugins/sailoflight/dsh-tui-compact-carry
  • GitHub:https://github.com/sailoflight/dsh-tui-compact-carry
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜