Session:一棵树,不是一条数组
从 JSONL entry、parentId、active leaf 到 compaction checkpoint,理解 Pi 如何保存可分支的工作历史。
ANALYSIS SNAPSHOTPi v0.82.1
5bc1c2c0为什么不是 messages.json
工作并不总沿直线前进。你可能回到上午的决策点尝试另一条路。树让旧路径还在,同时新路径可以继续。
每个 SessionEntry 有 id 与 parentId;SessionManager 维护 current leaf。branch() 只移动 leaf,后续 append 自然形成新分支。
SessionHeader 记录 version/id/timestamp/cwd;entry union 包含 message、model/thinking change、compaction、branch_summary、custom、label 与 session_info。
SESSION MODELAppend-only session tree
header
│user A
│assistant B
├──────────────┐user Cold pathuser Dactive leaf
Entry 类型的职责
| Entry | 进入模型 context | 作用 |
|---|---|---|
message |
是 | 用户/助手/工具事实 |
model_change |
间接 | 恢复后续模型状态 |
thinking_level_change |
间接 | 恢复 reasoning 配置 |
compaction |
是,作为 summary | 替代老历史 |
branch_summary |
是 | 携带被离开路径的经验 |
custom |
否 | 扩展持久状态 |
custom_message |
是 | 扩展注入上下文 |
label / session_info |
否 | 导航与元数据 |
packages/coding-agent/src/core/session-manager.ts:30-174SessionEntry union
JSONL 的工程含义
追加一行比重写一个巨大 JSON 数组更容易保持历史、流式落盘和故障恢复;每行仍可独立解析。代价是读取时必须迁移版本、重建索引和树,并处理截断或损坏行。
Pi 当前 CURRENT_SESSION_VERSION = 3,包含 v1→v2、v2→v3 迁移。Session discovery 只扫描有限头部字节,并用并发上限加载列表,避免在大量 session 下无界打开文件。
/tree、/fork 与 /clone
/tree:同一文件内移动 active leaf。/fork:从较早 user message 创建新 session 文件。/clone:复制当前 active branch 到新 session。
Trade-off
树保留探索空间并支持回溯,但 UI、统计和 compaction 都必须以“当前分支”而非“文件全部行”为准。线性日志更简单,树更符合真实开发工作。