Skip to content
dsh.fish
Bundle

dsh-headroom

Headroom-inspired automatic context compression plugin for DeepSeek Harness (dsh): compresses tool outputs before they reach the model and keeps every lossy compression reversible via CCR retrieval tools.

Source
giter00
stars
8 stars
License
Apache-2.0
Updated
Updated 8 days ago

Readme

# dsh-headroom

> 适配 **DeepSeek Harness (dsh)** 的上下文自动压缩插件,思路参考
> [Headroom](https://github.com/headroomlabs-ai/headroom)。

工具输出在进入模型之前先被压缩:JSON、搜索、日志、表格与长文本各自走专用压缩器;
所有**有损压缩**都会把原文存入本地 CCR store,并在压缩结果里注入一个短 marker,
模型需要精确原文时调用 `headroom_retrieve(id=…)` 即可逐字节取回。

```text
 tool body settles
        │
        ▼
 tools/post-execute   ← dsh-headroom 在此压缩
        │
        ▼
 tool/result 进入 session log / 模型历史(压缩后内容 + CCR marker)
        │
        ▼
 模型需要原文时调用 headroom_retrieve(id=…)
```

## 特性

- **自动压缩工具输出**:挂载 `tools/post-execute`,在工具结果物化之前替换文本内容。
- **内容路由,专用压缩器**:

  | 内容类型 | 压缩策略 |
  |----------|----------|
  | JSON 数组/对象 | SmartCrusher 风格透视:`_keys` + `_rows` + `_common`,长单元格截断 |
  | grep/ripgrep 结果 | 按文件折叠:`file (N matches)` + `line[:col]: rest` |
  | 构建/测试/日志 | 连续重复行折叠 + 保留 `error/fail/exception/assert` 上下文 |
  | CSV/TSV/markdown 表格 | 保留表头与首尾行,中间行 offload |
  | 长文本 | **Kompress 风格 ML 压缩**(默认):逐词打分 + must-keep 保护 + CCR 可逆取回;`textStrategy: 'head-tail'` 可切回首尾截断 |
  | 代码 | **默认不压缩**(JS 端口不做 AST 压缩,避免破坏可补丁字节;`read`/`str_replace_editor` 的行号前缀会先剥离再识别) |
  | 文件工具 | **默认不压缩**(`read`/`str_replace_editor`/`edit`/`write` 及其匹配 `*.js/*.ts/*.json/*.yml` 的路径) |

> **Kompress 文本压缩**(参考 [Headroom](https://github.com/headroomlabs-ai/headroom) 的
> [Kompress-v2-base](https://huggingface.co/chopratejas/kompress-v2-base) ML 模型):
> 文本按词切分 → 每词打分(`score = keep概率 × (0.5 + 0.5 × span分数)`,模拟模型的
> token 分类头 + span CNN 双头)→ `score > 0.5` 保留(或 `targetRatio` 取 top-k)→
> 数字 / hex / 全大写标识符 / 路径 / 扩展名 / CLI flag / CamelCase 等**语义脆弱词强制保留**
> → 保留词重组。默认评分器是确定性纯 JS 启发式;也可启用**真实 Kompress-v2-base
> ONNX 模型**打分(`kompress.scorer: 'onnx'`,见下文「真实模型压缩」)。

- **可逆压缩(CCR)**:所有有损压缩都保存原文,`headroom_retrieve` 按 id 精确取回;
  `headroom_stats` 查看节省量;`headroom_compress` 压缩任意文本。
- **持久化**:CCR store 默认写入 `<DSH_HOME>/storages/dsh-headroom-ccr.json`
  (1 秒去抖、原子替换、TTL + 最大条目数可配)。
- **无害跳过**:短文本、代码、错误输出、`excludeTools` 命中的工具、本插件自身工具
  都不会被压缩。
- **跨平台**:纯 JavaScript + Node 内置模块,无原生编译依赖;路径全部通过
  `node:path` 处理,`DSH_HOME` 支持环境变量覆盖,Windows / macOS / Linux 行为一致。
  CI 矩阵见 [`.github/workflows/ci.yml`](./.github/workflows/ci.yml)。

## 实现方式

```mermaid
flowchart LR
  A[ToolRuntime 工具执行完成] --> B[tools/post-execute]
  B --> C{文本块总长 >= minChars?}
  C -- 否 --> Z[原样返回]
  C -- 是 --> D[ContentRouter 类型检测]
  D --> E[json] --> E1[SmartCrusher 透视]
  D --> F[search] --> F1[按文件折叠]
  D --> G[log] --> G1[重复折叠 + 错误保留]
  D --> H[tabular] --> H1[首尾行保留]
  D --> I[text] --> I1[Kompress 逐词打分 + must-keep 保护]
  I1 -. 无收益 .-> I2[回退首尾截断]
  D --> J[code] --> Z
  E1 & F1 & G1 & H1 & I1 & I2 --> K{压缩后 + marker 更小?}
  K -- 否 --> Z
  K -- 是 --> L[写入 CCR store]
  L --> M[替换 decision.content]
  M --> N[模型看到压缩内容 + headroom_retrieve marker]
```

- `lib/compress.js`:纯函数压缩器,无 `node:*` 依赖,可独立测试。
- `lib/kompress.js`:Kompress 风格文本压缩管线(word 级评分 + must-keep 保护),
  参考 Headroom 的 Kompress-v2-base ML 模型;评分器可插拔(默认纯 JS 启发式)。
- `lib/ccr.js`:CCR store,内存 Map + 去抖持久化到 `<DSH_HOME>/storages/`。
- `lib/index.js`:dsh 插件入口,注册 `tools/post-execute` 监听器与三个工具。
- `dsh.plugin.json` + `cordis.patch.yml`:dsh 插件/bundle 清单与补丁。

## 压缩效果

### 压力测试配置(更激进,用于验证压缩器上限)

`node scripts/verify-compress.mjs` 在 `minChars=120, maxRows=40, maxCellChars=80, maxTextChars=400` 下的结果:

| 样本 | 类型 | 压缩前(字符) | 压缩后(字符) | 节省 |
|------|------|--------:|--------:|-----:|
| JSON 数组 200 行 | json | 62 491 | 9 302 | **85.1%** |
| grep 结果 270 条 | search | 10 772 | 4 603 | **57.3%** |
| 日志 180 行 | log | 3 909 | 1 125 | **71.2%** |
| CSV 201 行 | tabular | 19 814 | 3 029 | **84.7%** |
| 长文本 400 段 | text | 29 506 | 546 | **98.1%** |
| Kompress 长文本(事实+重复词) | text | 16 439 | 2 029 | **87.7%** |
| 代码 | code | 493 | 493 | 0%(故意不压) |
| 短文本 | text | 19 | 19 | 0%(未达阈值) |

> token 估算:脚本按 `chars / 4` 粗估,实际 token 与模型 tokenizer 相关。
> 所有有损压缩均保存原文,`headroom_retrieve` 可精确取回。
> Kompress 样本:关键事实(`HTTP`/`500`/hex/路径/`IndexError`)全部保留,
> 重复的 `boilerplatephrase` 被删除且可从 CCR 恢复。

### 真实模型压缩(Kompress-v2-base · ONNX)

v0.3.0 起可选用真实模型替代启发式评分器:

```jsonc
{
  "kompress": {
    "scorer": "onnx",
    "onnx": {
      "modelDir": "~/.dsh/storages/dsh-headroom-model/kompress-v2-base",
      "hfLocalDir": "~/.dsh/storages/dsh-headroom-model/hf"
    }
  }
}
```

- **下载模型**(huggingface.co 不可达时可用 hf-mirror.com):
  `onnx/kompress-int8-wo.onnx`(261MB,推荐)、`tokenizer.json`(3.4MB)、
  `config.json`、`tokenizer_config.json`、`special_tokens_map.json`
  来自 [chopratejas/kompress-v2-base](https://huggingface.co/chopratejas/kompress-v2-base);
  后四个文件同时复制一份到 `hfLocalDir/kompress-v2-base/` 供分词器加载。
- **依赖**:`pnpm add -D onnxruntime-node @huggingface/transformers`(可选依赖,
  未安装或模型缺失时自动回退启发式并告警)。
- **自动校准**:导出模型的融合分数普遍偏高(≈0.7–0.99),阈值 0.5 几乎全保留;
  插件在 onnx 模式且用户未显式配置 `targetRatio`/`scoreThreshold` 时自动改用
  top-k `targetRatio=0.55`。
- **实测**(`node scripts/kompress-onnx-eval.mjs`,int8 CPU):压缩率全面高于启发式
  且事实保留 100%(英文长文 28.4% vs 19.1%、中英混排 8.6% vs 0%、QA 文档 32.5% vs
  17.1%);吞吐约 100–400 词/秒(启发式 ≈40 万词/秒),适合只压大输出;重复压缩
  有界收敛、marker 防重入生效。

### 默认配置

默认配置更保守(`minChars=4000, maxRows=80, maxCellChars=200, maxTextChars=2400`):

| 样本 | 类型 | 节省 |
|------|------|-----:|
| JSON 数组 200 行 | json | 65.6% |
| grep 结果 90 条 | search | 41.3% |
| 日志 180 行 | log | 56.8% |
| CSV 201 行 | tabular | 59.8% |
| 长文本 400 段 | text | 94.7% |

### 不损害效果的验证

`node scripts/verify-compress.mjs` 同时断言:

1. 结构化输出中的关键事实(JSON 键/计数、文件分组、`ERROR/WARN` 行)在压缩后仍可见;
2. 代码、短文本、错误输出保持字节不变;
3. 每个有损压缩的原文都能通过 `headroom_retrieve` **逐字节取回**;
4. 长文本中间被省略的 `NEEDLE-42` 事实,压缩视图不可见,但 CCR 能精确恢复;
5. Kompress 压缩后 `HTTP`/`500`/`0x1f4d2a8b`/`/var/log/app.log`/`IndexError` 等
   语义脆弱事实仍可见,重复的 `boilerplatephrase` 被删除且可经 CCR 恢复。

`node scripts/verify-apply.mjs`(需要能解析 `@deepseek-ai/dsh-tools`)进一步验证:

- `apply()` 注册了 `tools/post-execute` 监听器和 3 个工具;
- 大 grep 输出在进入模型前被压缩并带 marker;
- `headroom_retrieve` 取回原文与压缩前完全一致;
- `fs-*` 排除工具、自身工具、代码、错误、短输出全部原样。

## 安装

### 环境要求

| 项目 | 要求 |
|------|------|
| Node.js | `>= 22.0.0`(推荐 Node 22 LTS 或更高) |
| DeepSeek Harness | `>= 0.0.1-rc.5 < 0.2.0-0`(含 0.1.x 预发布) |
| 包管理器 | 推荐 `pnpm >= 11`;`npm` / `yarn` 也可用于本地开发 |
| 操作系统 | Windows / macOS / Linux(纯 JS,无原生编译) |

### 一键安装(推荐)

直接从 GitHub 仓库安装(Windows / macOS / Linux 通用):

```bash
dsh plugin --profile web add github:giter00/dsh-headroom
```

如果 `dsh` 不在 PATH 上,可先定位 profile 内的 CLI 再执行同一命令:

```bash
# Windows PowerShell
node "$env:USERPROFILE\.dsh\profiles\node_modules\@deepseek-ai\dsh\lib\bin.js" plugin --profile web add github:giter00/dsh-headroom

# macOS / Linux
node "$HOME/.dsh/profiles/node_modules/@deepseek-ai/dsh/lib/bin.js" plugin --profile web add github:giter00/dsh-headroom
```

> pnpm 会在安装时拉取 GitHub 仓库的默认分支(`main`),并自动把
> `dsh-headroom` 追加到 profile 的 bundle 列表。

### 手动安装

也可以直接编辑 `<DSH_HOME>/profiles/web/package.json`:

```jsonc
{
  "dependencies": {
    "dsh-headroom": "github:giter00/dsh-headroom"
  },
  "dsh": {
    "profile": {
      "bundles": [
        // ...其他 bundles
        "dsh-headroom"
      ]
    }
  }
}
```

然后进入 profile 目录安装依赖:

```bash
cd "$DSH_HOME/profiles/web"      # Windows PowerShell: cd $env:DSH_HOME\profiles\web
pnpm install
```

重启 dsh 后生效。

### 卸载

```bash
dsh plugin --profile web remove dsh-headroom
```

## 配置

在 profile 的 `cordis.patch.yml`(或 `--patch` 覆盖层)中可覆盖默认配置:

```yaml
- id: dsh-headroom
  config:
    enabled: true
    minChars: 600
    maxRows: 80
    maxCellChars: 200
    maxSearchMatchesPerFile: 60
    maxLogLines: 80
    maxTextChars: 2400
    maxTabularLines: 80
    excludeTools: []
    noFoldForTools: ['read', 'str_replace_editor', 'edit', 'write']
    noFoldForPatterns: ['*.js', '*.ts', '*.json', '*.yml', '*.yaml']
    markerStyle: full          # full | compact
    includeErrors: false
    textStrategy: auto        # auto | kompress | head-tail
    kompress:
      enabled: true
      minWords: 10
      chunkWords: 350
      scoreThreshold: 0.5
      targetRatio: null       # null=阈值决策;0.3=强制保留 30% 最高分词
      mustKeep: true
      maxWordChars: 64
    ccr:
      enabled: true
      persist: true
      ttlMs: 86400000
      maxEntries: 2000
```

| 字段 | 默认值 | 说明 |
|------|--------|------|
| `enabled` | `true` | 总开关 |
| `minChars` | `600` | 文本块至少多少字符才考虑压缩 |
| `maxRows` | `80` | JSON 透视保留的最大行数 |
| `maxCellChars` | `200` | JSON 单元格字符串截断长度(search 匹配行保持全文) |
| `maxSearchMatchesPerFile` | `60` | 每个文件保留的搜索命中数 |
| `maxLogLines` | `80` | 日志保留的首尾行数 |
| `maxTextChars` | `2400` | 长文本首尾保留字符数(head-tail 策略) |
| `maxTabularLines` | `80` | 表格保留的首尾行数 |
| `excludeTools` | `[]` | `*` 通配符;命中的工具不压缩 |
| `noFoldForTools` | `['read','str_replace_editor','edit','write']` | 文件内容类工具永不压缩,避免 read→edit 快照不一致 |
| `noFoldForPatterns` | `['*.js','*.ts','*.json','*.yml','*.yaml']` | 匹配到的文件路径/工具名不压缩;保护源码与配置文件 |
| `markerStyle` | `'full'` | `full`=保留策略/节省量与 `headroom_retrieve` 提示;`compact`=只保留 `id="hr:…"`,减少标记噪音 |
| `includeErrors` | `false` | 是否压缩工具错误输出 |
| `textStrategy` | `'auto'` | 长文本策略:`auto`=Kompress 优先、无收益回退 head-tail;`kompress`=仅 Kompress;`head-tail`=仅首尾截断 |
| `kompress.enabled` | `true` | `false` 时文本走 head-tail |
| `kompress.minWords` | `10` | 少于该词数的文本跳过(与 Headroom 一致) |
| `kompress.chunkWords` | `350` | 每块词数(Kompress-v2-base 训练口径,与模型耦合) |
| `kompress.scoreThreshold` | `0.5` | 保留阈值:`score > 阈值` 才保留(与 Headroom 默认一致) |
| `kompress.targetRatio` | `null` | 强制保留比例(按分数取 top-k);`null` 用阈值决策 |
| `kompress.mustKeep` | `true` | 语义脆弱词(数字/hex/全大写/路径/扩展名/flag/CamelCase)强制保留 |
| `kompress.maxWordChars` | `64` | 超过该长度的词(如无空格中文长串)细分后评分 |
| `ccr.enabled` | `true` | 关闭后不进行有损压缩 |
| `ccr.persist` | `true` | 是否持久化 CCR store |
| `ccr.ttlMs` | `86400000` | 原始内容保留时长(毫秒) |
| `ccr.maxEntries` | `2000` | 内存/持久化 store 最大条目数 |

## 模型可见工具

| 工具 | 参数 | 作用 |
|------|------|------|
| `headroom_retrieve` | `id` | 取回被压缩工具结果的完整原文 |
| `headroom_compress` | `text` | 压缩任意文本,返回策略与压缩结果 |
| `headroom_stats` | 无 | 查看本进程压缩统计 |

压缩后的 tool result 会携带如下 marker:

```text
[headroom: search-fold 12345→987 chars; headroom_retrieve(id="hr:0123456789abcdef")]
```

## 项目结构

```text
dsh-headroom/
├── lib/
│   ├── index.js          # dsh 插件入口:post-execute 钩子 + 3 个工具
│   ├── compress.js       # 内容路由与确定性压缩器(纯 JS,无 node:* 依赖)
│   ├── kompress.js       # Kompress 风格文本压缩管线(词级评分 + must-keep 保护)
│   └── ccr.js            # CCR store:内存 + 去抖持久化
├── scripts/
│   ├── verify-compress.mjs   # 压缩效果 / 信息保留 / CCR 可逆验证
│   └── verify-apply.mjs      # apply() 集成冒烟(需要 dsh-tools 可解析)
├── tests/
│   └── compress.test.js      # 单元测试
├── dsh.plugin.json           # dsh 插件清单
├── cordis.patch.yml          # bundle patch
├── package.json
├── README.md
├── README.en.md
├── CONTRIBUTING.md
├── LICENSE
└── NOTICE
```

## 开发与验证

```bash
# 语法检查
node --check lib/index.js && node --check lib/compress.js && node --check lib/ccr.js

# 单元测试(无需 harness 依赖)
node tests/compress.test.js

# 压缩效果 + 信息保留 + CCR 可逆验证(无需 harness 依赖)
node scripts/verify-compress.mjs

# apply() 集成冒烟(需要 @deepseek-ai/dsh-tools 可解析,
# 例如链接 dsh checkout 的 node_modules)
node scripts/verify-apply.mjs
```

## 已知限制

- **默认评分器是启发式模拟,不是真实模型推理**:`lib/kompress.js` 忠实移植了
  Headroom Kompress-v2-base 的管线结构与评分公式,但默认打分来自确定性纯 JS 启发式;
  需要真实模型语义打分时,可库级注入 ONNX/PyTorch scorer。
- **Kompress 输出是保留词碎片**:为追求高压缩率,默认阈值会删除大量普通词,输出可读性
  有限,适合给模型看要点;精确原文始终可通过 `headroom_retrieve` 逐字节取回。
- **保守不压缩场景**:全部由 must-keep 类词组成的文本、纯重复中文文本会直接走
  head/tail 回退或原样返回,防止把内容删光。
- **模板文本不去重**:高频重复的数字/标识符会逐个保留(must-keep 语义),模板化输出
  可能保留较多重复事实 token,压缩率低于普通散文。

## 与 Headroom 的差异

| 维度 | Headroom | dsh-headroom |
|------|----------|--------------|
| 集成方式 | proxy / wrap / MCP / SDK | dsh 原生插件,直接挂 `tools/post-execute` |
| JSON | SmartCrusher(Rust core) | JS 透视压缩(`_keys`/`_rows`/`_common`) |
| 代码 | AST CodeCompressor | 默认跳过(保证可补丁字节安全) |
| 文本 | Kompress-v2-base ML 模型(ONNX/PyTorch) | **同款 Kompress 管线**;默认纯 JS 启发式 scorer,v0.3.0 起支持 `kompress.scorer: 'onnx'` 直连真实模型(见「真实模型压缩」) |
| 可逆性 | CCR | 本地 CCR store + `headroom_retrieve` |
| 原生依赖 | 部分 extra 需要(onnxruntime/torch) | 无(默认启发式);接入真实模型时才需要外部依赖 |

## License

[Apache-2.0](./LICENSE)

本项目是从 [Headroom](https://github.com/headroomlabs-ai/headroom)(Apache-2.0)
改造而来的衍生作品,因此沿用 Apache License 2.0 发布,以保持许可证一致性并满足
上游合规要求。版权与上游归属见 [NOTICE](./NOTICE)。

## 致谢

本项目的设计思路与压缩策略参考
[Headroom](https://github.com/headroomlabs-ai/headroom)(Apache-2.0)。

Install

dsh plugin --profile web add github:giter00/dsh-headroom#ca5de630fd9a4be1b0e0f900cc3260f52052019d

Profile: web

Source