第 3 章:会话日志(Session Log)、Surface 与投影
1. 本章定位
Agent 的记忆不是一个可随意修改的消息数组,而是只追加事件事实与若干可重建视图。
2. 学习目标
- 区分原始日志、Surface、模型历史、持久化和前端投影。
- 解释
deriveMessages()与surface.replace。 - 理解格式版本、checkpoint 与重放边界。
- 从事件序列手工推出模型可见消息。
3. 前置知识
可类比 Redux action log 与 selector:日志记录发生过什么,投影计算当前视图。局限是 Session 事件有序号、冻结 JSON、格式版本和持久化合同,不能重放任意副作用。
4. 对应源码
packages/core/session/src/types.ts:87:SESSION_FORMAT_VERSION。packages/core/session/src/types.ts:425:Session。packages/core/session/src/index.ts:790:deriveMessages()。packages/core/session/src/surface.ts:81:Surface 规则。packages/session/session-persistence/packages/session/session-persistence-jsonl/packages/session/session-log-deepseek/
5. 工作原理
Session Log 保存 durable event;Surface 决定当前哪些消息对模型可见;deriveMessages() 从 Surface 派生下一次模型请求的历史;projection、浏览器快照和统计都可从事件重建。replace 只改变可见区间,不删除旧日志。JSONL backend 负责落盘,checkpoint 缩短恢复成本,但不能取代原始语义。
6. 执行流程
无图回退:事件 → append-only log → Surface / persistence / page()+follow() → deriveMessages()、projection、Client Session → LLM 上下文和 React UI。
7. 关键源码讲解
SESSION_FORMAT_VERSION 是跨版本恢复边界;Session 保证事件序列;deriveMessages() 只读取模型可见节点。新增事件类型时必须同步检查 envelope schema、Surface 规则、持久化 codec、projection 和 UI assembler,否则会出现“日志可写但无法恢复或展示”。
8. 调试与观察方法
断点放在 append、Surface 校验和 deriveMessages();观察 seq、type、surfaceOp、Surface nodes。先用最小事件序列复现,再接 JSONL 与 UI。常见故障:seq 断裂、replace 范围错误、格式版本不兼容、checkpoint 与日志偏移不一致。
9. 本章实践任务
追加 user、turn/start、assistant/chunk、assistant/message,再用 replace 写入摘要;分别断言物理日志长度、Surface 节点和派生消息。验收:chunk 不直接成为模型历史,replace 后旧事件仍可审计。
10. 常见误区
- 把每个 chunk 当模型消息。
- 把 replace 当物理删除。
- 把 projection backend 当 persistence backend。
11. 自测题
- 为什么 chunk 不直接进入模型历史?
deriveMessages()的事实输入是什么?- checkpoint 能否替代日志?
- 新事件类型至少影响哪些消费者?
- 如何证明一个投影可重建?