先看边界,再看文件
用模块依赖、数据流与生命周期三张地图理解 Pi,而不是从目录树迷路。
ANALYSIS SNAPSHOTPi v0.82.1
5bc1c2c0总体架构
SYSTEM MAPPi 的四层边界
HUMANTerminal / SDK / RPC
prompt↓
@earendil-workspi-coding-agentSession · CLI · Extensions · TUI
AgentSession↓
RUNTIMEpi-agent-coreLoop · State · Tool dispatch · Events
stream()↙
execute()↘
MODELpi-ai
ENVIRONMENTTools
用户面对的是一个 CLI,但 CLI 背后不是单块程序。它先组织会话和资源,再把一次请求交给通用 runtime,最后由模型层连接具体 provider。
依赖方向是 coding-agent → agent-core → ai;控制流向下,stream/event 向上。SessionManager 是持久事实结构,Agent.state 是当前运行投影。
main() 解析模式、会话与资源,createAgentSessionRuntime() 装配 session,AgentSession 把 core Agent 的事件映射为 coding-agent 语义。
启动链
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 | 当前界面 |
生命周期
- 解析参数与运行模式。
- 决定 project trust,加载 settings/resources/context files。
- 创建或恢复
SessionManager。 - 用 model、tools、prompt、extensions 创建
AgentSession。 - prompt 进入 core
Agent,事件持续向上冒泡。 - 消息与配置变化追加到 session tree。
- UI、JSON 或 RPC consumer 消费事件。
dispose()释放订阅、资源与后台服务。
Trade-off
分层提高可替换性,但也产生“同一概念在不同层有不同形态”的认知成本。Pi 用显式类型和事件桥接换取可嵌入性,而不是追求单文件易读。