# DSH 结构化交接压缩 面向小上下文模型的 DSH 上下文压缩插件:压缩大小可视化配置,默认 8k 交接摘要 + 16k 最近上下文,完整历史仍可查询。 `dsh-handoff-compaction` 把较早的对话压缩成结构化交接摘要,保留最近消息的原文,完整历史则可以随时搜索和读取。模型继续工作时能看到目标、进展、决策、约束、下一步和验证状态;需要找回旧细节时,再按需查询历史。 **压缩后的上下文预算由你决定。** 在 Web 插件详情页直接调整摘要 token 上限和最近消息保留预算,默认 **8192 + 16000 token(8k + 16k)**,支持保存和恢复默认,重启后仍保留。接近阈值时自动压缩,也可以用 `/compact` 手动触发。尤其适合小上下文窗口的本地模型:按窗口大小调整预算后,长时间开发、排错和多轮协作也能持续推进。 ## 主要功能与优势 当前任务留在上下文里,较早细节留在可查询的历史里: | 你需要保住的能力 | 这个插件如何处理 | | --- | --- | | 压缩大小可视化配置 | 在插件页面分别设置摘要上限与最近上下文预算,默认 8k + 16k。保存后用于后续压缩,重启仍保留;小窗口模型可调低预算,大窗口模型可保留更多原文。对应配置项是 `maxTokens` 和 `retainTokens`。 | | 对缓存友好的全量上下文压缩 | 摘要请求重放**当前完整会话表面**,保持相同的 system prompt 和 tools,并在末尾追加交接指令;不会先把提示词截短到待摘要的较早部分。这样,即使本地模型服务无法复用“截短后的提示词”,原有前缀仍有机会复用。实际缓存命中取决于服务端,可查看 `cacheReadTokens`。 | | 不丢失长期记忆 | 历史事件仍是只追加记录。被压缩遮蔽的内容可通过官方 SQLite 历史工具按需搜索和读取。 | | 任务持续推进 | `Context Handoff` 记录当前在做什么、已经完成什么、接下来做什么,并保留关键事实和验证状态。 | ```text 长会话 → 结构化交接 + 最近原文尾部 → 小窗口模型继续当前工作 → 需要旧事实时,按需检索完整历史 ``` 插件不扩大模型原生上下文窗口。固定预算分别作用于摘要输出和最近消息保留,不代表整个请求严格等于某个 token 数:系统提示词、工具定义、完整消息边界和工具调用配对也会占用空间,小窗口配置时需要为这些内容留出余量。 ## DSH 版本兼容 同一个插件包兼容全部声明支持的 DSH 版本,用户直接按包名安装,无需按 DSH 版本挑选插件包。 | DSH 版本 | 支持与验证情况 | | --- | --- | | `0.2.2-alpha.2` | 支持;本次验证 Web/headless 安装启动、压缩、历史查询、预算热更新,以及配置接口保存与重启保留。 | | `0.2.1-rc.3`、`0.2.1-rc.4` | 支持;CI 验证 Web/headless 安装启动。 | | `0.2.1-rc.2` | 支持;此前验证 Web/headless 安装启动、压缩、历史查询、预算热更新,以及配置接口保存与重启保留。 | | `0.2.1-rc.1` | 支持;CI 验证 Web/headless 安装启动。 | | `0.2.1-alpha.4`、`0.2.1-alpha.5` | 声明兼容;本次未逐一实测。 | | `0.2.1-alpha.3` | 支持;此前验证 Web/headless 安装启动、压缩、历史查询、预算热更新,以及配置接口保存与重启保留。 | | `0.2.1-alpha.2` | 支持;此前验证 Web/headless 安装启动、压缩、历史查询、预算热更新,以及配置接口保存与重启保留。 | | `0.2.1-alpha.1` | 支持;此前验证 Web/headless 安装启动、压缩、历史查询、预算热更新,以及配置接口保存与重启保留。 | | `0.2.0-rc.2` | 支持;此前验证可视化保存、恢复默认、重启保留、Web/headless 安装启动,以及压缩和历史查询工具。 | | `0.2.0-rc.1` | 支持;此前验证可视化保存、恢复默认、重启保留与 Web/headless 安装启动。 | | `0.1.7-rc.2` | 支持;此前验证可视化保存、恢复默认、重启保留与 Web/headless 安装启动。 | | 此前声明支持的其他 DSH 0.1 预发布版本 | 声明兼容;本次未逐一重新验证。 | 截至 2026-10-28,npm 的 `latest` 指向 `0.2.1-rc.2`,`next` 指向 `0.2.1-rc.4`,`alpha` 指向 `0.2.2-alpha.2`。插件使用同一个包兼容这些发布通道。`engines.dsh` 与 DSH peer 范围保持一致,供新版插件管理器判断兼容性。新版已移除的 invariant 诊断模块不再作为插件依赖。 新版的预算保存与重启保留通过配置接口验证,页面点击交互未在本次更新中重新实测。 DSH 0.1 peer 范围:`^0.1.1-rc.2 || ^0.1.2-rc.1 || ^0.1.5-rc.2 || ^0.1.7-alpha.2`。 插件自身的 Node.js 范围:`^22.19.0 || >=24.0.0`;DSH `0.2.2-alpha.2` 要求 **Node.js >=24.9.0**,使用该宿主版本时需满足其更高要求。列表区分声明支持与实测记录,DSH 后续新版发布后会继续核验。 ## 安装 从 npm 安装时直接使用包名;声明兼容范围内的 DSH 版本使用同一个包。本地目录或 tarball 的安装方式见下方[其他包来源](#其他包来源)。 把 Bundle 直接添加到需要启用它的 DSH profile: ```sh dsh plugin --profile web add dsh-handoff-compaction dsh plugin --profile headless add dsh-handoff-compaction ``` add 命令完成后,按正常方式重启对应 profile。重启只负责重新载入 profile,不是额外的设置步骤;无需选择 Handoff Preset,也无需运行插件专用设置命令。 ### 验证 profile(只读) 重启后可使用以下标准的 profile 范围只读验证命令;这不是第二次设置步骤: ```sh dsh plugin --profile web list --depth 0 dsh plugin --profile headless list --depth 0 dsh --profile web --dump-config dsh --profile headless --dump-config ``` 对应的 `list` 输出必须显示 `dsh-handoff-compaction` 已安装。每个 `--dump-config` 输出中,确认活动的 `handoff-compaction` 条目使用 `dsh-handoff-compaction`,并保留已记录的默认值和历史配置:`thresholdRatio: 0.8`、`retainTokens: 16000`、`maxTokens: 8192`。同一份 dump 还必须显示可见的 SQLite 后端条目 `@deepseek-ai/dsh-session-query-sqlite`,其中包含 `openAt: first-search` 和 `session-query.sqlite`。五个运行时历史工具作为改编自 `@deepseek-ai/dsh-tool-session-query` 的代码包含在本插件中,不是用户应在该条目中查找的可见的 SQLite 后端名称。这些命令只检查已经安装的 profile,不会安装、配置或启用任何内容。 安装会替换整个 profile 的压缩配置。Bundle patch 会禁用 `compaction-basic` 和 `tool-result-pruner`,保留 `command-compact`,并同时注入本压缩器与官方 SQLite 后端;数据库位于 `$DSH_HOME/session-query.sqlite`,使用 `openAt: first-search`。 V1 确认的默认值是: ```yaml thresholdRatio: 0.8 retainTokens: 16000 maxTokens: 8192 compactionRetries: 1 maxOverflowRetries: 1 auto: true ``` ### 可视化调整上下文预算 Web 界面打开左侧 **插件 → dsh-handoff-compaction**,在插件详情页即可调整: - **交接摘要上限**:默认 **8192 token(8k)**,控制摘要生成上限。 - **最近上下文预算**:默认 **16000 token(16k)**,保留近期对话原文。 点击 **保存** 后写入当前 profile,后续压缩使用新预算,重启后仍保留。点击 **恢复默认 8k + 16k** 会填入默认值,再点保存生效。完整历史始终可搜索、读取和追溯。 摘要上限须为正整数,最近上下文预算须为非负整数。完整消息和工具调用配对可能使保留量略超预算;系统提示词和工具定义还会占用上下文。小窗口模型应适当降低预算,并留出输出和系统信息的空间。 如果原配置使用 `retainRatio`,保存此面板会切换为固定的 `retainTokens`。配置文件中的 `modelPolicies` 按模型覆盖仍优先于通用预算。面板接入 DSH 原生权限和配置冲突检查;部署不允许配置写入时显示只读。 可视化配置支持 DSH `0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-alpha.1`、`0.2.1-alpha.2`、`0.2.1-alpha.3`、`0.2.1-alpha.4`、`0.2.1-alpha.5`、`0.2.1-rc.1`、`0.2.1-rc.2`、`0.2.1-rc.3`、`0.2.1-rc.4`、`0.2.2-alpha.2`。Headless 或较早版本可在当前 profile 的 `cordis.patch.yml` 调整 `handoff-compaction` 条目的 `maxTokens`、`retainTokens`;默认 Web 文件为 `$DSH_HOME/profiles/web/cordis.patch.yml`,未设置 `DSH_HOME` 时使用 `~/.dsh`。 ### 其他包来源 所有支持的包来源都使用同一个 `dsh plugin --profile add ` 接口。下面以 Web profile 演示 npm、GitHub、本地目录和打包 tarball;安装到 Headless 时把 profile 名替换为 `headless`: ```sh dsh plugin --profile web add dsh-handoff-compaction dsh plugin --profile web add github:knighthongyu/dsh-handoff-compaction dsh plugin --profile web add ./dsh-handoff-compaction dsh plugin --profile web add ./dsh-handoff-compaction-0.2.0-rc.9.tgz ``` ## 可搜索的历史,而不是被遗忘的历史 Bundle 会把改编自 MIT 授权的官方 `@deepseek-ai/dsh-tool-session-query` 的五个工具与压缩器一起注入: - `session_search` - `session_event_search` - `session_trace` - `session_event_trace` - `session_event_read` 这里遵循 **no automatic RAG / no automatic retrieval**:只有代理判断旧工作相关时才调用工具。官方 SQLite 全文索引在第一次搜索时延迟生成到 `session-query.sqlite`。压缩只会让旧事件退出当前上下文表面,不会改写事件;因此 `session_event_search` 仍能找到被压缩遮蔽的事实,`session_event_read` 能返回完整原事件,同时继续执行 workspace 授权隔离。 Existing sessions(已有会话)仍保持只追加。安装插件只影响后续上下文选择和压缩,不会重写历史事件;第一次检索打开或更新索引后即可查询旧记录。 ## 移除与可选旧文件清理 使用标准命令从各 profile 移除插件激活: ```sh dsh plugin --profile web remove dsh-handoff-compaction dsh plugin --profile headless remove dsh-handoff-compaction ``` 移除后,正常重启对应 profile。DSH 随后会回到剩余的 profile Bundle 配置;如果基础 profile 提供了原生压缩器,则恢复使用该压缩器。 移除时 must not delete(绝不能自动删除)会话日志、`session-query.sqlite` 或用户文件;其中可能包含可恢复历史或用户修改。只有在检查内容并完成所需备份后,才可人工删除。 可选的旧文件清理仅适用于旧版本曾创建 `handoff-standard`、`handoff-code` 或 `handoff-cordis` 目录的情况。请先确认它们是旧版生成副本而不是用户自有内容,再手动删除。该清理不属于当前安装或移除流程。 ## 失败边界 摘要取消、流错误、空重放输入、Handoff 结构错误、全 `(none)`、缺失可恢复工作状态、图片输出或达到 max-token 都会 fail closed:不提交替换摘要,选中的原始 surface 保持当前状态。当提供方返回无效 Markdown 或 tool calls 时,插件会在同一压缩事务内立即进行一次恢复调用,并使用更强的指令。两次调用重放相同的 system prompt、tools 和源消息前缀;在同一 provider/model 路由上,还会继承会话已持久化的 `reasoningEffort`、`temperature` 和 `stop`,使模型实际渲染的提示词前缀保持缓存对齐。摘要专用的 `maxTokens` 上限仍独立生效,两次尝试之间只改变简短的最终恢复指令。配置了不同摘要路由时无法复用会话路由的提供方缓存,也不会错误继承该路由专用控制项。 每次摘要完成后都会记录不含正文的诊断信息,包含 `cacheAlignment`、路由、请求控制项是否存在、尝试次数和提供方返回的 token 使用量(包括可用时的 `cacheReadTokens`)。校验失败时记录同类安全元数据和错误码;两类日志都不包含对话或摘要正文。 成功交接后仍保留最近原文尾部,较早事件继续存在于只追加历史中。必须禁用 `tool-result-pruner`,避免工具结果被另一条链路单独且不可逆地剥离。安装本修复不会自动修正已经提交的全 `(none)` checkpoint;这类既有会话需要从 shadowed events 显式恢复。 ## 开发 使用 pnpm 安装依赖、检查类型、运行测试,并构建预编译的 `lib/` 输出: ```sh pnpm install pnpm typecheck pnpm test pnpm build ``` npm 包不含生命周期 hook,并直接发布预构建运行时;安装包时不会执行构建或设置脚本。 ### 贡献者发布门禁 维护者可运行与 CI 相同的本地发布验证: ```sh pnpm check pnpm check:package pnpm smoke:dsh pnpm verify:release ``` `check:package` 会在临时目录创建真实 tarball,输出文件名、SHA-256 和文件列表,然后清理该文件。`verify:release` 组合类型检查/构建/测试、归档审计与隔离的 Web/headless 冒烟门禁。这些仅是贡献者验证;普通用户仍只需使用上面的标准单条 `dsh plugin --profile add ` 命令安装。