Appearance
3.9 上下文管理:压缩与 Spill
本章概览:DSH 用两条机制治理上下文:压缩(compaction)在历史过大时把较老的范围总结为单个表面节点;Spill 把单条超大的工具输出持久化到会话作用域存储,用"预览 + 定位符"替换内联结果。二者都是 agent 循环之外的可选能力,按能力缝(capability seam)拆分为 Service Definition / Provider / Consumer 三角色。
概述 / 定位
上下文管理解决同一个问题的两端:压缩处理"历史累计过大",Spill 处理"单条工具输出过大"。两者共享两个独立服务:度量归 ctx.tokenMeter(单例),保留策略归 dsh-output-retention(库)。
压缩缝的拆分:Service Definition 是 @deepseek-ai/dsh-compaction(ctx.compaction),Provider 是 dsh-compaction-basic,人类 Consumer 是 dsh-command-compact 的 /compact 命令。与 bash 缝不同,这个 Service Definition 依赖 dsh-session 与 dsh-llm——它的动词作用在 Session 上、输出用 ContentBlock 词汇,无法不命名这些包来表达契约。Spill 缝同样三角色:Definition @deepseek-ai/dsh-spill(ctx.spillStore)、Provider dsh-spill-local、Consumer dsh-spill-policy(挂在 tools/post-execute)。
压缩:把较老历史总结为单个节点
CompactionEngine 定义"做什么"——决定历史何时太大,把较老范围总结为单个表面节点——而不规定"怎么做"。三个入口:
compactIfNeeded(agent, trigger, signal):自动策略入口,trigger为'pressure'(压力)或'context-overflow'(上下文溢出),确认的溢出可强制做一次低于正常阈值的有用平衡缩减;compactNow(agent, signal):空闲期手动压缩,即使低于压力阈值也做一次有用缩减;compactRegion(start, end, agent, signal?):按表面位置强制压缩[start, end]闭区间。
compaction/* 三个会话事件都是 log-only:compaction/start(获取锁)、compaction/summary(摘要、遮蔽区间与 seq、token 数、provider/model 包络)、compaction/end(释放锁)。SurfaceEventType 是封闭联合,只有 user/message、assistant/message、tool/result 能携带 surfaceOp,因此真正的表面变更只有一步:一个携带 source: compactCheckpointSource(compactionId) 与 surfaceOp: { op: 'replace', start, end } 的 user/message。compaction/end 最后追加,锁的括号覆盖整个操作:崩溃于其间留下可检测的孤儿锁(有 start 无 end),而不是一个谎称完成、表面却未被替换的 end。
表面位置区间 vs seq 区间:CompactionResult.shadowedRange 是表面位置跨度而非数字 seq 区间——前一次 replace 会在旧位置落下高 seq 的摘要节点,所以 start 可以大于 end;shadowedSeqs 才是按表面顺序的权威被遮蔽集合。
配对边界:切割点两侧不得有未应答的 assistant 工具调用。toolPairingBalancedBefore/After(session, seq) 校验当前表面成员资格并拒绝缺失 seq 与孤儿 result,缓存按 session.surface.replaceGeneration 失效。
出处:
packages/compaction/compaction/README.md(deepseek-harness-src/packages/compaction/compaction/README.md)
基础后端:压力、保留与总结
dsh-compaction-basic 拥有策略:用 ctx.tokenMeter 度量最新 canonical 请求包络与当前表面;保留最近的尾部预算(retainRatio 0.16 与绝对 retainTokens 互斥,且合并后的保留预算必须低于阈值 thresholdRatio 0.8,否则插件加载失败);总结是一次直接的 ctx.llm.stream() 调用(非 loop 步骤),重放会话自身系统提示、工具与被遮蔽消息以复用提供方热前缀缓存,GenerateOptions.purpose = 'compaction'(DeepSeek 适配器转发 x-deepseek-harness-compact: 1)。只有返回文本进入 checkpoint——排除会泄漏私有推理的 reasoning 与孤儿工具调用——替换消息用 <compacted-summary> 标记,后续自动周期合并先前 checkpoint。压力压缩挂在串行 agent/pre-step、请求派生之前;canonical 溢出经 agent/request-error 进入,仅在 surface.replaceGeneration 前进后授权重试。
可选的 ctx.toolResultPruner(compaction-tool-result-pruner)在区间选择前把超预算 tool/result 改写为"头 + 固定省略标记 + 尾"(thresholdChars 8192 / headChars 4096 / tailChars 1024,sourceEventSeqs 引用被遮蔽节点保证可重放),完整原事件保留在追加式日志中;修剪是模型无关的,字符预算不是 token 预算,能否解除压力仍以 ctx.tokenMeter 复测为准。
出处:
packages/compaction/compaction-basic/README.md(deepseek-harness-src/packages/compaction/compaction-basic/README.md)
手动 /compact
dsh-command-compact 通过 ctx.commands 注册参数为空的全局命令,直接调用 compactNow。busy、changed、summary、commit、persistence 映射为稳定的直接错误文本;changed/summary 不改表面,但失败尝试仍记录在日志。命令生命周期记录 log-only 的 command/run / command/done 对,不经模型轮次。
Spill:把超大输出落盘
SpillStore.saveText(input) 是唯一操作:原样持久化完整 content,返回 SpillRef(不透明定位符 locator、精确字节数 bytes、检索提示 retrievalHint);真实存储失败(权限、ENOSPC、后端不可用)时 reject,由调用方决定降级。SpillLocator 是 branded 模型侧句柄:本地后端渲染为文件路径,远程后端可为 URI、key 或命令 token,消费方用 retrievalHint 呈现而不解析它。
三角色语义:SpillOwner.sessionId 是保存时存储命名空间(fork 会话从 seed 日志继承既有定位符,不复制不重属主,fork 后新 spill 用子会话 id);SpillSource(toolName/callId/label)仅供命名与检查,不是访问控制;suggestedName 只是命名提示,永不当路径。
本地后端 dsh-spill-local 写入 <root>/session-<hash>/<random>-<safeName>:root 可配置,缺省是懒创建的私有(0700)进程级临时目录;sha256(sessionId) 短前缀分组;不可预测的十六进制前缀 + 清洗为单安全路径段的 safeName(防穿越);写入用独占属主模式 open(path, 'wx', 0o600)——任何已存在路径(含符号链接)都失败,植下的链接无法重定向。其 retrievalHint 指示模型对该路径用 read 或 grep。
消费策略 dsh-spill-policy 是 tools/post-execute 转换器:仅当最终结果超过 maxInlineBytes 且为纯文本(全 text 块)时触发;跳过嵌套执行、已接受的 value 替换与 read(避免 read→spill→read 循环)。替换物 = 保留库 head/tail 预览 + 通知 (Omitted N bytes. Full formatted result stored at: <locator>. <retrievalHint>),通知字节成本从预算预留,替换物永不超上限。Best-effort:无属主、无后端或保存失败 ⇒ 记警告并保留原内联结果——溢出失败绝不把成功调用变成 isError。另一臂监听 tools/code-dispatch-log,对每个 run_code 子调用的持久副本施加同一上限。
保留库 dsh-output-retention:TextRetainer(head/tail/headTail,UTF-8 边界在 finish() 保全)与 ItemRetainer(head,有序逻辑单元);按字节计数而非字符(进程管道与 HTTP body 是字节流);truncated 是预算事实,绝不表示"上游不完整"。
出处:
packages/spill/spill-policy/README.md(deepseek-harness-src/packages/spill/spill-policy/README.md)
关键设计决策
- 压缩与 spill 都是可选能力,词汇在子系统页而非 core;度量/保留与压缩、存储与保留/替换/检索各自分离拥有者,后端可整体替换而不动调用方。
- 表面变更只有一步
user/messagereplace:compaction/*只记录,"模型可见即已记录",回放确定性来自保留原始事件。 - 锁是持久化括号而非内存互斥:崩溃产生可检测孤儿锁。
- 配对边界只保工具调用/结果配对、不保整个 turn——允许一次超大 turn 的早期已关闭步骤被压缩。
- Spill 的 best-effort 降级:存储失败保留内联结果,安全语义优先于节省。
- 字符/字节预算不是 token 预算:
ctx.tokenMeter始终是压力的最终裁决者。
扩展点
- 新压缩后端:子类化
CompactionEngine实现三个入口并注册为ctx.compaction;模板或远程总结器可只重写summarize()钩子;checkpoint 源必须用compactCheckpointSource(compactionId)保证跨后端可识别。 - 新 spill 后端:实现
SpillStore.saveText,定位符与检索提示随后端语义(远程 URI / 数据库 key)。 - 策略调整:
dsh-compaction-basic的modelPolicies按精确 provider/model 覆盖阈值与保留;auto: false关闭自动监听只留手动;spill-policy 的maxInlineBytes省略即禁用整个策略。 - 保留映射:按工具选择
TextRetainer/ItemRetainer与 head/tail/headTail 策略(glob/grep/bash/web_fetch/web_search 各有既定映射)。
参考资料
- packages/compaction/compaction/README.md — 压缩 Service Definition(
deepseek-harness-src/packages/compaction/compaction/README.md) - packages/compaction/compaction-basic/README.md — 基础后端策略与配置(
deepseek-harness-src/packages/compaction/compaction-basic/README.md) - packages/compaction/compaction-tool-result-pruner/README.md — 工具结果修剪(
deepseek-harness-src/packages/compaction/compaction-tool-result-pruner/README.md) - packages/compaction/command-compact/README.md — /compact 命令(
deepseek-harness-src/packages/compaction/command-compact/README.md) - packages/llm/token-meter/README.md — 固定启发式度量(
deepseek-harness-src/packages/llm/token-meter/README.md) - packages/spill/spill/README.md — spill Service Definition(
deepseek-harness-src/packages/spill/spill/README.md) - packages/spill/spill-local/README.md — 本地文件后端(
deepseek-harness-src/packages/spill/spill-local/README.md) - packages/spill/spill-policy/README.md — spill 消费策略(
deepseek-harness-src/packages/spill/spill-policy/README.md) - packages/util/output-retention/README.md — 保留库(
deepseek-harness-src/packages/util/output-retention/README.md) - docs/subsystems/compaction.md — 压缩子系统参考(
deepseek-harness-src/docs/subsystems/compaction.md) - docs/subsystems/spill.md — spill 子系统参考(
deepseek-harness-src/docs/subsystems/spill.md) - compaction capability-seam Agent Note(
deepseek-harness-src/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md) - tool output spill Agent Note(
deepseek-harness-src/.agents/notes/implemented/architecture/2026-07-08-tool-output-spill-files.md)