fan56/dsh-dcp
dsh plugin: deterministic context compression backend — zero LLM calls, reproducible compression
Project Overview项目介绍
This is a deterministic context compression backend plugin for DeepSeek Harness (dsh). It does context compression purely via code, needs zero LLM calls, consumes no extra tokens, outputs stable results and retains key hard info for Chinese. Use it to compress conversation context to save tokens. It does no semantic induction, use official compression for deep semantic summarization.
dsh-dcp 是 DeepSeek Harness(dsh)的确定性上下文压缩后端插件,核心为纯代码实现零 LLM 调用的上下文压缩,不额外消耗 token,输出稳定,中文友好保留关键硬信息。需要压缩对话上下文节省 token 时使用,不做语义归纳,需深度语义摘要请用官方默认压缩。
请帮我了解并安装插件:【dsh-dcp】【https://github.com/fan56/dsh-dcp】
Send this message to DSH in your current session. CLI install commands may not be accurate across systems — DSH will figure it out for you.把上面这条消息直接发给当前会话里的 DSH,让它帮你了解并安装。安装命令不一定准确,发给 DSH 更稳。
Or use CLI install (for developers)或使用命令行安装(适合开发者)
CLI Install命令行安装
dsh plugin add @aiwayds/dsh-dcp
把 fan56/dsh-dcp 加入你的 DSH 配置(web profile)即可启用。
READMEREADME
dsh-dcp
dsh(DeepSeek Harness)的确定性压缩后端:上下文压缩不调 LLM,开箱即用。
要求 dsh >= 0.1.5-rc.2 — 本插件只跟随 dsh RC/stable 线(CI 与发版在运行时解析 latest/next 中更新的 dist-tag)。不再支持 alpha 线。
简体中文 · English
为什么做
dsh 默认的压缩(compaction-basic)每次压缩都要让模型把旧对话重新总结一遍——费 token、慢、结果还不稳定。我们参考 opencode 社区的 opencode-dcp(去重、清错、"技术摘要代替散文"),做了一个纯代码版本:
- 零 LLM 调用:压缩本身不消耗任何额外 token
- 输出稳定:相同对话永远得到相同摘要
- 中文友好:用户原话/路径/命令/报错逐字保留,按 CJK 真实密度计价
- 继承官方全部安全机制:触发、保留尾巴、事务锁、tool-pairing 边界都复用 dsh 官方实现(只替换"摘要"这一环)
效果
与官方默认压缩的对比
| 官方 compaction-basic | dsh-dcp | |
|---|---|---|
| 摘要方式 | 每次调 LLM 重写 | 确定性代码抽取 |
| 每次压缩的模型调用 | 1 次 | 0 次 |
| 输出稳定性 | 同对话多次可能不同 | 相同输入永远相同 |
| 摘要内容 | 语义归纳 | 逐字保硬信息(路径/命令/报错/待办/用户原话) |
| 中文 | 依赖模型转写 | 原样保留 + CJK 计价 |
| 触发/保留/溢出/安全 | 官方 | 继承官方,完全相同 |
| 检查点格式 | 官方 | 兼容(可互相合并) |
设计上还吸收了 opencode-dcp 的思路(去重、清错、/dcp 命令、技术摘要),但按 dsh 的压缩接口重新实现——它服务于 opencode,dsh-dcp 服务于 dsh。
CJK 适配
内容逐字保留、不做英文转写;token 计价按 CJK 真实密度(中/日/韩/全角约 2 字符/token),不沿用宿主"4 字符/token"对中文的低估——中文会话的摘要预算反映真实成本,不会被饿死,信息更密集。
真实 dsh 会话实测
一段约 8 万 token 的历史压成约 700 token(~100x),全程零 LLM 调用;缓存命中率几乎不变(压缩后总会有一个"冷请求",任何后端都一样)。
真实会话里压缩出的检查点(中文内容逐字保留):
## Primary Request and Intent
- 帮我把登录页的重定向 bug 修掉
## Files and Code
- /app/src/auth/login.ts — W×1 R×1
## Errors and Fixes
- bash: FAIL src/auth.test.ts
## Pending Jobs
- add regression test
## Critical Context
- dsh-dcp 确定性压缩了 12 条消息 / 8 次工具调用(未调用 LLM 摘要)
Not in scope
- 不做语义归纳:不"理解"代码,只保留"出现过的事实"。需要深度语义摘要的场景,请继续用官方
compaction-basic - dsh 已经有的我们不重复做:
- 工具结果剪枝(
compaction-tool-result-pruner,确定性按大小剪) - 触发策略、保留尾巴、溢出恢复(直接继承官方;本插件仅新增轮数触发,见上)
/compact命令、UI 检查点卡片(dsh 自带)
- 工具结果剪枝(
安装
推荐:配合我们的 dsh-tui-pi 用(tui 已依赖 dsh-dcp):
npm i @aiwayds/dsh-tui-pi
dsh plugin add @aiwayds/dsh-dcp # 激活 dcp,bundle 自动挂载
独立使用:
npm i @aiwayds/dsh-dcp
npx dsh-dcp-setup # 安全脚本:带日期备份 → 只追加 → 幂等判断,不碰你已有的配置
dsh-dcp 挂在 dsh 的压缩接口上,只对挂载了它的 profile 生效。web profile 没挂 tui,继续用官方压缩,不受影响。
卸载
Bundle 方式(dsh plugin add 或列在 bundles):
dsh plugin --profile <name> remove @aiwayds/dsh-dcp
宿主自动收敛:bundles 条目移除、patch 层随包消失,官方 LLM 压缩后端 compaction-basic 自动恢复。
setup 脚本方式(npx dsh-dcp-setup 写入的 patch 块):
npx dsh-dcp-setup --remove # 默认 home patch
npx dsh-dcp-setup --remove --profile tui # 指定 profile
npx dsh-dcp-setup --remove /path/to/cordis.patch.yml
--remove 只删除 setup 写入的挂载块(含你调过的 config),修改前同样带日期备份;手工写的挂载块不受影响;删完文件为空时自动删除文件。两条 WARN 要留意:文件里若还留有 compaction-basic 的 disable 条目,官方压缩后端会保持关闭 —— 不是给 dsh-dcp 用的就手动删掉;同一文件里另一处 dsh-dcp 挂载不会被碰。
不执行反向步骤直接卸包,patch 里的绝对路径会指向已消失的安装目录,profile 启动将以 module-not-found 失败。
/dcp 命令
| 命令 | 作用 |
|---|---|
/dcp |
立即压缩(零 LLM);等同于 /dcp compact |
/dcp status |
状态:配置、压缩次数、省下的 token |
/dcp help / --help / -h |
显示命令用法 |
/dcp set <k> <v> |
会话内调参,并提示如何持久化 |
可调键:dedup、purgeErrors、maxItems、maxItemChars、maxSummaryTokens、language、tokenEstimate、thresholdRatio、roundInterval、notice、onModelSwitch、modelSwitchMinTokens。
裸 /dcp 与 /dcp compact 走同一条手动压缩缝——最常用的动作零参数直达,不必记子命令;只读或调参的动作留在显式子命令后面(看状态打 /dcp status,用法打 /dcp help)。
0.11.0 起语义变更:裸
/dcp由「显示状态」改为「立即压缩」,原来的状态输出移到/dcp status。升级后别再用裸/dcp查状态——它会直接压一次。
/dcp status 还会列出每个发生过压缩的会话(per-session 概览,含子代理),例如 per-session: session-1 (2 compactions, ~444 tokens), child (1 compaction, ~22 tokens)。压缩按会话独立计数;已销毁的会话(含 one-shot 子代理)自动从概览消失;列表封顶一行(最多前 10 个会话,超出显示 +N more)。
触发条件
| 触发 | 时机 | 说明 |
|---|---|---|
| 压力触发 | 每步请求前 | token ≥ thresholdRatio(继承上游默认 0.8;本插件 bundle 挂载默认 0.7,见配置表)× 上下文窗口 |
| 溢出恢复 | 模型报 context 超限时 | 继承官方 |
| 轮数触发 | 会话每收到 roundInterval 条 assistant message |
本插件新增;一条 = 一次 LLM 往返(每轮工具迭代各算一条,one-shot 子代理也能触发)。默认 50:第 50 条后触发第一次,之后每 50 条一次(100、150……);任何一次压缩(含压力触发)都会重置轮数时钟。到达条数后的第一个空闲点触发(阈值之下也压)。0 关闭;需保持 auto: true(默认开) |
| 模型切换 | 会话实际路由的 provider/model 变化时 | 本插件新增(onModelSwitch)。默认 notice:追加一行提醒"建议先执行 /dcp compact 压缩旧模型历史,节省 token";auto 在该会话下一个空闲点自动压缩;off 关闭。两道门控:距上次压缩不足 10 条 assistant message 忽略(没有旧账可甩),上下文不足 modelSwitchMinTokens(默认 32768,0 关闭该门)忽略(不够甩的量);auto 需保持 auto: true(默认开),否则降级为 notice |
| 手动 | /dcp(无参数)、/dcp compact、/compact |
随时可用 |
- subagent 同样生效:进程内 subagent(含 continuable 与 one-shot 子代理)走同一套事件分发,压力/溢出/轮数/模型切换对子会话独立计数、独立触发。轮数触发按 assistant message 计数,所以全程只有 1 个 turn 的 one-shot 子代理(多次工具迭代)也能触发。
- 模型切换检测原理:折叠每请求的
request/context路由快照(provider 或 model 任一变化即判定切换),覆盖所有切换入口(TUI/model、Web 客户端、默认模型设置变更);会话首个请求只播种基线不告警。notice: false只关压缩通知行,模型切换提醒行由onModelSwitch独立控制。上下文下限按宿主 tokenMeter 的实测计价(measure().surfaceTokens),测不到时 fail-open(只留轮数门控)。 - 压缩可见性:每次压缩成功后,会话里追加一行
dcp: 已压缩 N 条历史(约 X tokens,触发方式)通知行(前端渲染为折叠行)。注意该行也会作为上下文随请求发给模型(每次压缩约 15–25 tokens),且 0.4.0 起默认开启;notice: false可关闭。/dcp status的 stats 持续累计(压力触发的多次 region 提交各计一次)。
配置
全部可选,默认即用:
| 键 | 默认 | 说明 |
|---|---|---|
thresholdRatio |
0.8 | 压力触发阈值(继承上游 compaction-basic 默认 0.8;本插件 bundle patch 挂载时默认 0.7,中文场景建议 0.7) |
roundInterval |
50 | 每 N 条 assistant message(一次 LLM 往返)触发一次压缩(0 关闭)。默认 50:50、100、150……每次压缩后重数 |
onModelSwitch |
notice |
模型切换后:notice 提醒执行 /dcp compact(默认);auto 下一个空闲点自动压缩;off 关闭 |
modelSwitchMinTokens |
32768 | 模型切换提醒/自动压缩的上下文下限(按宿主 tokenMeter 实测计价):不足则忽略该次切换;0 关闭此门。默认 32k ≈ 压缩后基线(~16% 窗口)之上再涨一截才有得甩 |
notice |
true |
压缩后在会话中追加一行通知 |
language |
zh |
摘要语言;zh 额外识别中文报错和"待办:" |
tokenEstimate |
cjk |
CJK(中/日/韩/全角)按 ~2 字符/token 计价;ascii 与宿主一致 |
dedup |
true |
标注重复工具调用 |
purgeErrors |
true |
旧报错折叠成一条提示 |
maxItems / maxItemChars |
10 / 200 | 摘要密度 |
maxSummaryTokens |
2048 | 摘要 token 预算 |
升级提示(0.5.0):
roundInterval的计数单位由 completed turn 改为 assistant message——同值下触发会更频繁(一个 turn 内往往有多条 assistant message)。
内置技能 / Bundled skill
插件随包注册了 dsh-dcp-config skill(skills/dsh-dcp-config/SKILL.md,经 ctx.skills.registerProvider):在会话里让 agent 调压缩、配置 dcp 或排查压缩行为时,指南自动加载——内含 ask_user_question 交互式调参向导(先问期望再映射到具体键)与 cordis.patch.yml 挂载块 config: 段的持久化写法,无需翻文档。
设计参考
- Opencode-DCP/opencode-dynamic-context-pruning
- dsh 官方 compaction 接口:
docs/subsystems/compaction.md(deepseek-harness)
开发
npm install && npm test # 65 个用例:抽取/压缩/命令/配置/触发/安装脚本
License
MIT
liangmianya/dsh-synapse
alaliqing/claude-paper
omdsh-dev/dsh-annotation
Anionex/dsh-turn-rewind
hanshenmesen/dsh-turn-delete
qkycir-123/dsh-run2skill
Tyan66666/billion-context-dsh
PKUfudawei/dsh-capability-menu