先看边界,再看文件

用模块依赖、数据流与生命周期三张地图理解 Pi,而不是从目录树迷路。

ANALYSIS SNAPSHOTPi v0.82.15bc1c2c0

总体架构

SYSTEM MAPPi 的四层边界
调用由上向下;事件、增量与结果由下向上返回。Extension 横切 coding-agent 层,不是独立沙箱。

用户面对的是一个 CLI,但 CLI 背后不是单块程序。它先组织会话和资源,再把一次请求交给通用 runtime,最后由模型层连接具体 provider。

启动链

bin/pi
  → main(args)
  → resolve app mode + trust + session
  → createAgentSessionRuntime(...)
  → createAgentSession(...)
  → InteractiveMode | print | json | rpc

CLI 入口本身很薄;复杂度集中在 main.ts 的装配决策和 core/ 的服务对象。

packages/coding-agent/src/main.ts:469-864main()

数据流:两套“消息”

Pi 刻意区分 AgentMessage 与 provider 可理解的 Message。前者可以由应用通过 declaration merging 扩展,用来承载 UI 或业务消息;到模型边界前,convertToLlm() 必须转换或过滤它们。

这条边界解释了为什么“屏幕上看见的东西”不一定“模型也看见”。

packages/agent/src/types.ts:296-319CustomAgentMessages

状态流:事实、投影与瞬时值

典型状态 生命周期
Session JSONL message、model change、compaction、branch 跨进程持久
Agent.state model、tools、messages、isStreaming 当前 session runtime
streamed partial text/toolcall delta 单次 provider response
TUI component state selection、overlay、editor 当前界面

生命周期

  1. 解析参数与运行模式。
  2. 决定 project trust,加载 settings/resources/context files。
  3. 创建或恢复 SessionManager
  4. 用 model、tools、prompt、extensions 创建 AgentSession
  5. prompt 进入 core Agent,事件持续向上冒泡。
  6. 消息与配置变化追加到 session tree。
  7. UI、JSON 或 RPC consumer 消费事件。
  8. dispose() 释放订阅、资源与后台服务。

Trade-off

分层提高可替换性,但也产生“同一概念在不同层有不同形态”的认知成本。Pi 用显式类型和事件桥接换取可嵌入性,而不是追求单文件易读。