首页/消息与对话

消息与对话

消息流水线与上下文压缩

消息系统处理用户与 Claude 之间的所有通信,包括文本消息、工具调用、系统消息等。上下文压缩系统通过 4 层策略确保对话不超过模型的上下文窗口。

核心要点

消息类型:user, assistant, system, progress, tool_use, tool_result
系统消息子类型:local_command, interruption, hook, notification
虚拟消息 — REPL 内部调用时对用户不可见
4 层上下文压缩:裁剪 → 摘要 → 截断 → 驱逐
粘贴内容去重和引用系统

设计亮点

压缩时 AI 自己先打草稿

就像考试时先在草稿纸上列提纲,只把最终答案写到答题纸上

压缩过程中,AI 用 <analysis> 标签做内部推理——分析哪些信息重要、哪些可以丢弃。但只有 <summary> 标签里的精炼内容才会真正进入压缩后的上下文。这让 AI 可以'思考'而不浪费宝贵的上下文空间。

// 压缩提示词中的关键设计
// AI 输出格式:
// <analysis>
//   这段对话主要讨论了文件X的重构...
//   用户关心的是性能,不是代码风格...
// </analysis>
// <summary>
//   用户正在重构 utils/parser.ts 以提升性能。
//   已完成:缓存层、异步化。待做:批处理优化。
// </summary>
// 只有 <summary> 的内容会被保留

压缩后自动补回常用文件

就像搬家时虽然扔了很多东西,但钥匙、钱包、手机一定会随身带着

上下文被压缩后,系统会统计对话中最频繁引用的 5 个文件,重新将它们的内容注入到上下文中。同时,当前激活的技能定义也会被恢复。这确保压缩不会让 AI '忘记' 正在处理的核心文件。

自己压缩失败时有逃生舱

飞机有备用发动机——如果主引擎故障,备用引擎能让你安全降落

如果需要压缩的对话本身就已经超过了模型的上下文限制(连压缩请求都发不出去),系统不会崩溃。它有一个 escape hatch:直接丢弃最旧的对话轮次,粗暴但有效地把大小降下来。这是最后的保底措施。

粘贴内容用引用去重

图书馆不会因为 10 个人借同一本书就买 10 本——用借书卡指向同一本就行

当用户反复粘贴同一段代码或文本时,消息系统只保留一份实体内容,其余引用通过指针关联。这在调试场景中特别有用——用户可能多次粘贴错误日志,但不会重复占用上下文空间。

模块架构图

加载架构图...
核心文件
types/message.ts300 LOC

消息类型定义

history.ts500 LOC

会话历史管理(14K)

services/compact/1,500 LOC

上下文压缩服务

utils/messages.ts400 LOC

消息处理工具函数

query.ts1,729 LOC

查询系统

QueryEngine.ts1,295 LOC

查询执行引擎

数据流程
1
用户/系统消息
新消息进入管道
2
消息处理
类型标注、附件解析
3
历史存储
持久化到会话文件
4
检查上下文
是否接近限制
5
压缩
4 层渐进压缩
6
发送 API
带上下文发送请求

关键代码

加载代码...

深入解析

消息系统是 Claude Code 的通信中枢,所有用户交互和模型响应都通过它流转。消息类型远不止文本——tool_use、tool_result、progress 等都是一等公民。

上下文压缩是保证长对话可用性的关键。4 层压缩策略渐进式工作:先裁剪冗余工具输出,再用 AI 摘要替代早期对话,然后截断超大内容,最后驱逐最旧的消息轮次。

压缩时 AI 使用 <analysis> 标签进行内部推理(如分析哪些信息重要),但只有 <summary> 标签内的内容会被保留进上下文——这是一种让 AI '打草稿' 的机制。

压缩后系统会自动重新注入最常用的 5 个文件和技能定义。这意味着即使上下文被压缩,核心工作文件的内容不会丢失。

如果压缩请求本身太长(超过模型上下文),系统有 'escape hatch':直接丢弃最旧的对话轮次,而不是崩溃。

粘贴内容通过引用系统去重——如果用户多次粘贴同一段代码,只保留一份实体,其余用引用指针替代。

虚拟消息 (virtual messages) 是 REPL 内部调用产生的消息,对用户完全不可见,用于工具间的内部通信。

query.ts (1729行) 和 QueryEngine.ts (1295行) 构成查询执行引擎,负责将处理好的消息序列发送到 Anthropic API 并处理流式响应。