会话与运行时
前两篇分别讲了"地图"和"工具"。这一篇讲把工具、模型、事件流缝在一起的那层——会话与运行时。对应源码:
core/session-manager.ts— JSONL 会话文件与树操作core/compaction/— 上下文压缩core/model-runtime.ts— 模型目录与 provider 认证core/agent-session.ts— 总装sdk.ts— 对外的程序化入口
SessionManager:磁盘上的树
极简主义篇讲过会话文件的格式(JSONL、id/parentId 树)。这里补实现细节。
SessionManager 是个 class(core/session-manager.ts:791),构造靠静态工厂:
磁盘布局按工作目录归档:~/.pi/agent/sessions/--Users-mario-my-project--/<timestamp>_<uuid>.jsonl——把 cwd 的路径分隔符替换成 -- 当目录名,同一会话目录下的文件按时间排序,--continue 就是取最新的一个。
文件条目分四类:session(header,version 3)、message、model_change、compaction。每条带 id/parentId,新条目追加到当前 leaf 之下。关键操作:
newSession(parentId?):从当前会话分叉——写入新 header(parentSession指向旧文件),同目录新建文件。这就是/new命令和分叉式回滚的实现。getTree():从 entries 构建树,返回所有节点,供/tree导航和 TUI 的树选择器使用。- fork/分支切换:从树中任意节点重新加载上下文(约
session-manager.ts:1352的loadEntriesFrom/buildSessionContext一线)——沿该节点的祖先链收集 message,作为新的 agent 上下文。撤销一次工具调用?选中调用前的节点即可。
compaction 条目是树上的特殊节点:firstKeptEntryId 标记保留区的起点,summary 是压缩摘要。后续构建上下文时遇到它,就用"摘要 + 保留区消息"代替原始历史。
Compaction:作为第一条的 hook
压缩机制本身(transformContext 触发、agentic 摘要生成,阈值 contextWindow - reserveTokens,reserve 16384)在前面的篇章已展开。这里值得记录的是它在扩展机制里的位置:transformContext 是 pi 全部扩展钩子的第一个——编号 01。扩展系统里管上下文生命周期的钩子一族(transformContext、prepareMessages、transformSystemPrompt)都以压缩为原型:在消息发给 LLM 之前,给你一次改写的机会。理解了 compaction,就理解了 pi 扩展钩子的一半设计语汇。
ModelRuntime:模型的统一门面
ModelRuntime(core 里)实现 pi-ai 的 Models 接口,把三件事揉在一起:
- 模型目录:内置目录(300+ 模型条目)与
~/.pi/agent/models.json的用户自定义合并,定期后台刷新(远端目录拉取); - 认证解析:provider 环境变量 → OAuth 凭证 →
apiKey配置的优先级链,解析出某个模型本次调用该用的凭证; - 统一接口:对上层只暴露"给我一个 model + credentials,我返回 stream 函数",与 pi-ai 的
getModel/completeSimple形状一致。
ModelRuntime.create(...) 是标准入口;registerProvider 允许扩展注册新 provider。CLI 的 /login、/models、Ctrl+P 换模型,都只是这个门面的 UI。
AgentSession:总装与四种模式
core/agent-session.ts 把以上一切组装成一个对象:持有 Agent(pi-agent-core)、SessionManager、ModelRuntime、SettingsManager、ResourceLoader,订阅 agent 事件流,把事件翻译给 UI,把 UI 的输入(steer/followUp/abort)翻译回 agent。
四种运行模式——interactive(TUI)、print(-p)、RPC(--mode rpc)、SDK(createAgentSession)——消费的是同一条事件流。这是"UI 是外围"原则的最终兑现:TUI 的 AgentEventVisualizer、print 模式的 stdout 渲染器、RPC 的 JSON 行协议,只是同一事件流的三种渲染器。新增一种前端不需要动 agent 一行代码。
SDK 一览
sdk.ts 的 createAgentSession(options) 是最小入口,默认配上 DefaultResourceLoader(扫描 skills/extensions/主题)和 ModelRuntime:
你拿到的是与 CLI 完全同构的 session:prompt、steer、abort、事件订阅、树导航。给 agent 套个 Web 前端、接进 CI、做成聊天机器人,都从这个入口开始。用 pi 重构一章有另一组更贴近 Agent 类的示例。
小结
至此三张源码导读拼齐了全貌:main.ts 引导 → agent loop 跑圈(pi-agent-core)→ 工具执行(tools/ + 四个横向机制)→ 会话落盘与恢复(SessionManager/compaction)→ 模型门面(ModelRuntime)→ 模式渲染(四种 UI 消费同一事件流)。想再深入,带着这张地图回到 源码地图 逐个文件读即可。