🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

压缩状态行 sailoflight/dsh-tui-compact-carry

DeepSeek Harness
sailoflight30 天前有提交已提供中文文档扫描:未发现敏感能力

在状态行显示压缩进度,并用命令把摘要带进新会话

30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/5 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add sailoflight/dsh-tui-compact-carry
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · ui
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
数据截至 2026/11/04·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 30 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🟢 扫描:未发现敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。

扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 状态栏显示压缩次数
  • 状态栏显示压缩进度
  • 命令携带摘要进会话

仅 TUI 的 DeepSeek Harness 插件:状态栏显示压缩次数与进度,/carry 把缓存的压缩摘要带进当前会话

README

由 DeepSeek 最新模型翻译生成
dsh-tui-compact-carry 一个只面向 TUI 的插件,服务于 DeepSeek Harness(dsh):在状态行显示压缩次数 + 实时进度,并用 /carry 把缓存的压缩摘要带进当前会话。 ⚠️ 只支持 TUI(@deepseek-harness-tui/dsh-tui)。状态行依赖 ctx.tuiStatus, Web / headless 没有这个服务,装上去不会报错但也没有状态行。命令本身在两端都能跑,但本插件刻意只面向 TUI 场景。 一个零依赖的小插件(只用 Node 内置模块),解决 TUI 里压缩体验的三个痛点: 1. 看不到压缩在跑 —— 自动压缩在 TUI 主界面完全无声,十几秒里没有任何指示。 2. 数不清压过几次 —— 一屏之外的历史压缩次数没有地方可看。 3. /new 之后上下文归零 —— 刚压缩出来的完整摘要带不到新会话里。 它做什么 | 能力 | 实现 | | 状态行实时显示已压缩次数(+ 最近一次回收 token) | ctx.on('session/event') 数 compaction/summary → ctx.tuiStatus.set('compact-carry', …) | | 压缩进行中显示「压缩中…
展开完整文档(README 剩余 1 节)
dsh-tui-compact-carry

一个只面向 TUI 的插件,服务于 DeepSeek Harness(dsh):在状态行显示压缩次数 + 实时进度,并用 /carry 把缓存的压缩摘要带进当前会话。

⚠️ 只支持 TUI(@deepseek-harness-tui/dsh-tui)。状态行依赖 ctx.tuiStatus, Web / headless 没有这个服务,装上去不会报错但也没有状态行。命令本身在两端都能跑,但本插件刻意只面向 TUI 场景。

一个零依赖的小插件(只用 Node 内置模块),解决 TUI 里压缩体验的三个痛点:

1. 看不到压缩在跑 —— 自动压缩在 TUI 主界面完全无声,十几秒里没有任何指示。
2. 数不清压过几次 —— 一屏之外的历史压缩次数没有地方可看。
3. /new 之后上下文归零 —— 刚压缩出来的完整摘要带不到新会话里。

它做什么

| 能力 | 实现 |
| 状态行实时显示已压缩次数(+ 最近一次回收 token) | ctx.on('session/event') 数 compaction/summary → ctx.tuiStatus.set('compact-carry', …) |
| 压缩进行中显示「压缩中…(第 N 次 · Ns)」 | compaction/start 进进度态、summary/end 退出;1 秒一跳,progressMaxMs 兜底 |
| 手动 /compact 后自动缓存摘要 | 认签名 sourceCommandId === undefined && turn == null(出回合 + 非命令驱动)→ compaction/end 时置 pending,状态行出现「· 摘要待带出」,弹 toast 提示敲 /carry |
| /carry:把缓存的摘要写进当前会话 | invocation.agent.session → append('user/message', …, {surfaceOp:'append'}) → ctx.sessions.flush();带官方 checkpoint 标记 → TUI 渲染成折叠的「压缩检查点」行 |
| /carry show:先看要带什么 | 打印来源会话、回收量、正文前 400 字 |
| /carry all / merged / last | all = 每一次压缩记录按序拼接;默认只带最后一条(官方已把上一份 checkpoint 合并进新摘要 = 全量) |
| /carry now:另建一个独立会话 | ctx.sessions.create('carry-<uuid>') → append → flush;之后 /resume 选第 1 条 |
| /carry off:清掉待带出摘要 | 清 pending(不删已有的会话记录) |
| /compactstats:看账目 | 次数 + 累计回收 + 待带出/已带出状态 |
| 关键节点弹一条 toast | ctx.get('tuiToast', false)(拿不到该服务就静默跳过) |

为什么要进度行:自动压缩在 TUI 主界面是无声的——channel.compact() 里的「正在压缩会话…」
只属于手动 /compact;全包响应 compaction/start|end 的只有轨迹页投影(trajectory/projection.js)。所以插件把这两个事件搬到了状态行上。

安装

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

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

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

package.json 里声明了 dsh.bundle,所以 dsh plugin add 会把它作为一层配置装进 profile。
装完重启该 profile 才生效(manifest/包元数据不热更新;只有用户自己的 cordis.patch.yml 才热重载)。

方式 B:绝对路径挂载(零依赖,不需要 pnpm)

本插件零外部依赖,所以也可以直接把 index.js 放到插件目录,再用绝对路径挂一行:

mkdir -p "$HOME/.dsh/plugins/dsh-tui-compact-carry"
cp index.js "$HOME/.dsh/plugins/dsh-tui-compact-carry/"

在 $DSH_HOME/profiles/dsh-tui/cordis.patch.yml(默认 $DSH_HOME = ~/.dsh)里加:

- insert:
- id: dsh-tui-compact-carry
name: /home/<you>/.dsh/plugins/dsh-tui-compact-carry/index.js
config: {}

⚠️ 方式 A 与方式 B 二选一,别同时用(同一个 id 挂两次会报 duplicate loader entry id)。

用法(三步)

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

- ②③ 之间的顺序不重要,重要的是 ③ 要在你希望摘要落在的那个会话里敲——插件写的是 "当前 agent 的会话",不猜、不追、不抢。
- 想先看内容:/carry show;想带全部压缩记录:/carry all;改主意:/carry off。
- 摘要缓存默认 30 分钟内有效(autoArmWindowMs),过期就提示"过期"并要求重新 /compact。
- 没有摘要可带时 /carry 直接报错,让你先按官方 /compact(不猜测、不虚报、绝不自己动手压)。
- 摘要缓存是进程内的:/compact 之后没敲 /carry 就重启了 TUI,缓存就没了,重新压一次即可。

设计约束(三条硬规则)

一、不订阅任何 TUI 决策事件

tui/session-switched、tui/input、tui/compact 等属于 TUI 决策事件 (TUI_DECISION_EVENT_NAMES)。TUI 装了全局钩子 ctx.on('internal/listener', …) (dsh-adapter/decision-guard.js 的 installDecisionGuard),cordis 对每一次订阅都会触发它。
插件用裸 ctx.on 注册决策事件时:

- 若插件没有 Component 身份 → 记 warn 并返回 () => false(空 disposer),监听器根本没注册;
- 若有身份但没有 tui.dsh/v1alpha1#DecisionEvents 契约 → registerDecisionHandler 抛错,同样被捕获、告警、拒绝。

dsh-adapter/extension-events.js 也写得很明白:"Handlers come from the host-mediated DecisionEvents registry. Raw Cordis ctx.on listeners are intentionally absent from this path."

⇒ 普通插件订阅决策事件是死代码。要用决策事件,得把一个完整 TUI 扩展组件(manifest + DecisionEvents 契约 + 权限声明 + 授权文件)装进 dsh-tui 自己的扩展宿主里——那是另一量级的工程,而且正好是"插件深度介入 /new 切换"的高风险区。
本插件的选择是退出这条路径:计数/进度/缓存全部走 session/event (普通事件,决策守卫不管)。

排查提示:如果你看到"状态行更新了、但新会话里什么都没发生",八成就是踩了这个区别——普通事件能用,决策事件被静默拒绝。

二、插件绝不自己触发压缩

TUI 把「手动压缩」做成了一个必须在会话切换前结算的事务(dsh-adapter/channel/compaction.js:"Owns the one manual compaction transaction that must settle before a switch."),settleCompaction 被注入 newSessionAction / fork / rewind / session-tree。

插件绕过这个事务直接触发压缩 → /new 的 settle 无事可等 → 切换与压缩赛跑,会卡在半路(表现为:压缩完成后输入栏不再接受输入、盲打 /new 后卡在选择界面、方向键以 [[A 之类的原始序列堆进输入行)。

⇒ TUI 没有给插件留"安全触发官方压缩"的入口(tui/compact 是给插件用的否决钩子,不是触发器)。所以:压缩只由用户按官方 /compact,插件只负责"取现成的摘要 + 搬运"。 离线冒烟的最后一道门就是 engineCalls.length === 0。

三、完全不参与 /new 的切换事务

插件连"新会话出现了"这件事都不需要知道:/carry 是在新会话里敲的,写的是 invocation.agent.session(就是"当前会话"),不依赖任何切换通知。
/new 的建会话/清屏流程逐字保持 dsh-tui 原样。

有一个默认关闭的可选自动版(autoCarryOnNew):新会话出现后延迟 autoCarryDelayMs 自动写入。它走的是普通事件 session/created,刻意绕开 /new 的切换事务;那条监听器抛错会让 attach 回滚,所以全程 try/catch,里面只做"读字段 + 调度定时器"。
默认选择仍是手动 /carry。

与宿主版本的耦合:session format V4(0.6.0)

DSH 的会话格式升到 V4 之后,/carry 会报 format v4 message requires a producer-owned source kind。原因是 0.5.0 写的是 V3 时代的泛型包装 source: { kind: 'plugin', plugin: 'compact' };V4 的准入校验直接拒绝 kind: 'plugin',要求消息源报出「生产者自己的 kind」:

| 形状 | 结果 |
| { kind: 'plugin', plugin: 'compact' } | ❌ 抛错 |
| { kind: 'compact-checkpoint', compactionId } | ✅ 通过(官方 checkpoint 标记) |
| { kind: 'plugin:dsh-tui-compact-carry', compactionId } | ✅ 通过(第三方插件的生产者 kind 约定) |

判据在 dsh-session-format-v3-to-v4/lib/index.js 的 assertV4SourceRowAdmission / assertV4MessageSources,编码与解码两条路径都调用——所以既是写不进去、也是读不出来。
compact-checkpoint 与 dsh-compaction 的 COMPACT_CHECKPOINT_MARKER 逐字一致; TUI/客户端用 isCompactCheckpointSource 只比对它。压缩不变量只作用于「替换型 surface 事件」,而本插件用 surfaceOp: 'append',不受 compactionId 配对约束。

同一版还删掉了 Session.events(只剩 snapshotEvents() / ownEvents()),所以 0.5.0 里遍历 session.events 的兜底读取会 TypeError;0.6.0 改用 snapshotEvents()。

提示:这类耦合会随宿主升级漂移。升级 dsh / dsh-tui 之后先跑一遍离线冒烟。

离线冒烟

node smoke.mock.mjs # 或 npm test

60 项硬断言,失败则 exit≠0,不需要装进任何 profile(用假 ctx)。四道核心回归门:

- 引擎门:假压缩引擎当陷阱,整场跑完断言 engineCalls.length === 0(插件一次都没碰引擎)。
- 决策事件门:断言 listeners 里没有 tui/session-switched。
- V4 生产者 kind 门:本地镜像规则扫过每一条注入消息(kind 非空、≠ plugin、无 plugin 字段、compactionId 非空);若本机装了 @deepseek-ai/dsh,还会加载宿主真实的 assertV4RowAdmission 复核同样这批消息,并做一次「旧形状必须被拒」的反向对照(防止假绿)。
- 会话快照门:假 session 不暴露 events,并构造一条"只存在于会话日志里、插件从没观察到" 的压缩记录,验证 /compactstats、/carry show 能从 snapshotEvents() 补出历史。

其余覆盖:状态行的计数/进度/待带出/已带出流转、/new 纯净性(没有任何写入动作)、不重复注入、/carry all|show|off|now、非法参数、carry-<uuid> 的全局唯一 id、可选自动版(fork/子会话不注入、延迟调度、监听器绝不抛错)。

已知限制

| # | 限制 | 说明 |
| 1 | /carry now 建的新会话不 attach 到 TUI 的 workspace registry(只写了 meta.cwd) | /resume 读的是持久化后端的全量会话,同 cwd 归到同一项目 → 仍会出现在列表里 |
| 2 | 伪造的 compactionId(carry-<uuid>)没有对应的 compaction/summary 事件 | 纯显示层影响;把 useCheckpointMarker 设为 false 可完全规避(代价:不折叠成「压缩检查点」行) |
| 3 | 摘要缓存只覆盖本进程 | 有 live 会话回读兜底;重启 TUI 后对已 dispose 的旧会话取不到记录 → 就不带(保守) |
| 4 | 注入行是否"立刻"渲染未逐一验证(写入是确定的:flush 完就在持久化里) | 状态行「已带 N 条摘要」是立刻可见的确认;万一首条没马上显示,/resume 重进一次即可 |
| 5 | 压缩不由插件触发 → 要自己按 /compact,且多了一条 /carry | TUI 侧硬约束(见「设计约束 二」) |
| 6 | 自动缓存靠事件签名判定(sourceCommandId === undefined && turn == null) | 若将来 payload 形状变了,降级是安全的:不会误带,只是要手动 /compact 后重压 |
| 7 | 贴住了两个会随宿主升级漂移的契约(消息源 kind、Session 快照读法) | 都写进了离线冒烟;升级后先 npm test |

配置项(index.js 顶部 CONFIG)

| 键 | 默认 | 含义 |
| carryMode | 'merged' | 命令参数可覆盖;'merged'=最后一条全量,'all'=每一次压缩按序 |
| maxCarryChars | 0 | 注入正文字符上限,0=不截断 |
| maxKeepSessions / maxItemsPerSession | 8 / 64 | 内存缓存上限 |
| statusKey / showStatus | 'compact-carry' / true | 状态行 key 与开关 |
| showProgress / progressElapsed | true / true | 压缩进行中的进度态;是否带秒数 |
| progressMaxMs | 900000(15 min) | 进度兜底上限:超过视为 compaction/end 丢失,回到计数行 |
| useCheckpointMarker | true | 用官方 kind:'compact-checkpoint' 标记(渲染成原生压缩检查点行)。设为 false 则改用 plugin:dsh-tui-compact-carry(代价:不折叠成检查点行) |
| showNextStepToast | true | 关键节点弹一条 tuiToast(拿不到该服务则静默跳过) |
| autoArmOnManualCompact | true | 用户按官方 /compact 后自动缓存摘要(等 /carry 带入) |
| autoArmWindowMs | 1800000(30 min) | 缓存的有效窗口;超过就不带。0/负数 = 不过期 |
| autoCarryOnNew | false | 自动版:新会话出现后自动写入。默认关 |
| autoCarryDelayMs | 1500 | 自动版的延迟:等 /new 的切换事务落定后再写 |

许可

MIT
预览分享卡片长什么样 ↓sailoflight/dsh-tui-compact-carry
分享 · DeepSeek Harness Hub
sailoflight/dsh-tui-compact-carry

在状态行显示压缩进度,并用命令把摘要带进新会话

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部