Appearance
Monorepo 仓库结构
在动手前,先看清 pi 这个 monorepo 在磁盘上的样子。它使用 npm workspaces 管理,根目录的 package.json 声明了所有工作区。
顶层目录
pi/
├── package.json # 根 package.json,声明 workspaces
├── package-lock.json # 依赖锁定(ground truth)
├── tsconfig.base.json # 共享 TS 配置
├── biome.json # 代码规范(lint + format)
├── AGENTS.md # 项目开发规则(给开发者和 AI 的守则)
├── CONTRIBUTING.md # 贡献指南
├── pi-test.sh / test.sh # 测试脚本
├── packages/ # ★ 所有工作区包都在这里
└── scripts/ # 构建、发布等脚本packages 目录
bash
packages/
├── agent/ # @earendil-works/pi-agent-core Agent 运行时
├── ai/ # @earendil-works/pi-ai 统一 LLM 抽象层
├── client/ # @earendil-works/pi-client 远程会话客户端
├── coding-agent/ # @earendil-works/pi-coding-agent 编码 Agent CLI
├── evals/ # 评测
├── protocol/ # @earendil-works/pi-protocol 字节协议
├── server/ # @earendil-works/pi-server 远程会话服务端
├── storage/ # @earendil-works/pi-storage SQLite 存储
└── tui/ # @earendil-works/pi-tui 终端 UI 库依赖方向(谁依赖谁)
这是全教程最重要的一张依赖图。箭头表示"依赖":
text
coding-agent ──► tui
│ └──► server ──► protocol
│ └──► client ──► protocol
└─────► agent-core ──► ai
server ──► agent-core
client ──► agent-core要点:
ai是最底层,谁也不依赖。agent-core依赖ai(通过StreamFunction与模型解耦)。protocol是纯字节层,不依赖ai/agent。server/client依赖protocol+agent。coding-agent依赖除了ai之外的所有包(它直接依赖ai的compat入口)。
每个包的 src 里有什么
以 packages/ai/src 为例,它没有把所有代码堆在一个文件里,而是按职责分了子目录:
packages/ai/src/
├── api/ # 每家厂商的 API 实现(openai-responses、anthropic-messages…)
├── providers/ # 每家厂商的 Provider 定义(openai、anthropic、google…)
├── auth/ # 认证(OAuth、凭证存储)
├── utils/ # 事件流、JSON 解析、重试、token 估算等工具
├── types.ts # ★ 核心类型:Message、Context、Model、StreamFunction
├── models.ts # ★ Model/Provider/Models 的定义与工厂
├── models.generated.ts # 自动生成的模型目录(勿手改)
└── index.ts # 对外导出建议:阅读 ai 时先看 types.ts 和 models.ts,它们是抽象层的"宪法";api/ 和 providers/ 是实现细节,等需要接入某家厂商时再看。
如何阅读本教程
本教程严格按依赖顺序组织,每个包一章,顺序不可乱:
@pi/ai—— 消息模型、事件流、Model/Provider、StreamFunction@pi/agent-core—— 核心循环、工具、事件、队列@pi/protocol—— 定帧、CBOR、Schema@pi/server+@pi/client—— 远程会话@pi/tui—— 终端差分渲染@pi/coding-agent—— 把上面全部缝合起来
对照源码
每一章都会标注真实源码路径,例如 packages/ai/src/types.ts:498 表示该文件第 498 行。建议打开仓库边读边看。