主要变更: - Skill Learning 闭环系统 (9/9 AC) - Opus 4.7 模型层接入 + adaptive thinking - Prompt 工程优化 (64 审计测试) - Agent Teams 简化门控 (默认启用) - Windows Terminal 后端修复 (EncodedCommand/WT_SESSION) - TF-IDF 技能搜索精准化 (字段加权/CJK 优化) - Autonomy 系统 (/autonomy 命令) - ACP 协议完整实现 - mock.module 泄漏修复 (CI 全绿) - 152+ lint/type 修复
8.8 KiB
Context Management 双机制深度分析
概述
项目中存在两套上下文管理机制,它们不是独立的平行系统,而是不同层次的互补机制,可以同时注入到同一个 API 请求中。
两套机制对比
cachedMicrocompact(cache_edits 机制)
- 文件:
src/services/compact/cachedMicrocompact.ts+src/services/compact/microCompact.ts:276-286 - 运行阶段: API 调用之前,在
query.ts:457中通过microcompactMessages()执行 - 注入方式: 在
addCacheBreakpoints()(claude.ts:3149-3298)中嵌入消息体内部:- 给 tool_result 添加
cache_reference: tool_use_id(第 3253-3294 行) - 将
cache_editsblock 插入用户消息(第 3228-3247 行) - 历史 pinned edits 重新插入原位置(第 3213-3225 行)
- 给 tool_result 添加
- 核心价值: 保留 prompt cache 前缀不失效。通过 cache 层操作删除指定 tool result,不触发完整前缀重写
- 触发条件: 工具计数超阈值(默认 10 个,客户端维护
CachedMCState) - 状态管理: 有状态——
registeredTools、deletedRefs、pinnedEdits。后续请求必须重发历史删除 - 适用场景: 缓存热(频繁交互,缓存 TTL 内)
- 当前状态: 未发布的内部 API,
CACHE_EDITING_BETA_HEADER = '',CACHED_MICROCOMPACTfeature flag 未注册
apiMicrocompact(context_management 公开 API)
- 文件:
src/services/compact/apiMicrocompact.ts - 运行阶段: 构建 API 请求参数时,在
claude.ts:1684的paramsFromContext内调用 - 注入方式: 作为顶层字段
context_management: { edits: [...] }发送(claude.ts:1775-1779) - 核心价值: 声明式策略配置——告诉 API "超过 X token 时自动清理最旧的 tool result"
- 触发条件: Token 超阈值(服务端评估,默认 180K input tokens)
- 状态管理: 无状态——每次请求独立声明策略
- 缓存行为: 会失效 prompt cache 前缀(Anthropic 文档:"Invalidates cached prompt prefixes when content is cleared")。需要
clear_at_least参数确保清理量值得缓存失效代价 - 适用场景: 缓存冷或阈值兜底(不在乎缓存失效)
- 当前状态: 已发布公开 API,使用
context-management-2025-06-27beta header(已在项目中定义)
调用时序
用户发消息
│
├─ query.ts:457 → microcompactMessages()
│ ├─ ① time-based MC(缓存冷时 content-clear,短路退出)
│ └─ ② cachedMicrocompact(缓存热时 cache_edits,不修改消息内容)
│ └→ 排队 pendingCacheEdits
│
└─ claude.ts:paramsFromContext()
├─ 消费 pendingCacheEdits → consumedCacheEdits
├─ getAPIContextManagement() → contextManagement
└─ 构建请求体:
├─ messages: addCacheBreakpoints(..., useCachedMC, consumedCacheEdits, pinnedEdits)
│ └→ cache_reference + cache_edits 嵌入消息内部
└─ context_management: contextManagement
└→ 顶层字段,声明式策略
互斥关系:
- time-based MC 触发时跳过 cachedMC(
microCompact.ts:264-266:"Cached MC is skipped when this fires: editing assumes a warm cache") - cachedMC 和 apiMC 可以同时生效——分别注入到消息内部和顶层字段
协作设计意图
两者的设计是分层互补:
- cachedMC(热缓存优化): 在缓存有效期内(~5 分钟),精细删除单个 tool result,零缓存失效代价。适合频繁交互的场景。
- apiMC(阈值兜底): 当 input token 超过阈值时,由服务端批量清理。代价是缓存失效,但确保不会超限。
- time-based MC(冷缓存兜底): 当空闲超时导致缓存过期时,客户端直接 content-clear 消息体,为重写缓存做准备。
当前门控限制
cachedMicrocompact 门控
| 门控 | 位置 | 值 | 影响 |
|---|---|---|---|
feature('CACHED_MICROCOMPACT') |
microCompact.ts:276 |
false(未注册) |
整条路径不可达 |
CLAUDE_CACHED_MICROCOMPACT=1 |
cachedMicrocompact.ts:27 |
未设置 | 启用检查失败 |
CACHE_EDITING_BETA_HEADER |
betas.ts:50 |
''(空) |
API 层 cachedMCEnabled=false |
apiMicrocompact 门控
| 门控 | 位置 | 值 | 影响 |
|---|---|---|---|
USER_TYPE=ant |
apiMicrocompact.ts:90 |
非 ant | tool clearing 不触发 |
USE_API_CLEAR_TOOL_RESULTS=1 |
apiMicrocompact.ts:94 |
未设置 | tool result 清理不启用 |
USE_API_CLEAR_TOOL_USES=1 |
apiMicrocompact.ts:97 |
未设置 | tool use 清理不启用 |
CONTEXT_MANAGEMENT_BETA_HEADER |
betas.ts:7 |
context-management-2025-06-27 |
已可用 ✓ |
modelSupportsContextManagement() |
betas.ts:282 |
Opus 4.6+, Sonnet 4.6 = true | 已可用 ✓ |
clear_thinking_20251015 |
apiMicrocompact.ts:82-87 |
有 thinking 时启用 | 已生效 ✓(所有用户) |
已知问题
P0: cachedMicrocompact 的 deletedRefs 未填充
详见 docs/bugs/cached-microcompact-issues.md 问题 1。
P1: 类型不安全的 as any 桥接
claude.ts:1763-1764 中 consumedCacheEdits 和 consumedPinnedEdits 通过 as any 传入 addCacheBreakpoints。CacheEditsBlock.edits 的类型是 { type: string; tool_use_id: string },而 addCacheBreakpoints 期望的是 { type: 'delete'; cache_reference: string }。两者字段名不同(tool_use_id vs cache_reference),靠 as any 掩盖了类型不匹配。
P2: 两机制同时存在时的 API 行为未定义
目前无文档说明 Anthropic API 如何处理 cache_edits(消息内嵌)和 context_management(顶层字段)同时存在的情况。可能存在未定义交互。
启用方案
方案 A: 仅启用 apiMicrocompact(推荐,可立即实施)
- 移除
USER_TYPE=ant门控(apiMicrocompact.ts:90),改为环境变量或 settings 控制 - 默认启用 tool clearing(移除
USE_API_CLEAR_TOOL_RESULTSenv 检查,或设置默认值) - Beta header 和
context_management注入逻辑已就绪,无需额外改动
代价:缓存失效(每次清理触发缓存前缀重写),但对订阅用户来说这不是问题(按使用量计费,不按缓存写入计费)。
方案 B: 同时启用两者(需等 cache_edits API 可用)
- 先完成方案 A
- 修复
deletedRefsbug - 等
CACHE_EDITING_BETA_HEADER有值后启用 cachedMC - 两者共存:cachedMC 在缓存热时精细操作,apiMC 在超限时兜底
方案 C: 用 CACHE_EDITING_BETA_HEADER = CONTEXT_MANAGEMENT_BETA_HEADER 尝试
将 CACHE_EDITING_BETA_HEADER 设为 'context-management-2025-06-27',测试 API 是否接受消息内嵌的 cache_reference + cache_edits。如果接受,说明两者确实共用同一个 beta header。
API 实测验证(2026-04-21 OAuth 订阅账户)
/v1/models确认 Opus 4.7/4.6/Sonnet 4.6 都支持context_management,含三种策略:clear_tool_uses_20250919✓clear_thinking_20251015✓compact_20260112✓(服务端压缩,新发现)
context-management-2025-06-27beta header 被 API 接受(context_management字段不报错)cache_edits内嵌机制未测试(需要 beta header 值)
2026-04-21 已实施的修复
解除 USER_TYPE=ant 门控
apiMicrocompact.ts:89-92:移除 if (process.env.USER_TYPE !== 'ant') 整个 early return block。clear_tool_uses_20250919 默认对所有用户启用,可通过 USE_API_CLEAR_TOOL_RESULTS=0 环境变量禁用。
betas.ts:277-289:移除 antOptedIntoToolClearing 变量中的 process.env.USER_TYPE === 'ant' 条件,改为 modelSupportsContextManagement(model) || USE_API_CONTEXT_MANAGEMENT=1。beta header 注入不再依赖 ant 身份。
验证结果
- tsc 零错误
- compact 相关 35 tests 全部通过
- beta header 17 tests 全部通过
- 全量 3415 pass / 1 fail(deep link 无关测试)/ 268 files
参考文件
- Anthropic Context Editing 文档
src/services/compact/microCompact.ts— 入口及时序(第 253-293 行)src/services/compact/cachedMicrocompact.ts— cache_edits 实现src/services/compact/apiMicrocompact.ts— context_management 实现src/services/api/claude.ts:1579-1583— consumedCacheEdits/consumedPinnedEdits 准备src/services/api/claude.ts:1684-1688— contextManagement 获取src/services/api/claude.ts:1726-1741— useCachedMC 和 beta header 注入src/services/api/claude.ts:1756-1779— 两者同时注入到请求体src/services/api/claude.ts:3149-3298— addCacheBreakpoints 完整实现src/utils/betas.ts:277-289— CONTEXT_MANAGEMENT_BETA_HEADER 注入条件