canonical history(会话事实,不被改写);request history(每次请求前的复制快照,可压缩);transcript(摘要前保存的 canonical 快照);tool-result artifact(大结果的完整内容)。
canonical history 会话事实,不会被请求压缩改写
request history 每次请求前复制,可被 snip/micro/摘要
↓
大结果在写入 canonical 之前先落盘为 artifact
canonical 里存 <persisted-tool-result> 路径与预览
一条 assistant 可含多个 tool_calls,它与全部 tool results 组成不可拆分原子组。snip 的保留边界、micro 的替换单位、摘要保留的尾部都用组。
assistant(tool_calls=[call_a, call_b])
tool(tool_call_id=call_a)
tool(tool_call_id=call_b)
→ 一个原子组,整组保留或整组省略
单项严格大于 30,000 bytes 才落盘(恰好等于仍保留在消息里);未落盘合计仍大于 200,000 时,按字节从大到小挑最大的落,够用就停。消息保留相对路径、original_bytes、头尾各最多 2,000 bytes 预览;预览按 byte 截断,装不下的多字节字符整字丢弃。
const contentBytes = Buffer.from(result.content, "utf8");
const sizeBytes = contentBytes.byteLength;
snip:>50 组时保留前 3 组 + [Compacted] 标记 + 后 46 组。micro:保留最近 3 个工具交换组,更早结果替换为 [Earlier tool result compacted. Re-run if needed.]。注意 micro 对短结果反而可能让历史变长——它是为几 KB 以上的结果设计的,规则简单且结果确定。
snip:
50 组阈值 → 前 3 组 + 省略标记 + 后 46 组
micro:
保留最近 3 个工具交换组;更早结果替换为占位符
(不删 assistant 调用,不改 tool_call_id)
先保存 canonical transcript,再让 summarizer 读取 request history;摘要请求不带工具;只接受 stop、无 toolCalls、五字段精确 JSON。五字段:current_goal / key_findings / files_read_or_changed / remaining_work / user_constraints。
1. 保存 canonical 快照为 transcript
2. 让 summarizer 读 request history
3. 摘要请求不带任何工具
4. 只接受 finishReason==stop 且无 toolCalls
5. 输出精确 5 字段非空 JSON(多一个字段也拒)
transcript 写失败 → 不调摘要模型
压缩不在一次请求内部改上下文,而在两次模型调用之间:整轮工具跑完后整批结果落盘写入 canonical;下一轮请求前才复制快照做 snip/micro/摘要。KV Cache 按前缀命中,从改动点之后缓存失效、之前仍有效——所以批量压缩优于频繁压缩,摘要推迟到超过字节阈值之后。
第 N 轮结束: 整批 ToolResult → compactToolResults() 落盘
第 N+1 轮开始: 复制 canonical → prepare(): snip → micro → 超阈值才摘要
KV Cache: [System][工具定义][消息1..N] 前缀命中,改动点之后失效
CompactionManager 在实例内缓存最近一次压缩前快照和压缩后请求历史:完全相同 → 直接返回上次结果(连对象引用都相同);纯追加 → 复用已压缩前缀只接新后缀;否则完全重新准备。缓存不跨进程、不持久化,canonical history 仍是唯一事实。省钱省在摘要输入上:重压缩时 summarizer 看「缓存前缀 + 新后缀」,transcript 仍写完整 canonical。
完全相同 → return cachedHistory
纯追加 → [...cachedHistory, ...新消息]
重压缩 → 摘要输入 = 缓存前缀 + 新后缀
transcript = 完整 canonical
整轮 ToolResult 先按单项/批次预算落盘,再以引用写入 canonical(发生在写入 canonical 之前)。
下一轮请求前从 canonical 复制快照——压缩只发生在两次调用之间。
超过 50 组裁中段。
替换更早工具结果。
超过 50_000 才写 transcript + 调摘要模型。
用处理后的 request history。