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

@xiaobanli/dsh-compact-after-task

v0.1.2

Published

Auto-compact a DSH conversation after the current task finishes, at a user-set context threshold. Settings-page switch + slider included.

Readme

dsh-compact-after-task

一个针对 DSH(DeepSeek Harness,Cordis 插件体系)的插件:当前任务执行完毕后,若上下文压力达到你设定的阈值(默认 50% 的路由模型上下文窗口),自动压缩一次会话历史。装上它,你就不用再手动点压缩、也不用眼睁睁看着上下文和成本一起膨胀。

开关和阈值都可以在 设置 → 插件 里直接调(开关 + 滑块),改完立即生效、无需重启

它解决的痛点

长对话里,模型每轮都要把完整历史重新发一遍。随着对话变长,几个问题越来越明显:

  • 不压缩 → 成本爆炸。 上下文越大,每轮回传的 token 越多。哪怕提供方有 KV 缓存(缓存命中价比全新输入便宜),这些历史每一轮都要重新传输、重新计费。对话从几万 token 滚到几十万、上百万,单轮成本跟着翻几倍——越聊越贵,而且是在不知不觉中
  • 手动压缩又烦又容易忘。 /compact 或界面上的压缩按钮确实能用,但每次都要记得自己去点;而人总是等到"明显变慢、明显变贵"才想起来,那时几轮大额开销已经花出去了。
  • 内置自动压缩太晚,还卡在任务中途。 内置的 dsh-compaction-basic 要等到上下文用到 80%、并且只在 step 边界(任务进行中)才触发——到那个点你已经为好几轮巨型请求付过费了,而且压缩会打断手头正在干的事。
  • 响应越来越慢。 前缀越长,每次请求的处理时间越长,体感明显变卡。

这个插件把"记得去压缩"这件事自动化:每次任务跑完(agent 回到 idle)自动检查压力,达到你设的阈值就压一次——在成本开始痛之前就处理,而不是痛了之后才补救。

它和内置压缩的关系(互补,不冲突)

| | 内置 dsh-compaction-basic | 本插件 | |---|---|---| | 触发时机 | 每个 step 边界(agent/pre-step),任务中途 | 任务彻底跑完(agent 回到 idle)之后 | | 阈值 | thresholdRatio 固定 0.8 | thresholdRatio 用户可设,默认 0.5 | | 定位 | 任务中途的最后兜底 | 日常的"任务之间自动瘦身" |

压缩动作与 /compact 完全同款:调用 ctx.compaction.compactNow(),生成一个 <compacted-summary> 检查点,对话界面照常显示"已压缩 N 条历史记录"卡片。

环境要求

  • DSH Desktop / DSH profile,且带有基础 bundle(dsh-base),其中包含 dsh-compaction-basicdsh-token-meterdsh-agentdsh-llm
  • 核心自动压缩功能任何版本都能用。设置页卡片(开关 + 滑块)需要 DSH ≥ 0.1.0-rc.7(2026-08-17 发布):rc.7 起 Host 自动把每个已注册的 settings 命名空间暴露给网页端,第三方插件的设置卡片开箱即用,这正是官方机制。rc.6 及更早版本里命名空间白名单是硬编码的,第三方命名空间会被拒绝(settings-not-exposed)——请升级;确实无法升级时,才用下面第 5 步的补丁。
  • rc.7 起本插件改为通过 agentPresets.serviceFor() 访问压缩服务,不再 inject: ["compaction"] 原因:rc.7 引入 agent-presets 架构后,compaction 服务不再由 host 平面提供,而是由 agent preset(standard/cordis 等)在 isolate realm 里为每个会话挂载;host 平面的插件若 inject: ["compaction"] 会永远 pending(waiting for service: compaction)。本插件在 agent 回到 idle 时用官方 READ 接口 ctx.agentPresets.serviceFor(agent, "compaction") 取该 agent 的实例(该接口正是为"请求关于某个 session、但从外部到达"的调用者设计的);rc.6 及更早版本自动回退到 ctx.get("compaction")
  • 客户端卡片能显示的前提:包的 exports 必须放行 "./package.json": "./package.json" dsh-client-modules 扫描 client bundle 时用 require.resolve("<包名>/package.json") 读取包的 dsh.client 元数据;一旦声明了 exports 字段而没放行 ./package.json,该调用会抛 ERR_PACKAGE_PATH_NOT_EXPORTED,被永久静默缓存为"非客户端包"——插件 host 侧正常启动,但设置卡片永远不出现。官方包都在 exports 里带这一行。

安装

两种方式,二选一(不要混用:重复插入同一 entry id,加载器会拒绝启动)。

方式 A:标准安装 —— 插件市场 / dsh plugin add(推荐)

本包自带 dsh.bundle.patch,指向包内的 cordis.patch.yml,是一等公民的 bundle:通过市场或 CLI 安装时,它会被加进 profile 的 dsh.profile.bundles,下次启动时加载器自动应用包自己的补丁层——完全不需要手动改任何配置

# 从 npm(发布后)—— 或直接从 GitHub:
dsh plugin --profile desktop add @xiaobanli/dsh-compact-after-task
dsh plugin --profile desktop add github:xiaoliang2/dsh-compact-after-task

或者在桌面端 设置 → 插件市场 里一键安装。重启 DSH Desktop 即完成。

方式 B:手动安装(本地 profile,不需要市场、不需要发布)

  1. 把本包复制进 profile,并让 profile 的 node_modules 能解析到它(与 dshmarket 的安装方式一致):

    # 在 DSH home 下执行,例如 C:\Users\you\.dsh\profiles\desktop
    Copy-Item -Recurse <path-to>\dsh-compact-after-task .\plugins\dsh-compact-after-task
    New-Item -ItemType Junction -Path .\node_modules\@xiaobanli\dsh-compact-after-task -Target .\plugins\dsh-compact-after-task
  2. 在 profile 的 cordis.patch.yml(用户补丁层,在每个 bundle 层之后应用)中插入插件行:

    - insert:
        - id: compact-after-task
          name: '@xiaobanli/dsh-compact-after-task'
          config:
            enabled: true
            thresholdRatio: 0.5
  3. 在 profile 的 package.json 中声明依赖,防止以后 pnpm install 把它清掉:

    "dependencies": {
      "@xiaobanli/dsh-compact-after-task": "file:plugins/dsh-compact-after-task"
    }
  4. 重启 DSH Desktop,profile 变更才会生效。

如果已经用手动方式 B 装过,请先卸载/移除,再走市场安装;否则同一个 entry id compact-after-task 会被插入两次,加载器拒绝启动。

仅 DSH ≤ 0.1.0-rc.6 需要(无法升级时才做)

rc.7 之前 Host 只暴露一份硬编码的命名空间白名单,因此要让设置卡片能读能写,得先把本插件的命名空间加进去(应用安装目录下两处文件,位于 resources\app.asar.unpacked\node_modules\@deepseek-ai\dsh-host-apiproxy):

  • lib/index.js —— 在 const WEB_SETTINGS_NAMESPACES = [ ... ](约第 888 行)里加 "compact-after-task",
  • lib/types/api-proxy.js —— 在单行的 const WEB_SETTINGS_NAMESPACES = [...](约第 50 行)里加 "compact-after-task"

然后重启。注意 DSH 升级会覆盖这两个文件,每次升级后要重打。rc.7+ 不需要这个补丁,且这两个文件已不存在于新版。

配置项

| 键 | 类型 | 默认值 | 含义 | |---|---|---|---| | enabled | boolean | true | 总开关。 | | thresholdRatio | number (0.05–1) | 0.5 | 上下文压力达到该比例(相对路由模型 context window)时压缩;0.5 = 50%。 | | onlyRoots | boolean | false | 只压缩顶层对话 agent(跳过后台 subagent)。 |

设置页调节(开关 + 滑块)

装好后,在 设置 → 插件 → 可配置插件 里会有一张"自动压缩"卡片:

  • 开关:是否在任务结束后自动压缩;
  • 滑块:自动压缩阈值(5%–100%,步进 5%)。

拖动滑块松开即保存,settings/updated 事件实时生效,无需重启。设置值持久化在 settings 文档里,优先于 cordis.patch.yml 里的加载器配置(加载器配置作为默认值/基础层)。

阈值怎么选

按"你能接受的单轮回传上限 ÷ 模型上下文窗口"来定:

  • DeepSeek 默认 1M 窗口:0.3~0.6 都是合理区间,0.5 是保守稳妥的默认值;
  • 想让单轮回传 ≤ 40 万 token → 0.4;≤ 25 万 → 0.25;
  • 别设 ≥ 0.8:内置压缩会在 0.8 的 step 边界先触发,你的阈值设得比它还高就失去意义;
  • 小窗口模型(128K/64K)建议 0.6~0.8,否则有效工作上下文会被压没;
  • 阈值太低(如 0.1 以下)意味着刚干完小事就压一次,摘要把还有用的细节也吞了,得不偿失。

调完跑一两轮长任务看体感:刚干完小事就压缩、摘要变粗糙 → 阈值太低;每条消息还是回传大几十万 token → 阈值太高。改 cordis.patch.yml 里的 thresholdRatio 后重启生效。

行为细节

  • 监听 agent/status 事件,只在 idle 状态转换时动作 —— 也就是本轮任务的驱动器已完全排空,正是"执行完本次任务再压缩"的时机,不会打断任务。
  • 压力口径与内置引擎一致:tokenMeter.measure(session).totalTokens 对比 contextWindow × thresholdRatio(context window 通过 llm.resolveModelInfo 解析)。
  • 压缩是一次 ctx.compaction.compactNow(agent, signal) 调用 —— 与 /compact 完全同一操作;compactNow 会保留下一次轮次的入场权,后续消息会被正确地排在压缩完成之后。rc.7 起 ctx.compaction 换成 agentPresets.serviceFor(agent, "compaction") 取得的实例,操作不变。
  • 预期内的失败静默处理:busy(agent 忙 / 已有压缩在跑)与 cancelled 直接跳过;其余失败仅记 warn,不影响 agent 生命周期事件。
  • 若某 agent 挂载的 preset 不包含 compaction 组(如 minimal),serviceFor 返回 undefined,该 agent 自动跳过压缩。

测试

npm install
node test-compact-after-task.mjs

单测用桩服务覆盖:空闲+超阈值触发、低于阈值不触发、running 不触发、busy 静默、disabled 完全不动作、onlyRoots 过滤 subagent。

许可证

MIT