Part I · The Map

01 仓库全景 10 个包、25 万行、一年、286 位署名作者

已发布 TS 代码 250858 行 提交 5565 起始 2025-08-09
§1 Mental Model 一句话心智模型

先记住这一句

pi 是一个「三层核心 + 一堆试验性外围」的仓库:ai 管 provider,agent 管循环,coding-agent 管产品——这三个包占了 81% 的代码。其余七个包加起来不到两成,且多数标着 experimental。

看规模分布比看包名更快理解一个仓库的重心:

包TS 行数职责
coding-agent123797CLI 产品本体:工具、扩展、交互模式、会话管理
ai58449统一多 provider 的 LLM API
tui32374自研终端 UI 库,差分渲染
agent21053agent 循环、工具执行、会话存储、harness v2
session-backends4039SQLite 后端(独立成包)
server3761会话服务端(experimental)
client2472客户端
protocol1961线上协议(CBOR 编解码 + framing)
evals1774评测框架
telemetry1178厂商中立的 telemetry 契约

行数由 tools/stats.sh 从锚定 SHA 的工作树程序化统计(含测试与生成文件),非手写。

锚点之后包的组成在锚点之后变了不少。到 v1.2.0,表里的 session-backends 随 7fd478a(2026-10-01)删除,client、protocol、server 随 7472cda(2026-10-12)删除;新增了 chord、codemode、durable、env、mcp。上表的包数与行数都按锚点统计,本书没有为 v1.2.0 重算。

§2 Evidence 代码实证

依赖方向:一条干净的单向链

各包 package.json 的 @earendil-works/* 依赖从 package.json 提取,非源码
telemetry  → (无内部依赖)
tui        → (无内部依赖)
protocol   → (无内部依赖)
evals      → (无内部依赖)

ai         → telemetry
agent      → ai, telemetry
client     → protocol
server     → ai, protocol
coding-agent → agent, ai, client, protocol, tui  ← 唯一的汇聚点
没有环。tui 完全独立于 agent 逻辑——它是一个可以单独拿走用的终端 UI 库,不知道 LLM 的存在。

这张图里最值得注意的是 agent 不依赖 tui,tui 也不依赖任何东西。渲染与执行彻底分离,是 headless 模式(第 14 章)能存在的结构前提。

一年的提交形状

5565
提交总数
286
署名作者
428
月均提交
13
活跃月份

作者分布是典型的「一个主力 + 一圈卫星」:Mario Zechner 3513 次提交(63%),Armin Ronacher 512 次,其后是 github-actions[bot] 与一串三位数以下的贡献者。286 位作者里,绝大多数只提交过个位数。

把这个分布和 第 18 章的贡献者门禁放在一起看才完整:240 个已批准账号,286 位历史作者——门禁不是把人挡在外面,而是把「随手扔一个 issue」和「真的来做事」分开。

一个不在仓库里的东西

provider 的模型元数据不在 git 里:

.gitignore原文 L11
packages/ai/src/providers/data/
39 个 provider 的模型清单是 build 时从上游目录拉取的产物。.gitignore:11

所以 npm run build 的注释写的是「先刷新模型数据,再构建全部包」,另有一个 build:offline 用已有数据、不联网。README.md:56–57 完整含义见 第 09 章。

§3 Design 设计动机与权衡

为什么 coding-agent 这么大

12 万行里装的是:7 个内建工具、扩展系统、交互模式的全部 UI 组件、会话管理、设置系统、主题、键位、RPC/JSON 模式、导出 HTML……换句话说,凡是「产品决策」都在这一层。

这与 CONTRIBUTING.md 的声明是一致的:核心要最小,不属于核心的应该做成扩展。CONTRIBUTING.md:9 但要注意「核心」在这句话里指的是 packages/agent(2 万行),不是 coding-agent。coding-agent 本身不受这条约束——它是产品。

自研 TUI 这个决定

3.2 万行手写一个终端 UI 库,而不是用 Ink(React for CLI)或 blessed。代价是显然的;收益要到 第 11 章才说得清。这里先记一个事实:tui 包零内部依赖,也不依赖 React——它是这个仓库里最容易被单独复用的部分。

experimental 的自我标注

server 包的 README 第一句就是:Experimental. 本包处于活跃开发中,可能变更或移除,恕不另行通知;API 与行为尚不稳定。server/README.md:3

把稳定性承诺写在 README 第一行,比藏在版本号里诚实。对照 第 07 章提到的「唯一兼容承诺」,这是同一种做法:把变更自由度显式声明出来,而不是靠 semver 暗示。

§4 Limits 边界与失效条件
§5 Takeaway 拿走什么
§ Self-check 自测

给场景,判断 pi 会怎么做

场景你想拿 pi 仓库里的一个包单独做自己的终端应用,且不想拖进任何 LLM 相关依赖。哪个包能直接拿走?

看答案

C。依赖图里 tui 没有任何 @earendil-works/* 依赖,也不依赖 React;agent 依赖 ai 和 telemetry,coding-agent 是全图唯一的汇聚点。

场景你 clone 仓库后在断网环境执行 npm run build,会发生什么?

看答案

B。39 个 provider 的模型清单在 gitignore 掉的 data/ 目录里,.gitignore:11 默认 build 第一步就是联网刷新它。README.md:56

基于 earendil-works/pi @ ac4ac9e(2026-08-07 快照)。
本页全部数字由 tools/stats.sh 程序化生成,未手写。