npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-compaction-instant

v0.1.3

Published

VCC-style instant, near-lossless deterministic compaction engine for the DeepSeek Harness — a drop-in replacement for @deepseek-ai/dsh-compaction-basic

Readme

dsh-compaction-instant

DeepSeek Harness 打造的即时、近无损上下文压缩引擎——装上就能直接替换官方引擎 @deepseek-ai/dsh-compaction-basic,用 lllyasviel/VCC 的"对话编译"思路取代原来的 LLM 摘要。

对话太长了怎么办?普通方案是让模型把旧内容"总结"一遍(慢、花钱、还会丢细节)。本引擎不总结,而是把旧内容重新整理成一份紧凑的存档(后面统称"检查点"):毫秒级完成、不调用模型、只使用原来的原文,不改写、不编造。被收进存档的内容随时可以原样找回来。

主要特性

  • 免 LLM——压缩过程完全不调用模型:没有摘要请求、没有推理等待、不花 token。它只是确定性的文本处理,哪怕一百万个 token 的历史也是毫秒级搞定。
  • 近无损——存档里只有原文;每处被省略的内容都有标记并注明出处(seq 序号),之前的存档会原封不动地保留。
  • 即时——把旧内容扫描一遍就完成;不联网、不调模型、不占 KV 缓存。
  • 完全兼容的替换——对外接口、事件、计费和报错方式都和官方引擎一致;内置预设不用改任何东西就能用(见"别名安装")。

示例

一段包含用户提问、助手回答 + 工具调用及其结果的历史,压缩后长这样:

[user]
please fix the bug
[assistant]
on it
* read "a.js" (seq 2 -> result 3)
[user]
next question

每个工具调用只占一行:白名单里的工具(toolArgTools)显示关键参数,其他工具只显示名字(* job_kill (seq 9 -> result 10)),hideTools 里列的工具完全不出现。工具结果不占位置——通过 -> result N 指针,用一次 recall(type:"result") 就能取回。较长的用户/助手文本按预算截断,并在末尾标注 ...(truncated from seq N);每处省略都写明了完整内容存在哪个事件里。

Recall:把丢掉的内容找回来

本包还配套了"找回"能力——同一会话内的回读,模型和人都能用。因为会话日志只增不改,编译器省略过的每一个字都还在,随时可取:

| 入口 | 模块 | 作用 | |---|---|---| | recall 工具(给模型用) | dsh-compaction-instant/tool | 按类型恢复原文:type:"seq" 配合 (seq N)/(seqs A-B) 标记,type:"result" 配合 result N 指针,type:"checkpoint" 配合 [checkpoint N] 序号——把原始内容一字不差地恢复到当前工具结果里 | | search 工具(给模型用,grep) | dsh-compaction-instant/tool | 在整个持久日志里按关键词/正则搜索——包括被压缩掉的内容——返回带 (seq N) 指针的匹配事件,可直接交给 recall 取回 | | /recall 命令(给人用,grep) | dsh-compaction-instant/command | /recall <关键词|正则> 追加一条持久的用户消息,内含匹配事件和 seq 指针,下一轮模型就能看到 | | 共享核心 | dsh-compaction-instant/recall + dsh-compaction-instant/search | seq 解析(123-7seq 12 / seqs 3-7)、日志展开、预算、字段筛选;正则编译与命中展示 |

Recall 能取回一切:文本、推理过程、工具调用的完整参数、嵌套的工具结果;只在日志里出现过的事件会以带标签的原始数据展示;找不到的 seq 会明确报错。maxRecallTokens 预算(默认 16000)超限时会截断并标注来源、统计跳过多少;搜索限制展示条数(maxSearchHits,默认 50)。这两个插件是独立的一行,可以挂在任何压缩引擎旁边——它们只读日志,不依赖本引擎。

每个检查点开头还附了一段简短的 RECALL 使用指南,告诉模型怎么用 recall / search 找回被省略的内容。如果更早的检查点因为空间不够被省略,它不会无声消失:会留下一行 [checkpoint N](N 是压缩序号,1 = 最早),用 recall(type:"checkpoint", id:"N") 就能完整恢复。

配置

所有配置项都可选,括号里是默认值。

| 键 | 默认 | 含义 | |---|---|---| | thresholdRatio | 0.5 | 上下文用到多大比例时自动触发压缩(0.5 = 用到一半) | | retainRatio | 0.05 | 对话最新的一段(按窗口比例)一字不差地保留,不压缩 | | retainTokens | — | 直接指定保留多少 token;与 retainRatio 二选一 | | manualRetainRatio | 0.05 | 手动 /compact 时保留当前对话的比例(保证正在聊的内容不会被收走) | | manualRetainTokens | — | 手动模式直接指定保留 token 数;与 manualRetainRatio 二选一 | | auto | true | 开启自动压缩:监听 agent/pre-step 压力事件和 agent/request-error 溢出恢复 | | maxTokens | 8192 | 单个检查点总预算的下限(按内容密度估算的 token) | | checkpointScale | 0.1 | 实际预算 = max(maxTokens, 被压缩掉的 token 数 × checkpointScale),再封顶于 checkpointCap——内容很多时不会把每条都压成一句话 | | checkpointCap | 65536 | 检查点预算的封顶值 | | textTokens | 512 | 每条助手文本的预算 | | userTextTokens | 1024 | 每条用户文本的预算 | | toolCallTokens | 128 | 每个工具调用单行的预算(这个永远不缩放——见下面的省略规则) | | toolResultExcerptTokens | 256 | 仅为兼容官方配置而接受;不起作用——工具结果本来就不占位置 | | includeReasoning | false | 是否在检查点里保留推理过程 | | stripNoiseXml | true | 是否去掉用户文本里配置的噪音标签 | | noisePatterns | 见 compiler | 噪音标签的正则来源,按 s 模式匹配 | | toolKeyFields | 内置 | 额外的"工具名 → 参数里的关键字段"映射,用于单行展示 | | toolArgTools | 见 compiler | 白名单:这些工具的关键参数会显示在单行里(read/write/edit/glob/grep/bash/shell/web_search/skill/subagent/…);其余工具只显示名字 | | hideTools | — | 完全从检查点里去掉的内部管理工具 | | modelPolicies | — | 按 provider/model 单独覆盖 thresholdRatio/retain*(与官方配置格式一致) | | compactionRetries / maxOverflowRetries | 1 / 1 | 重试次数,含义和官方引擎一样 | | summarizationProvider / summarizationModel | — | 仅为兼容官方配置而接受;不起作用——本引擎从不调用模型 |

recall 工具和命令插件各自接受 { maxRecallTokens?: 16000, maxSearchHits?: 50 } 配置。

Cordis 配置坑: 插件行的配置要经过 schemastery schema 校验,它的 ~standard 适配器会给每个没写的数组项注入 []toolArgToolshideToolsnoisePatternstoolKeyFieldsmodelPolicies)。本引擎把空数组当作"没设置",会回退到默认值——所以不写 toolArgTools 就自动用内置白名单(千万别用 toolArgTools: [] 想关掉它;空 = 默认)。debug: true 会把每次压缩的诊断写进 debugLogPath 指定的文件(默认 $DSH_HOME/compaction-debug.log)。

预算有两道保险:按 token 数限制,再按"预算 × 4"的字符数限制——所以再长的连续字符串(base64 大块、压缩过的文件)也绕不过去。工具调用永远是单行:不会缩放,预算不够时只压缩对话文本(每条最少留 32 token)。如果压缩结果还是超过(缩放后的)预算,先删最旧的工具行[N tool/result entries elided: seqs a-b]),再删其余最旧的条目([N earlier entries elided: seqs a-b])——工具调用永远挤不掉对话。最新的内容总能保住。

分词与多语言

分词器是简单的字符规则:连续的英文字母算一个 token,连续数字算一个,标点一个字符一个,空格免费,其他每个字符算一个。具体:

| 内容 | Tokens | |---|---| | 中文(你好,世界!) | 每个字 1(共 6) | | 西里尔 / 阿拉伯文 | 每个字符 1 | | 带重音拉丁文(café) | 英文部分成组(caf + é) | | Emoji(😀) | 2(一个 emoji 占两个 UTF-16 单元) |

所有截断都发生在字符边界——绝不会把一个 emoji 从中间切开(有 test/multilang.test.js 保证)。字符数上限按 UTF-16 长度算,对 emoji 这类字符偏保守。

另外,Harness 自带的 token 计量器(用于"压缩后必须变小"的检查、/compact 的用量报告)用的是另一套 字符数 / 4 + 固定开销 的估算,两套算法故意并存——详见设计说明。

保证

  • 即时——把旧内容扫描一遍就完成;不联网、不调模型、不占 KV 缓存。
  • 近无损——输出里只有原文;每处省略都有标记并注明出处 seq;之前的检查点原封不动保留。
  • 完全兼容的替换——接口、事件、计费(走同一个 ctx.tokenMeter)和报错方式与官方引擎一致,包括"压缩后必须变小"的检查(如果压缩完反而没变小,会被拒绝)。
  • 可选 pruner 兼容——和官方引擎一样会使用可选的 toolResultPruner 服务(它负责整理保留部分;被压缩的旧内容由本引擎自己处理)。

实测压缩率(真实会话、一条不丢)

数据来自真实会话日志(本项目的开发会话),编译时不丢弃任何一条——每条都保留,只做条目级截断和工具调用单行化。百分比是相对原文 token 数的比例。

| 负载 | 原文 tokens | 编译后 | 保留 | 压缩 | |---|---|---|---|---| | 工具密集会话全量(3,181 节点:1,438 个工具调用 + 1,540 个工具结果) | 2,523,012 | 226,205 | 9.0% | 91.0% | | 另一个会话全量(864 节点) | 685,088 | 62,705 | 9.2% | 90.8% | | 同一个工具密集会话,最近 800 条消息 | 625,927 | 45,031 | 7.2% | 92.8% | | 纯文本(同一会话去掉全部工具行) | 160,963 | 109,945 | 68.3% | 31.7% |

压缩主要来自哪里(不丢条目的情况下):

  • 工具结果零成本——结果不产生条目,靠 -> result N 指针一个 recall 就能取回,这是最大的来源。
  • 工具调用一行化——每个调用压成一行(≤ 128 tokens,平均约 100)。
  • 思考过程不保留——reasoning 增量整体省略(有标记,不是悄悄丢)。
  • 对话文本近乎无损——纯文本对照组保留了 68.3%;文本上那约 1.5 倍压缩基本是剥掉 JSON 包装,外加只截断最长的几段。

预算扫描(同一个 252 万 tokens 的工具密集会话):从 cap ≈ 22.6 万 tokens(原文的 9%,正好接近默认 checkpointScale 0.1,但被 64K 硬顶截断)才开始丢条目。低于这个值代价是悬崖不是斜坡

| Cap | 编译后 | 保留 | 条目数 | 被丢 | |---|---|---|---|---| | 8,192 | 8,243 | 0.33% | 111 | 2,090 | | 32,768 | 22,263 | 0.88% | 232 | 1,969 | | 65,536(部署默认) | 55,737 | 2.2% | 325 | 1,876 | | 65,536 | 55,737 | 2.2% | 325 | 1,876 | | 131,072 | 131,047 | 5.2% | 1,142 | 1,058 | | 226,205(一条不丢的临界值) | 226,205 | 9.0% | 2,199 | 0 |

安装

下面三种方法都用 Harness 自带的插件管理器安装(包发布在 npm,名字 dsh-compaction-instant;插件管理器会在 profile 目录里跑 pnpm,装完后宿主配置和每个 agent preset 都能找到它):

dsh plugin --profile web add <spec>

/compact 命令(dsh-command-compact)和用哪个引擎无关,任何安装方式下都照常工作。

方法 1 —— 顶替内置引擎(别名安装)

dsh plugin --profile web add "@deepseek-ai/dsh-compaction-basic@npm:dsh-compaction-instant"

dsh 目前没法让你选压缩引擎,内置预设(standardcodecordis)在配置里写死了包名 @deepseek-ai/dsh-compaction-basic。要让这些内置预设用上本引擎,就顶替内置插件:预设配置里的包名是从 profile 的 node_modules 解析的(优先级高于 Harness 自带的安装),所以把本包装到内置这个名字下面,所有内置预设就会自动加载本引擎——不动任何预设文件,预设以后升级也不受影响。

这样顶替是天然安全的:本引擎和官方引擎对外完全兼容——同一个 ctx.compaction 接口、完全相同的依赖注入列表llmtokenMetersessions)、相同的事件和报错方式,官方配置里的每一个键也都接受。把别名依赖删掉就恢复官方的引擎。

这种安装方式不会被识别成 bundle(Harness 会从自己的安装目录解析 @deepseek-ai/dsh-compaction-basic 这个名字,那里是官方包,没有 dsh.bundle 声明),所以没有任何自动化——需要把 recall 工具和 /recall 命令自己加进 profile 的 cordis.patch.yml(新行必须放在 insert 列表里;这个文件热重载,不用重启)。行名必须用别名包名(这种安装方式下只有它能解析);引擎行可选,只在需要给"没有压缩配置的预设"(如 minimal)提供宿主兜底时才加:

- id: compaction-basic
  disabled: true                     # 宿主层替换(可选兜底)
- insert:
    - id: compaction-instant
      name: '@deepseek-ai/dsh-compaction-basic'   # 给没有压缩配置的预设兜底
    - id: tool-recall
      name: '@deepseek-ai/dsh-compaction-basic/tool'
    - id: command-recall
      name: '@deepseek-ai/dsh-compaction-basic/command'

方法 2 —— 直接安装 + 让 AI 复制一份预设(dsh 创作模式)

dsh plugin --profile web add dsh-compaction-instant

然后用"预设创作"预设(内置的 cordis 预设,即「创造模式」)开一个会话,让 AI 执行:

复制 standard 预设,把它的压缩引擎行换成 dsh-compaction-instant

AI 会用 agentPresets.copy('standard', '<id>') 创建一份本地预设,在副本里改掉压缩行的 name,用 standingKeyFor('<id>') 校验能不能正常挂载,还可以通过改 agent-presets 行(config.default: <id>)把它设为默认。新预设会出现在 UI 选择器里;内置预设不受影响。

从 v0.1.1 起,本包还声明了 dsh.bundle,所以直接安装会自动注册成 profile 的配置层:自动禁掉内置的摘要引擎行、自动插入本引擎和 recall 工具(见包内 cordis.patch.yml)。宿主这边不用手动配置,只需复制预设。

方法 3 —— 直接安装 + 手动配置预设

dsh plugin --profile web add dsh-compaction-instant
mkdir -p "$DSH_HOME/.agent-presets/<id>"
# 从你想作为基础的内置预设复制配置和元数据
# (预设列表里能看到每个预设的真实路径):
cp <built-in-preset>/agent.cordis.yml "$DSH_HOME/.agent-presets/<id>/agent.cordis.yml"
# 在旁边写 preset.yml,包含 name + description

然后手工编辑副本里的压缩组——只改一行 name,仍在同一个隔离域(realm)里:

- id: compaction
  name: cordis:group
  group: true
  isolate:
    compaction: true
    toolResultPruner: true      # pruner 必须和引擎在同一隔离域
  config:
    - id: compaction-instant
      name: dsh-compaction-instant   # 原来是 '@deepseek-ai/dsh-compaction-basic'
    - id: command-compact
      name: '@deepseek-ai/dsh-command-compact'
    # ... 保留 pruner 行

规则:绝不改内置预设的安装文件;保留 isolate 隔离域;真正的检验是 standingKeyFor 挂载成功(或直接在预设上开一个会话)——预设列表里的 broken 标记只能发现解析错误。

方法 2 和 3 不需要任何宿主配置行:上面提到的 dsh.bundle 会自动注册好一切。

| 方法 | 内置预设里的引擎 | 要改预设文件吗 | 选择器里多出预设 | 安装成本 | |---|---|---|---|---| | 1. 别名替换 | ✅ 自动(standard/code/cordis) | 否 | 否 | 一条命令 + 手动 patch | | 2. AI 复制副本 | 只有新预设 | 副本 | 是 | 一句提示 | | 3. 手动预设 | 只有新预设 | 副本 | 是 | 手动编辑 |

每个上下文只能挂载一个 ctx.compaction 实现(接口文档写明"每个上下文加载一个实现");预设挂载各自有独立的隔离域,所以宿主和预设的实例永远不会冲突。

开发

npm test        # node --test(编译器单元测试、配置校验、会话集成、引擎)
npm run check   # 对所有源码做 node --check

本包依赖很少:@deepseek-ai/schemastery 用于配置校验;其余依赖都是 Harness 自己提供的。src/compiler.js 刻意零依赖,没有运行中的 Harness 也能单独跑单元测试。

和官方引擎的区别

  • 不调摘要模型 → 压缩从几秒变成几毫秒;不花摘要的 token。
  • 不改写 → 事实、文件路径、命令、变量名都一字不差;模型继续用自己的话接着聊。
  • 确定性 → 同样的内容永远压缩出同样的检查点。
  • 之前的检查点原样保留,而不是重新摘要一遍(又快又无损)。
  • 手动 /compact 会保留最近的一小段原文(manualRetainRatio,默认保留当前对话的 0.05)而不是压缩全部历史,正在聊的内容永远不会被收走;只有更早的部分进检查点。
  • compaction/summary 事件携带压缩后的条目本身——UI 里可展开的检查点行显示的就是模型实际看到的内容,外面包一层能自动变长的代码框(框线永远比内容里的 ``` 长,所以含 markdown 的消息也能整齐地显示成一个代码块),检查点开头还有一段简短的使用指南,告诉模型怎么用 recall / search 找回被省略的内容。
  • 权衡:对以长对话、叙述为主的历史,检查点的信息密度可能不如 LLM 摘要(长句是截断而不是合并)。正在进行的对话有逐字保留的尾部(自动 retainRatio 和手动 manualRetainRatio)兜底,其余内容都能通过 (seq N) 指针 + recall 找回来。

MIT 许可证。