跳到主要内容

Pi 是什么 · 全景图 · 阅读地图

30 秒导读: Pi 是一个跑在终端里的 AI 编码 agent(类似 Claude Code / Codex CLI)。 它的设计信条是内核尽量小,真正的能力靠 TypeScript 扩展、Skills、prompt 模板、 主题、以及可安装的「pi 包」长出来——甚至能用自己去改自己。本章是这组文档的门厅: 先讲清「它是什么」,再画出「四个包怎么分层」,追一条「敲一句话到屏幕出字」的主线, 最后给一张阅读地图告诉你 01–05 章各读什么。本章只做导航与心智模型,机制细节留给后续章。


1. 这是什么(零基础也能懂)

一句话定义

Pi 是一个终端里的编码 agent 框架:你在命令行敲自然语言,它调用大模型,并让模型真的动手 ——读文件、改代码、跑 shell 命令——来完成任务。

它对外的产品叫 pi(npm 包 @earendil-works/pi-coding-agent)。项目自我定位是 "a minimal terminal coding harness"(最小的终端编码骨架),核心刻意做小,能力靠扩展长出来 (packages/coding-agent/docs/index.md:3)。

解决什么问题 / 给谁用

  • 给谁: 想在终端里让 AI 帮忙读/写/改一个真实代码库的工程师。
  • 解决什么: 把"模型只会说话"补齐成"模型能动手"——它自带 read/write/edit/bash 四件工具,让模型在你的工作目录里实际操作文件、执行命令(packages/coding-agent/docs/quickstart.md:77-84)。
  • 和别家不同的地方: 内核极小 + 多层自扩展。你可以写 TS 扩展加工具/命令/UI、放 Skills(按需加载的技能说明)、写 prompt 模板、换主题,还能把这些打包成 "pi 包" 分享安装 (packages/coding-agent/docs/index.md:52-59)。

用起来什么样(最小交互示例)

装好之后在项目目录里直接敲 pi,进入交互界面,打一句话就开始干活:

$ npm install -g --ignore-scripts @earendil-works/pi-coding-agent
$ cd /path/to/project
$ export ANTHROPIC_API_KEY=sk-ant-...
$ pi

> Summarize this repository and tell me how to run its checks.

⏺ read package.json
⏺ bash ls src
⏺ 这个仓库是一个 monorepo…… 跑检查用 `npm run check`。

模型每一步想读文件、跑命令,都会以工具调用的形式发生;结果回喂给模型,直到它给出最终答复。 除了这种交互模式,pi 还支持一次性 pi -p "..."、管道输入、以及给别的程序集成的 --mode rpc / --mode json(packages/coding-agent/docs/quickstart.md:146-155)。

一句话直觉

把 Pi 想成**「给大模型接上手脚,再套一层会记事的外壳」**: pi-ai 是嘴(统一对各家模型说话),pi-agent-core 是脊椎与反射弧(一轮轮循环:说话→动手→再说话), pi-coding-agent 是手脚和工具箱(真正去读写文件、跑命令,并管理会话/扩展/CLI), pi-tui 是眼睛能看到的屏幕(把整个过程画在终端里)。

本节到此不涉及底层代码。记住一件事:内核小,能力靠层层扩展长出来


2. 全景图(monorepo 四(+1)包怎么分层)

这是一个 monorepo

package.json 用 workspaces 把所有包收在 packages/* 下 (package.json:5-12)。核心是四个包,外加一个实验性的第五个:

包目录npm 名一句话职责顶层入口
packages/ai@earendil-works/pi-ai统一多-provider LLM API:把 OpenAI / Anthropic / Google / Bedrock / Mistral 抹平成一套流式接口packages/ai/src/index.ts
packages/agent@earendil-works/pi-agent-coreagent 运行时:循环、工具调用、状态管理,外加 harness(会话树/压缩/skills)packages/agent/src/index.tsagent-loop.ts
packages/tui@earendil-works/pi-tui终端 UI 库,差分渲染(differential rendering)高效重画文本界面packages/tui/src/index.tstui.ts
packages/coding-agent@earendil-works/pi-coding-agent顶层产品 pi:工具集 + 扩展/skills/主题 + 会话管理 + CLIpackages/coding-agent/src/main.tscli.ts
packages/orchestrator@earendil-works/pi-orchestrator实验性、可能随时改动/移除的多-agent 编排包packages/orchestrator/src/index.ts

包描述取自各自 package.jsonname/description 字段 (packages/ai/package.jsonpackages/agent/package.jsonpackages/tui/package.jsonpackages/coding-agent/package.jsonpackages/orchestrator/package.json)。

分层依赖图

怎么读这张图: 箭头 A → B 表示「A 依赖 B」;越往下越底层、越通用,越往上越贴近产品。 依赖关系取自各包 package.jsondependencies 字段。

实验层 pi-orchestrator 实验性 · 多 agent 编排
│ 依赖

产品层 pi-coding-agent 顶层产品 = 命令 `pi`(工具 / 扩展 / 会话 / CLI)

┌────────┼─────────────┐ coding-agent 同时依赖这三个
│ │ │
▼ ▼ ▼
pi-tui pi-agent-core pi-ai
(渲染) (循环+harness) (统一 LLM)
│ 依赖
└──────────► pi-ai

三条关键事实(都来自 dependencies):

  • pi-tuipi-ai 是最底层、彼此独立的两块——一个只管画屏幕,一个只管跟模型说话, 谁都不依赖谁,也不依赖上层(packages/tui/package.jsonpackages/ai/package.json)。
  • pi-agent-core 只依赖 pi-ai(packages/agent/package.json"@earendil-works/pi-ai": "^0.80.2")——循环逻辑只需要「能跟模型说话」,不关心终端长什么样。
  • pi-coding-agent 依赖前面三个全部(packages/coding-agent/package.json 同时列出 pi-agent-corepi-aipi-tui),因为它要把「循环 + LLM + 屏幕」组装成真正的产品。

注:很容易把这几个包脑补成一条线性栈 "pi-tui ← pi-ai ← pi-agent-core ← pi-coding-agent", 但那只是一条便于记忆的简化心智链;真实的依赖边如上图——pi-tuipi-ai 是彼此独立的 并列底座,pi-agent-core 只依赖 pi-ai,pi-coding-agent 才把三者汇到一起 (以各包 package.jsondependencies 为准)。

一句话记住每层的分工

  • pi-ai: 「跟谁说、怎么说」——统一 LLM 层。→ 详见 01-unified-llm.md
  • pi-agent-core: 「一轮轮怎么转」——循环 + 工具调用 + harness。→ 详见 02-agent-loop.md03-harness-context.md
  • pi-coding-agent: 「有哪些手脚、怎么当命令用」——工具/扩展/CLI。→ 详见 04-coding-agent.md
  • pi-tui: 「屏幕怎么画」——差分渲染 UI。→ 详见 05-tui.md

3. 主线走一遍(端到端控制流,只点部件不进代码)

跟着一句用户输入,看它怎么穿过四个包。怎么读: 从上往下是时间顺序,箭头旁标的是「传下去的东西」。

用户在终端敲一句话


[coding-agent] 组装 system prompt + 工具集 + 会话上下文 main.ts → AgentSession
│ prompts, AgentContext{systemPrompt, messages, tools}, config

[agent-core] runLoop:开始一轮(turn) agent-loop.ts
│ 把 AgentMessage[] 转成 LLM 的 Context

[pi-ai] streamSimple:按 provider 发请求、流式解码回复 compat.ts streamSimple
│ 流式 AssistantMessage(可能带一个/多个 toolCall)

[agent-core] 有 toolCall?→ executeToolCalls 执行工具 agent-loop.ts
│ 调用 coding-agent 注册的 read/edit/bash…,产出 ToolResultMessage

[agent-core] 结果回填进 messages → 回到 runLoop 开下一轮 (循环直到没有工具调用)


[pi-tui] 差分渲染:把这一路的事件流实时画到终端 tui.ts TUI

逐步拆解(每步只点关键部件与符号,细节留给后续章):

  1. 组 prompt / 工具(coding-agent)。 main() 解析 CLI 参数、建会话,最终由 AgentSession 把系统提示、工具集(默认 read/write/edit/bash)、上下文交给 agent 循环 (packages/coding-agent/src/main.ts:468 main;系统提示由 packages/coding-agent/src/core/system-prompt.ts:28 buildSystemPrompt 拼)。

  2. 进入循环(agent-core)。 Agent 类内部调 runAgentLoop,核心是 runLoop——一个「说话 → 看有没有工具要执行 → 执行 → 再说话」的内外双层循环 (packages/agent/src/agent-loop.ts:155 runLoop;packages/agent/src/agent.ts:166 class Agent)。

  3. 调 LLM(经 pi-ai)。 每轮 streamAssistantResponseAgentMessage[] 转成 LLM 的 Context,交给 streamSimple 流式拿回复(packages/agent/src/agent-loop.ts:275 streamAssistantResponse)。streamSimple 再按 model.api 分派到对应 provider 实现 (packages/ai/src/compat.ts:258 streamSimple)。

  4. 执行工具(agent-core 调 coding-agent 的工具)。 回复里若含 toolCall, executeToolCalls 会校验参数、跑 tool.execute、把产出包成 ToolResultMessage 塞回上下文, 于是下一轮模型能"看到"结果(packages/agent/src/agent-loop.ts:373 executeToolCalls)。 工具本身由 coding-agent 提供(packages/coding-agent/src/core/tools/)。

  5. 渲染(pi-tui)。 整个过程 agent 循环持续 emit 事件(message_starttool_execution_end…), 交互模式把它们喂给 TUI 差分重画终端(packages/tui/src/tui.ts:295 class TUI)。

一个要记住的巧妙点: agent 循环内部始终用 AgentMessage,只在「要调 LLM 的那一刻」 才转成 provider 认识的 Message[]——这条边界把「循环逻辑」和「各家模型格式差异」彻底解耦 (见 agent-loop.ts 顶部注释与 streamAssistantResponse)。


4. 阅读地图(01–05 章各讲什么)

这组文档由浅入深。建议顺序、每章讲什么、给谁读:

顺序章节讲什么建议读者
①(先读)本章 index.mdPi 是什么 · 四包全景 · 端到端主线 · 导航所有人,尤其第一次接触
01-unified-llm.mdpi-ai 怎么把各家 LLM 抹平成一套统一流式 API(provider 分派、模型目录、流式事件)想搞懂"跟模型说话"这层的人
02-agent-loop.mdpi-agent-core 的 agent 循环:turn 结构、工具并行/串行执行、steering/follow-up 消息想搞懂"一轮轮怎么转"的人
03-harness-context.mdHarness 层:会话树(session)、系统提示装配、Skills、上下文压缩(compaction)关心长会话、记忆与上下文管理的人
04-coding-agent.mdpi-coding-agent:read/write/edit/bash 工具集、扩展/skills 自扩展、interactive/print/rpc/json 四种 CLI 模式要用/扩展 pi 这个产品的人
05-tui.mdpi-tui:差分渲染原理、组件模型、终端 UI 库想做自定义终端 UI 或好奇渲染细节的人

两条推荐路线:

  • 想"会用 + 懂大盘": 本章 → 04(产品/CLI)→ 需要时回看 02(循环)。
  • 想"从底往上吃透原理": 本章 → 01(LLM 层)→ 02(循环)→ 03(harness)→ 04(工具/CLI)→ 05(渲染)。

5. 巧妙之处速览(先建立心智,不进细节)

这几处是 Pi 的"设计精华",本章只点名建立印象,具体在各章展开:

  • 内核小、能力靠自扩展长出来。 工具、命令、UI 用 TS 扩展加;技能用 Skills 按需加载; 还能打包成 "pi 包" 分享——pi 甚至能用自己改自己(packages/coding-agent/docs/index.md:52-59)。→ 04 章
  • AgentMessage 与 LLM Message 的边界。 循环内部只认自己的消息类型,只在调用 LLM 那一刻转换, 把循环逻辑和各家格式差异隔开(packages/agent/src/agent-loop.ts:275-296)。→ 02 章
  • 统一 LLM 层 + 运行时 provider 分派。 同一个 streamSimple,靠 model.api 决定发给谁 (packages/ai/src/compat.ts:258)。→ 01 章
  • 差分渲染。 TUI 只重画变化的行,而不是每帧全清屏重绘,终端里也能有流畅 UI (packages/tui/src/tui.ts:2 文件注释、:295 class TUI)。→ 05 章
  • steering / follow-up 消息。 用户在模型"思考"时插话,或在它本要停下时追加任务, 循环都能接住(packages/agent/src/agent-loop.ts:167:253:257)。→ 02 章
  • 不内建权限系统,靠容器化划边界。 默认以启动它的用户权限运行,要更强隔离就沙箱化 (README.md:37-45)。→ 04 章

6. 顶层代码地图(各包入口 · 给人和 agent 的跳转表)

想直接钻进源码,从这些入口开始。列出真实符号名,便于用 grep 定位(比行号抗漂移):

想看什么文件路径关键符号
coding-agent CLI 真正入口(设进程标题后调 main)packages/coding-agent/src/cli.tsmain(process.argv.slice(2))
CLI 参数 → 会话 → 选模式的总装配packages/coding-agent/src/main.ts:468main
SDK 式创建一个会话(嵌入用)packages/coding-agent/src/core/sdk.ts:166createAgentSession
面向 CLI 的会话对象(拿 Agent 驱动循环)packages/coding-agent/src/core/agent-session.ts:266class AgentSession
系统提示装配(工具/指南/上下文/skills)packages/coding-agent/src/core/system-prompt.ts:28buildSystemPrompt
内建工具集packages/coding-agent/src/core/tools/read / write / edit / bash / grep / find / ls
agent-core 对外导出面packages/agent/src/index.tsexport *(agent / loop / harness)
agent 循环核心packages/agent/src/agent-loop.ts:31:155agentLooprunLoop
单轮:转消息 + 调 LLMpackages/agent/src/agent-loop.ts:275streamAssistantResponse
工具执行(并行/串行)packages/agent/src/agent-loop.ts:373executeToolCalls
驱动循环的 Agent 类packages/agent/src/agent.ts:166class Agent
Harness(会话树/压缩/skills)packages/agent/src/harness/agent-harness.ts:157class AgentHarness
pi-ai 对外导出面packages/ai/src/index.tsexport *(models / auth / types)
统一流式入口(按 provider 分派)packages/ai/src/compat.ts:258streamSimple
TUI 差分渲染主类packages/tui/src/tui.ts:295class TUI
TUI 对外导出面packages/tui/src/index.ts组件 / 键位 / fuzzy
实验性编排包入口packages/orchestrator/src/index.tsexport *

各章会用相对链接互链;需要更深的机制,直接跳 01 / 02 / 03 / 04 / 05。本章只做导航,不重复它们的细节。