Files
claude-code/docs/bugs/context-management-analysis.md
unraid 95fece4b51 feat: 整合功能恢复与技能学习闭环(含 ECC v2.1 parity + Opus 4.7 接入 + prompt 工程优化)
主要变更:
- 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 修复
2026-04-22 16:07:42 +08:00

159 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 faildeep 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 注入条件