
1. 项目定位与整体架构
Pi 是一个可扩展的编码智能体(coding agent)框架:核心是 Agent 循环 + 多提供商 LLM 抽象 + 工具系统,外层是 CLI/TUI、会话持久化和扩展机制。
- 根工程:npm workspaces,ESM,Node >= 22.19,TypeScript 7(
D:\work\pi\package.json:5-13,:71-73) - 11 个包:
agent、ai、chord、codemode、coding-agent、durable、env、evals、mcp、telemetry、tui - 构建顺序在
D:\work\pi\package.json:16:chord → tui → telemetry → codemode → mcp → ai → durable → env → agent → coding-agent
内部依赖关系(来自各包 package.json):
coding-agent → agent, ai, codemode, mcp, tui
agent → ai
ai → telemetry
durable → chord, ai, codemode
env → chord, durable
evals → ai, coding-agent (dev)
关键点:durable / env 是独立的持久化运行时与远程执行环境,当前没有被 coding-agent 引用 ;chord 只被 durable / env 使用。
分层视图
┌──────────────────────────────────────────────────────────┐
│ 入口/交互层 cli.ts → main.ts → interactive / print / rpc │
├──────────────────────────────────────────────────────────┤
│ 会话编排层 AgentSessionRuntime + AgentSession + Services │
├──────────────────────────────────────────────────────────┤
│ 智能体内核 Agent + agent-loop(流式响应、工具执行、队列)│
├──────────────────────────────────────────────────────────┤
│ 模型层 pi-ai:Models / Provider / API Registry │
├──────────────────────────────────────────────────────────┤
│ 工具与扩展 内置工具、ExtensionRunner、MCP、codemode │
├──────────────────────────────────────────────────────────┤
│ 持久化 SessionManager(JSONL);durable(独立运行时)│
├──────────────────────────────────────────────────────────┤
│ 终端 UI pi-tui(差分渲染、viewport、输入/编辑器组件) │
└──────────────────────────────────────────────────────────┘
2. 核心模块与调用关系
2.1 启动链路
入口非常薄:
packages/coding-agent/src/cli.ts:1-6:调用setupCli()和main(process.argv.slice(2))packages/coding-agent/src/main.ts:574:main()是真正的启动编排器
main() 的顺序(main.ts:574-1000):
- 离线标记、主题校验、内置扩展列表(
:578-583) runAuthCommand()处理pi auth ...(:585)handlePackageCommand()/handleConfigCommand()/pi mcp子命令(:600-621)parseArgs(),处理--version、--export(:623-652)- 运行迁移
runMigrations()(:669) - 创建
SettingsManager、首次设置、主题(:672-684) createSessionManager()选择/创建/恢复/fork 会话(:696, 定义在:358)- 构造
createRuntime工厂并调用createAgentSessionRuntime()(:733-870) - 按模式分发(
:949-999):runRpcMode(runtime)(RPC)new InteractiveMode(runtime, ...).run()(交互 TUI)runPrintMode(runtime, ...)(单次文本/JSON 输出)
createRuntime 内部完成 cwd 绑定服务的重建(main.ts:733-864):
createAgentSessionServices() // modelRuntime / settings / resourceLoader
→ DefaultResourceLoader.reload() // 发现 extensions/skills/templates/themes
→ resolveModelScope()
→ createAgentSessionFromServices()
→ sdk.createAgentSession()
→ new Agent(...) + new AgentSession(...)
对应代码:
packages/coding-agent/src/core/agent-session-services.ts:135(createAgentSessionServices)packages/coding-agent/src/core/agent-session-services.ts:214(createAgentSessionFromServices)packages/coding-agent/src/core/sdk.ts:191(createAgentSession)packages/coding-agent/src/core/sdk.ts:411(new Agent)packages/coding-agent/src/core/sdk.ts:461(new AgentSession)
2.2 AgentSession:会话编排核心
packages/coding-agent/src/core/agent-session.ts:379 定义 AgentSession,它是三种运行模式共享的会话抽象。构造函数在 :486:
- 订阅
Agent事件(持久化、扩展事件、自动压缩、重试) - 安装工具钩子
_installAgentToolHooks()(:653) - 安装下一轮刷新、请求投影、边界钩子(
:516-520) - 构建运行时工具集
_buildRuntime()(:522)
主要职责:
| 职责 | 位置 |
|---|---|
| 发送 prompt、排队 steer/followUp | prompt() :2058,_startRun() :1837 |
| 运行前准备(压缩、扩展钩子、图像、工具装载) | _prepareRun() :1890 |
| 工具调用前后拦截 | _beforeToolCall() :659,_afterToolCall() :685 |
| 嵌套工具调用 | _executeNestedToolCall() :731 |
| 手动/自动压缩 | compact() :2794,_runAutoCompaction() :3127 |
| 模型与思考等级切换 | setModel() :2507,setThinkingLevel() :2642 |
| 扩展绑定 | bindExtensions() :3288 |
| 会话统计、导出、树导航 | getSessionStats() :4213,exportToHtml() :4318,navigateTree() :3994 |
2.3 Agent 内核:状态机与循环
packages/agent/src/agent.ts:188 定义 Agent,负责状态、事件、队列和生命周期:
prompt():371→runPromptMessages():432→runAgentLoop()continue():384→runAgentLoopContinue()runWithLifecycle():507:创建AbortController、设置isStreaming、失败时生成错误消息processEvents():565:归约message_start/update/end、tool_execution_*、turn_end、agent_end,再按订阅顺序 await 监听器steer()/followUp()队列::299-332
packages/agent/src/agent-loop.ts 是实际循环:
runAgentLoop():102:加入 prompt、声明工具变更、发出agent_start/turn_startrunLoop():163:外层处理 follow-up,内层处理工具调用与 steeringstreamAssistantResponse():381:transformContext → convertToLlm → getApiKey → streamFunction,逐事件转发并生成最终AssistantMessageexecuteToolCalls():508:根据toolExecution和工具自身的executionMode选择串行/并行- 工具结果消息在
:930构造;截断响应中的工具调用在:478统一失败,避免执行不完整参数
消息类型扩展(bashExecution、custom、branchSummary、compactionSummary)在 packages/coding-agent/src/core/messages.ts:29-77,并通过 convertToLlm() 转成 LLM 可接受的消息。
2.4 pi-ai:多提供商模型层
packages/ai/src/index.ts 明确只导出"无副作用核心",不导出生成目录、provider 工厂或 API 注册表;这些通过子路径导入(index.ts:4-8)。
核心抽象在 packages/ai/src/types.ts:
Model/ImageModel/ClassifierModel::825-898ProviderStreams::311Context/TranscriptContext::771-785AssistantMessageEvent::806
运行时实现:
ModelsImpl:packages/ai/src/models.ts:395createModels()::998createProvider()::1047ModelsImpl.streamSimple()::907builtinProviders():packages/ai/src/providers/all.ts:136(约 40 个提供商)- 兼容层 API 注册表:
packages/ai/src/compat.ts:180-191注册anthropic-messages、openai-completions、openai-responses、google-generative-ai、bedrock-converse-stream、pi-messages等 compat.streamSimple()::278按模型 API 选择内置 provider 或注册表实现
每个 provider 的典型结构(以 Anthropic 为例,packages/ai/src/providers/anthropic.ts:74-90):
ts
createProvider({
id: "anthropic",
baseUrl: "https://api.anthropic.com",
auth: { apiKey: ..., oauth: ... },
models: Object.values(ANTHROPIC_MODELS),
api: anthropicMessagesApi(),
})
API 实现通过 .lazy.ts 延迟加载(packages/ai/src/api/lazy.ts:46-99),避免启动时加载所有提供商 SDK。模型目录由 models.generated.ts + 运行时 catalog 刷新组成(models-store.ts、model-catalog.ts)。
coding-agent 的 ModelRuntime(packages/coding-agent/src/core/model-runtime.ts:173)在 Models 之上增加了:认证同步、provider 动态注册、虚拟模型路由、可用性刷新。streamSimple() 在 :723。
2.5 工具系统
内置 8 个工具,统一由工厂函数 + TypeBox schema 定义:
- 导出与名称集合:
packages/coding-agent/src/core/tools/index.ts:95 - 默认编码工具集:
:164(read/bash/edit/write) - 只读工具集:
:173(read/grep/find/ls) - 单工具工厂:
:141
实现文件:
read.ts:读取文件/图片、截断、图像缩放bash.ts:shell 执行、超时、输出累积、进程树清理edit.ts/write.ts:带file-mutation-queue.ts串行化同一文件的修改grep.ts/find.ts/ls.ts:检索类工具powershell.ts:Windows 专用truncate.ts:统一的头/尾截断策略
工具最终实现 AgentTool.execute(id, args, signal, onUpdate),由 agent-loop 调用。
2.6 扩展系统
内置扩展注册在 packages/coding-agent/src/extensions/index.ts:7-14:
llama.cppcodemode(可替换)tool-search(可替换)mcp(可替换)
ExtensionRunner(packages/coding-agent/src/core/extensions/runner.ts:364)负责:
bindCore():417:把宿主能力注入扩展运行时- 事件分发:
emitToolCall():1249、emitToolResult():1190、emitInput():1525、emitBeforeAgentStart():1427、emitContext():1305、provider 请求/响应钩子:1368-1399、会话边界:1036 - UI 上下文、命令、快捷键、工具渲染器
资源发现由 DefaultResourceLoader(packages/coding-agent/src/core/resource-loader.ts:315)完成:扩展、skills、prompt templates、themes、context files、项目信任。扩展加载在 packages/coding-agent/src/core/extensions/loader.ts:718。
2.7 MCP 与 codemode
pi-mcp是独立 MCP 客户端:McpClient(packages/mcp/src/client.ts:155),支持 stdio 与 Streamable HTTP 传输、OAuth、工具/资源调用。coding-agent内置 MCP 扩展:packages/coding-agent/src/extensions/mcp/index.ts:279(createMcpExtension)。它把 MCP 工具映射为mcp__<server>__<tool>,并支持codemode/deferred/direct/hidden暴露模式。pi-codemode在 QuickJS/WASM 沙箱中执行模型写的 JavaScript,只暴露工具调用能力;嵌套工具调用不进入 LLM 上下文(packages/codemode/src/runtime/execution.ts:460、packages/codemode/src/runtime/vm.ts:160)。coding-agent的 codemode 扩展入口:packages/coding-agent/src/extensions/codemode/index.ts:32。
2.8 TUI
pi-tui 是独立的终端 UI 库,只被 coding-agent 使用:
- 组件模型:
Component.render(width)+handleInput+invalidate(packages/tui/src/tui.ts:117) Container::358;TUI/TuiBase::464/:506- 主屏差分渲染:
packages/tui/src/tui-main-screen.ts:124 - 备用屏视口:
packages/tui/src/tui-alt-screen.ts:202 - 布局引擎:
packages/tui/src/layout.ts:379 - 输入/按键:
packages/tui/src/keys.ts:163、packages/tui/src/keybindings.ts:231 - 编辑器、Markdown、SelectList、ScrollView 等组件:
packages/tui/src/components/*
coding-agent 的交互模式在 packages/coding-agent/src/modes/interactive/interactive-mode.ts:451(InteractiveMode),init() :943,run() :1146,事件处理 handleEvent() :3408。
2.9 durable / env(独立运行时)
pi-durable:以"先提交、后发布"为核心的可恢复 agent 运行时。- Session 内核:
packages/durable/src/session/session.ts:69 - Harness:
packages/durable/src/harness/harness.ts:181/:460 - Storage:memory / JSONL / SQLite(
packages/durable/src/storage/*) - 任务调度:
packages/durable/src/harness/scheduler.ts:200
- Session 内核:
pi-env:通过 SSH + Rust daemon 提供远程ExecutionEnv。Connection:packages/env/src/connection.ts:181RemoteExecutionEnv:packages/env/src/remote-env.ts:354- SSH 部署:
packages/env/src/ssh.ts
这两个包当前不参与 coding-agent 的启动链路,属于可独立使用的运行时/执行环境。
3. 关键入口文件与函数
| 作用 | 文件:行 |
|---|---|
| CLI 可执行入口 | packages/coding-agent/src/cli.ts:1 |
| 启动编排 | packages/coding-agent/src/main.ts:574 |
| 参数解析 | packages/coding-agent/src/cli/args.ts(parseArgs) |
| 创建会话管理器 | packages/coding-agent/src/main.ts:358 |
| 创建运行时 | packages/coding-agent/src/core/agent-session-runtime.ts:420 |
| 创建 cwd 服务 | packages/coding-agent/src/core/agent-session-services.ts:135 |
| SDK 入口 | packages/coding-agent/src/core/sdk.ts:191 |
| 会话编排类 | packages/coding-agent/src/core/agent-session.ts:379 |
| 发送 prompt | packages/coding-agent/src/core/agent-session.ts:2058 |
| Agent 类 | packages/agent/src/agent.ts:188 |
| Agent 循环 | packages/agent/src/agent-loop.ts:102 |
| 流式响应 | packages/agent/src/agent-loop.ts:381 |
| 工具执行 | packages/agent/src/agent-loop.ts:508 |
| 模型集合 | packages/ai/src/models.ts:395 |
| 提供商注册表 | packages/ai/src/providers/all.ts:136 |
| API 注册表 | packages/ai/src/compat.ts:180 |
| 内置工具注册 | packages/coding-agent/src/core/tools/index.ts:95 |
| 内置扩展列表 | packages/coding-agent/src/extensions/index.ts:7 |
| 扩展事件运行器 | packages/coding-agent/src/core/extensions/runner.ts:364 |
| MCP 扩展 | packages/coding-agent/src/extensions/mcp/index.ts:279 |
| 打印模式 | packages/coding-agent/src/modes/print-mode.ts:33 |
| RPC 模式 | packages/coding-agent/src/modes/rpc/rpc-mode.ts:54 |
| 交互模式 | packages/coding-agent/src/modes/interactive/interactive-mode.ts:451 |
| 会话持久化 | packages/coding-agent/src/core/session-manager.ts:987 |
| TUI 核心 | packages/tui/src/tui.ts:506 |
4. 主要业务逻辑
4.1 一次 prompt 的完整调用链
以交互模式输入一条消息为例:
InteractiveMode提交文本 →AgentSession.prompt()(agent-session.ts:2058)- 扩展命令拦截(
/command)、input事件、skill/prompt template 展开(:2065-2100) - 如果正在流式输出,进入
steer/followUp队列(:2102-2116) - 校验模型与认证(
:2118-2136) _startRun()(:1837):_prepareRun():必要时先压缩、触发before_agent_start、处理图片、更新工具装载(:1890)agent.prompt(messages)(:1863)
Agent.prompt()→runPromptMessages()→runAgentLoop()(agent.ts:432,agent-loop.ts:102)runLoop()(agent-loop.ts:163):- 处理 steering / follow-up
streamAssistantResponse():convertToLlm→ 选择模型认证 →streamFunction- 收集
toolCall,执行工具(串行/并行) - 发出
turn_end;如果还有工具调用或排队消息则继续
AgentSession通过订阅的_handleAgentEvent持久化消息、转发扩展事件、触发自动压缩/重试(agent-session.ts:1288,:3127,:3792)- 最终
agent_end→ UI 更新或 print/RPC 输出
4.2 工具调用与扩展拦截
工具执行前后各有一层扩展钩子:
_beforeToolCall()(agent-session.ts:659)→tool_call扩展事件,可阻止或修改调用_afterToolCall()(:685)→tool_result扩展事件,可替换内容/错误状态,并统一做图像归一化- 嵌套工具调用(工具内部通过
ctx.executeTool()再调用工具)复用同一套钩子(:731)
agent-loop 对未知工具、参数校验失败、被阻止、抛异常都返回 isError: true 的工具结果,而不是让循环崩溃(agent-loop.ts:708-777)。
4.3 会话持久化、恢复与分支
SessionManager(session-manager.ts:987)以 JSONL 文件保存会话:
- 条目类型:message、thinking_level_change、model_change、usage、compaction、branch_summary、custom、label、session_info、context_edit(
:57-197) - 当前版本
CURRENT_SESSION_VERSION = 3,带 v1→v2→v3 迁移(:41,:287-350) - 创建/打开/继续/内存/fork:
:1755-1874 - 上下文投影:
buildSessionProjection():1493,buildSessionContext():1497 - 分支:
branch():1579,createBranchedSession():1632
AgentSessionRuntime(agent-session-runtime.ts:74)负责运行时替换:switchSession()、newSession()、fork()、importFromJsonl(),每次先 teardown 旧会话、再重建 cwd 服务和新 AgentSession。
4.4 上下文压缩与重试
- 压缩算法在
packages/coding-agent/src/core/compaction/compaction.ts,入口聚合在index.ts - 阈值判断:
AgentSession._exceedsCompactionThreshold()(agent-session.ts:768) - 自动压缩:
_checkCompaction():2977、_runAutoCompaction():3127 - 手动压缩:
compact():2794 - 重试:
_prepareRetry():3792,判断可重试错误_isRetryableError():3739,取消_finishCancelledRetry():3776
4.5 三种运行模式
| 模式 | 文件 | 行为 |
|---|---|---|
| Interactive | modes/interactive/interactive-mode.ts:451 |
TUI、编辑器、选择器、主题、扩展 UI |
modes/print-mode.ts:33 |
单次执行,text 只输出最终文本,json 输出事件流 |
|
| RPC | modes/rpc/rpc-mode.ts:54 |
stdin/stdout JSON 协议,供外部程序嵌入 |
三种模式共享同一个 AgentSessionRuntime 和 AgentSession,只是 I/O 层不同。
4.6 模型、认证与目录刷新
ModelRuntime.create()(model-runtime.ts:217)加载auth.json、models.json,组合内置 + 动态 provider- 认证解析:
getAuth():557,支持 API key、OAuth、订阅、环境变量 - 运行时刷新:
refresh():848,离线时只读缓存 - 模型选择:
resolveCliModel()/resolveModelScope()(core/model-resolver.ts),支持--model provider/pattern、--models、思考等级 - 虚拟模型路由:
registerVirtualModel():964、resolveModel():1003
4.7 扩展、MCP 与 codemode 的协作
- 扩展在
DefaultResourceLoader.reload()中加载,ExtensionRunner.bindCore()注入宿主能力 - MCP 扩展把服务器工具注册为普通 Pi 工具,因此
AgentSession的工具装载、权限过滤、codemode 可见性都无需特殊分支 - codemode 扩展把工具集合渲染为 TypeScript 声明,在 QuickJS 沙箱中执行,工具调用通过
executeTool()回到同一工具管线(agent-session.ts:731) - tool-search 扩展用于按需暴露大量 MCP 工具,避免一次性塞满系统提示
5. 证据清单(主要文件)
- 启动与模式:
packages/coding-agent/src/cli.ts、main.ts、modes/index.ts、modes/print-mode.ts、modes/rpc/rpc-mode.ts、modes/interactive/interactive-mode.ts - 会话编排:
core/agent-session.ts、core/agent-session-runtime.ts、core/agent-session-services.ts、core/sdk.ts - 智能体内核:
packages/agent/src/agent.ts、agent-loop.ts、types.ts、stream-fn.ts - 模型层:
packages/ai/src/index.ts、models.ts、types.ts、compat.ts、providers/all.ts、providers/*.ts、api/*.ts - 工具:
packages/coding-agent/src/core/tools/*.ts - 扩展:
packages/coding-agent/src/core/extensions/{loader,runner,types}.ts、extensions/index.ts、extensions/mcp/*、extensions/codemode/* - 持久化:
packages/coding-agent/src/core/session-manager.ts;独立运行时packages/durable/src/session/session.ts、harness/harness.ts、storage/* - 终端 UI:
packages/tui/src/index.ts、tui.ts、tui-main-screen.ts、tui-alt-screen.ts、layout.ts - 远程执行:
packages/env/src/connection.ts、remote-env.ts、ssh.ts