mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-17 22:05:50 +00:00
主要变更: - 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 修复
159 lines
8.8 KiB
Markdown
159 lines
8.8 KiB
Markdown
# 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_edits` block 插入用户消息(第 3228-3247 行)
|
||
- 历史 pinned edits 重新插入原位置(第 3213-3225 行)
|
||
- **核心价值**: **保留 prompt cache 前缀不失效**。通过 cache 层操作删除指定 tool result,不触发完整前缀重写
|
||
- **触发条件**: 工具计数超阈值(默认 10 个,客户端维护 `CachedMCState`)
|
||
- **状态管理**: 有状态——`registeredTools`、`deletedRefs`、`pinnedEdits`。后续请求必须重发历史删除
|
||
- **适用场景**: **缓存热**(频繁交互,缓存 TTL 内)
|
||
- **当前状态**: 未发布的内部 API,`CACHE_EDITING_BETA_HEADER = ''`,`CACHED_MICROCOMPACT` feature 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-27` beta 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 **可以同时生效**——分别注入到消息内部和顶层字段
|
||
|
||
## 协作设计意图
|
||
|
||
两者的设计是**分层互补**:
|
||
|
||
1. **cachedMC(热缓存优化)**: 在缓存有效期内(~5 分钟),精细删除单个 tool result,**零缓存失效代价**。适合频繁交互的场景。
|
||
2. **apiMC(阈值兜底)**: 当 input token 超过阈值时,由服务端批量清理。**代价是缓存失效**,但确保不会超限。
|
||
3. **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(推荐,可立即实施)
|
||
|
||
1. **移除 `USER_TYPE=ant` 门控**(`apiMicrocompact.ts:90`),改为环境变量或 settings 控制
|
||
2. **默认启用 tool clearing**(移除 `USE_API_CLEAR_TOOL_RESULTS` env 检查,或设置默认值)
|
||
3. Beta header 和 `context_management` 注入逻辑已就绪,无需额外改动
|
||
|
||
代价:缓存失效(每次清理触发缓存前缀重写),但对订阅用户来说这不是问题(按使用量计费,不按缓存写入计费)。
|
||
|
||
### 方案 B: 同时启用两者(需等 cache_edits API 可用)
|
||
|
||
1. 先完成方案 A
|
||
2. 修复 `deletedRefs` bug
|
||
3. 等 `CACHE_EDITING_BETA_HEADER` 有值后启用 cachedMC
|
||
4. 两者共存: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 订阅账户)
|
||
|
||
1. `/v1/models` 确认 Opus 4.7/4.6/Sonnet 4.6 都支持 `context_management`,含三种策略:
|
||
- `clear_tool_uses_20250919` ✓
|
||
- `clear_thinking_20251015` ✓
|
||
- `compact_20260112` ✓(服务端压缩,新发现)
|
||
2. `context-management-2025-06-27` beta header 被 API 接受(`context_management` 字段不报错)
|
||
3. `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 文档](https://docs.anthropic.com/en/docs/build-with-claude/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 注入条件
|