dsh-block-ptc
Model-directed context compaction for PTC mode, grouping program runs into blocks and replacing completed block messages with model-written summaries.
Install
dsh plugin --profile web add dsh-block-ptc
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-block-ptc
[English](README.md) | 中文



给 DeepSeek Harness 的 PTC 模式加「黑板块」。
0.4.0 使用 block_compact({ ids, content }),不兼容旧的 block_summary
工具及 summary/单个 id 参数。更新后重启 DSH,并新建 Block PTC 会话。
区块协议使用内置 run_code 传输层。DSH 的 PTC 呈现只允许直接调用
run_code,所以区块归属写在工具描述的开头:
run_code({ description: "[block: <ids>] <goal>", code })
一个区块就是黑板上的一块区域。模型跑的每段程序都会带上区块 id。当区块内容不再
需要,或相关结果已经汇报且准备转向其他工作时,可以提交自己整理的保留内容替换
区块消息。仍需用于执行、回复或讨论的内容应继续保留。原始消息仍保留在
只追加的会话日志里,人类看到的对话记录不变,重放也是确定性的。
- DeepSeek Harness 0.2.1-rc.2 或更新,不设版本上限
- 社区插件,维护者 mengwEX
- 零运行时依赖:唯一的外部导入是
node:crypto - 许可证:MIT
目录
- [为什么做这个](#为什么做这个)
- [上下文与缓存对比](#上下文与缓存对比)
- [工作原理](#工作原理)
- [安装](#安装)
- [快速上手](#快速上手)
- [接口参考](#接口参考)
- [设计说明](#设计说明)
- [验证](#验证)
- [排障](#排障)
- [已知边界](#已知边界)
- [开发](#开发)
- [许可证](#许可证)
为什么做这个
自动压缩在 token 压力上来时压缩历史,它按大小决定压什么,并不知道前四十条消息是
一个已经完成的子任务、后十条是新任务。
这个插件让模型自己划线:开一个区块、在里面干活、用一段交接总结收口——于是保留
下来的上下文就是模型选择保留的那一段。总结由模型在程序调用里提交,插件不另跑
一个总结模型。
上下文与缓存对比
这是机制示意,不是 API 基准测试。 两个面板重放同一段合成四任务负载,token
权重相同。整条 = 输入上下文;蓝色 = 建模的缓存命中;橙色 = 建模的缓存未命中。
被缓存的 token 仍然占用上下文窗口。
区块收口后,下一次请求用一段总结替代已完成的工作。替换历史也可能让缓存后缀
失效:上下文变小并不保证缓存命中率更高或账单更低。收口前会等 assistant/tool
对落定;原始用户消息保留。基线尚未触发自动压缩阈值。
数据、假设与复现步骤见 [docs/context-comparison/README.md](docs/context-comparison/README.md)。
插件返回的 tokensFreed 不是服务商的缓存命中指标。
工作原理
模型看到的直接工具就是内置 PTC 传输层,再加一个程序内可调用的工具:
run_code({ description: "[block: <ids>] <goal>", code }) 唯一可直接调用的工具
await tools.block_compact({ ids, content }) 在程序内部调用
1. run_code.description 开头的区块头声明这段程序推进哪些区块。id 归属覆盖整条
assistant 消息(包含工具调用前的 thinking/content)及对应工具结果;同一消息内
多个调用的 id 取并集。
2. tools.block_compact({ ids, content }) 用整理后的保留内容替换从最早到最晚一次出现
目标 id 的完整区间。
3. 总结继承「区间内 id 的并集减去本次收口的 id」。它可以再次参与后续总结;没有
剩余 id 的总结节点也会保留。
4. 区间里的工具对还没完成时,请求先排队,等结果落定再执行。区间里出现受保护的
system/developer 消息会拒绝整个区间,不会只替换前缀。
A A B A C B -- compact([A]) --> S[B] C B S[B] C B -- compact([B]) --> T[C] T[C] -- compact([C]) --> U[] A A B A C B -- compact([A, B]) --> S[C]
人类看到的仍是完整对话(日志只追加);模型下一次请求看到的是总结。Web UI 里
总结显示为压缩检查点节点。
安装
要求:DeepSeek Harness >=0.2.1-rc.2 及其自带运行时,Cordis >=4.0.5。
两个 peer 范围都没有上限。插件是一个 profile bundle:安装后往
dsh.profile.bundles 加一行,并新增一个 agent preset block-ptc;不会改动
自带的 ptc preset。
版本范围只说明「允许新宿主加载」,不等于已完成兼容性验收。本版本的实机验收使用
DSH 0.2.1-rc.2。DSH 的插件加载器评估 peer 范围时包含预发布版本。插件在挂载前
检查所需的工具/提示词方法,在总结前检查会话方法,缺失时报错。方法存在不等于事件
语义、preset 配置或模型行为已经验证;宿主变化时仍需要重新验收。
从 npm 安装(推荐)
在 Harness 的 Plugin Manager 里找到 dsh-block-ptc 安装,或让启用了 Plugin
Manager 工具的 agent 安装:
plugin_manager install_bundle dsh-block-ptc
包已发布在 npm。安装后重启应用,
选择 Block PTC preset。
从本地目录安装
git clone https://github.com/mengwEX/dsh-block-ptc.git
在 Plugin Manager 里安装绝对路径:
plugin_manager install_bundle /absolute/path/to/dsh-block-ptc
两种方式都会在目标 profile 里用 pnpm 安装。本地方式装成 link: 依赖,适合开发。
带版本号的源码包也放在 GitHub Releases。
手动安装(等价做法)
在 ~/.dsh/profiles/<profile>/package.json 里:
{
"dependencies": { "dsh-block-ptc": "link:/absolute/path/to/dsh-block-ptc" },
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-block-ptc"] } }
}
然后在该目录运行 pnpm。
安装之后
1. preset 选择器里出现 Block PTC。
2. 重启一次应用。 加载器按解析后的 URL 缓存插件模块,安装 bundle 会改变组合;
运行中的宿主会继续用旧模块,直到重启。
3. 用 Block PTC preset 新建会话。
卸载
plugin_manager remove_bundle dsh-block-ptc
然后重启。plugin_manager set_bundle dsh-block-ptc enabled=false 可以只停用、
不卸载。
快速上手
先完成工作并讨论结果;之后转向其他工作、原始内容不再需要时,再整理之前的区块:
讲清 tokenizer 怎么工作。
讨论完之后:接着看 lexer;之前的区块如果已不需要原始内容,就整理一下。
你应该看到:
- 模型每次跑程序都用带区块头的
run_code,例如
[block: tokenizer] Explain the tokenizer;
- 一次
block_compact收口调用,返回值类似
{"replaced": 3, "tokensFreed": 346}——替换了多少条消息,以及被替换消息的
估算 token 数(不含新总结本身);
- 原位置出现一个
<block-summary>…</block-summary>节点。
首次请求的系统提示、原生工具描述和参数 schema 都会说明区块头要求,SDK 使用说明
也使用相同格式。
如果程序调用被拒绝并提示 "Every run_code call, including the first",
那是 preset 的 guard 在工作:带上区块头重试即可;
被拒绝的那次调用本身不会被归属到任何区块。
接口参考
按相对独立的工作内容组织区块,继续处理同一内容时复用原有 id。区块内容已不再
需要,或相关结果已经向用户汇报且准备转向其他工作时,可以整理并收口。仍需用于
接下来的执行、回复或讨论的内容应继续保留。不要仅因某个工作步骤完成就收口。
run_code.description 里的区块头
部分 · 类型 · 必填 · 含义
[block: <ids>] · 头部 · 是 · 逗号分隔、非空、不重复的区块 id,例如 [block: auth] 或 [block: auth, parser]。id 不能包含逗号、方括号或换行。
<goal> · string · 是 · 头部之后同一行里的目标,显示为工具行的摘要。
run_code 本身是 DSH 的工具,插件不替换它。code/timeoutMs 参数、沙箱、
并行调度和结果渲染都与内置 PTC 完全一致。插件会对齐模型可见的区块头说明,
读取区块头并给周围消息打归属。
可调用 tools.block_compact
参数 · 类型 · 必填 · 含义
ids · string[] · 是 · 要整理并收口的区块 id。
content · string · 是 · 由模型撰写,整理这些 id 从第一次到最后一次出现的完整内容。后续仍需使用的信息应完整保留,保证可以直接继续工作;不再需要的内容可以简要概括,无关或重复内容可省略。准确保留用户要求、修正和约束,写清已完成的工作、结果、未完成事项和下一步。
替换文本会说明这是模型从先前工作中整理保留的信息,并包在
<block-summary>…</block-summary> 里。只有还有剩余归属时才出现 Block ids
一行;空 ids 留在内部元数据里。这个格式与 DSH 自动压缩分开,二者可以共存。
立即完成时返回 { replaced, tokensFreed, ids? };ids 非空时表示总结继承的
剩余归属。tokensFreed 是被替换消息的估算大小,不含新总结的成本。
如果工具结果或另一个压缩还没结束,返回
{ replaced: 0, tokensFreed: 0, pending: true, requestSeq, note }。这只表示
已排队,不代表替换完成。成功的工具结果会写入日志,重启/分叉后可以继续完成;
延迟执行失败会记录日志,目标归属保留到真正替换为止。目标 id 不存在或区间含受保护
消息时,整个请求被拒绝,不会删除任何归属。
预设 block-ptc
自带 ptc preset 加上:
- 与自带 preset 相同的
tool-presentation.mode: ptc,因此宿主的 PTC 收窄规则
继续生效:只有 run_code 可以直接调用;
- 本插件的行:一条 guard,要求每次模型直接调用的
run_code都带
`
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::8,最后更新 2026-10-21