的?)
作為龍蝦(OpenClaw)早期的實現(xiàn)基座, 開源AI Agent項目“pi”,正被越來越多人所提及. 其優(yōu)雅簡潔的設計以及便捷的擴展能力讓你可以輕松的基于它進行二次創(chuàng)作而快速地得到自己獨有的Agent. 尤其在各路主流Coding Agent內置了各種臃腫上下文的情況下(比如在claude code輸入一個hello則動輒攜帶上萬token的提示詞), 清爽簡潔的pi則看起來別具一格.而從agent設計入門和借鑒的角度, pi也是再好不過的一個參考項目.廢話不多說, 本篇從全局出發(fā)一窺pi的設計思想和整體架構.從v0.80.3開始, pi逐漸調整架構, 拆分出更多細分職責的包. 然而舊版本在包劃分上更簡潔易于理解. 本篇先使用v0.80.3以前版本來分析.下篇將分析最新版本.1. 概覽pi主要是用TypeScript開發(fā), 是一個 monorepo4個npm包按依賴方向自下而上堆疊層包名角色能否獨立運行L1earendil-works/pi-ai多 provider 統(tǒng)一 LLM 流式 API可被其它包引用L2earendil-works/pi-agent-core通用 Agent 運行時循環(huán) / 狀態(tài) / 工具 / Session可提供 SDKL3earendil-works/pi-tui終端 UI 與差分渲染可提供組件庫L4earendil-works/pi-coding-agent交互式 CLI 應用main.ts 模式分發(fā)最終運行入口用戶執(zhí)行的pi命令 L4 啟動依次調用 L2 驅動 AgentAgent 通過 L1 調用大模型最終通過 L3 在屏幕渲染消息。2. 依賴方向圖依賴關系L4 同時依賴 L2、L3、L1L2 與 L3 都依賴 L1。方向單向下層不知道上層。關鍵約束依賴方向是單向的下層永遠不知道上層的存在。這讓pi-agent-core可以脫離 CLI 被任何宿主SDK、測試、第三方應用使用。3. 各模塊職責pi-ai屏蔽各 LLM providerAnthropic / OpenAI / Google / Bedrock / Mistral / Cloudflare / Vertex / GitHub Copilot / OpenAI Codex 等的協(xié)議差異對外只暴露streamSimple(model, context, options)。內置fauxprovider 用于測試。pi-agent-core與 UI / CLI / 應用場景無關的通用 Agent 運行時。提供低層 Agent Loop流式 工具調用循環(huán)、高層 AgentHarnessSession 集成 Compaction Skills、狀態(tài)機、工具協(xié)議。pi-tui通用 TUI 庫。TUI類提供組件樹 鍵盤事件 差分渲染Editor、Input、Markdown等是可復用組件。無任何 Agent 業(yè)務邏輯。pi-coding-agent把上述三者組裝成用戶可用的 CLI。負責 CLI 解析、SessionManager、擴展系統(tǒng)、內置工具、多種運行模式interactive / print / json / rpc。4. 啟動鏈路從pi命令到第一次回復以下時間線描述一次pi啟動在 4 個包之間發(fā)生了什么。4.0 啟動總覽粉L4 / 藍L2 / 黃L1。虛線是事件回流方向與實線反向。步驟 1CLI 入口L4packages/coding-agent/src/main.ts:477pi-coding-agentexport async function main(args: string[], options?: MainOptions)main()是CLI入口函數(shù)由 dist 編譯后的dist/cli.js調用。入口函數(shù)順序執(zhí)行解析參數(shù) → 決定模式 → 加載配置 → 構建 runtime → 分發(fā)到模式。步驟 2參數(shù)解析與模式分發(fā)L4main.ts:497-509.pi-coding-agentconst parsed parseArgs(args); // cli/args.tslet appMode resolveAppMode(parsed, process.stdin.isTTY);appMode類型為interactive | print | json | rpc由命令行參數(shù)和 stdin 是否是 TTY 共同決定。步驟 3創(chuàng)建 SessionManagerL4main.ts:250-322pi-coding-agent根據(jù)--fork/--session/--resume/--no-session等參數(shù)決定是新建、分叉、恢復還是純內存 Session。核心 APISessionManager.inMemory(cwd) // 純內存不落盤SessionManager.open(path, dir) // 打開已有 JSONLSessionManager.forkFrom(path) // 從已有分叉步驟 4構建 Agent Session runtimeL4 ? L2packages/coding-agent/src/core/sdk.ts:204pi-coding-agentexport async function createAgentSession(options)這是 SDK 入口。它做 5 件事解析cwd、agentDir、authStorage、modelRegistry?;謴蜌v史SessionsessionManager.buildSessionContext()。解析模型options → 歷史 → 配置 → provider 默認。實例化Agent來自 L2 pi-agent-core。構造AgentSession封裝 Agent 與 SessionManager。關鍵代碼sdk.ts:331-394agent new Agent({initialState: { systemPrompt: , model, thinkingLevel, tools: [] },convertToLlm,streamFn: async (model, context, options) { return streamSimple(model, context, { ... }); },transformContext, steeringMode, followUpMode, ...});步驟 5Agent 啟動首輪對話L2packages/agent/src/agent.ts:386-400pi-agent-coreprivate async runPromptMessages(messages: AgentMessage[]) {await this.runWithLifecycle(async (signal) {await runAgentLoop(messages,this.createContextSnapshot(),this.createLoopConfig(),(event) this.processEvents(event), // ← emit 回調signal,this.streamFn, // ← streamSimple);});}Agent 持有_state狀態(tài)機調用runAgentLoop驅動 LLM 與工具循環(huán)。詳見后續(xù)對Agent Loop的詳解。步驟 6流式調用 LLML1packages/ai/src/stream.tspi-aistreamSimple(model, context, options)根據(jù)model.api在api-registry.ts查找對應provider實現(xiàn)返回AssistantMessageEventStream。provider 屏蔽 HTTP/SSE/WebSocket 差異。步驟 7事件回流到 UIL4 → L3agent.ts:509-556Agent 層 agent-session.ts:460-510Coding Agent 層pi-agent-core / pi-coding-agentLLM 流式事件經(jīng)processEvents更新 Agent 狀態(tài)然后通過subscribe()傳遞給AgentSession._handleAgentEvent再轉發(fā)給InteractiveMode最終由TUI差分渲染到屏幕。詳見后續(xù)消息傳遞分發(fā)鏈路詳解。5. 端到端數(shù)據(jù)流從用戶按鍵到屏幕像素的完整調用鏈每個箭頭都是一次跨層調用。6. 關鍵模塊職責映射職責所在包關鍵文件說明CLI 入口pi-coding-agentmain.ts:477解析參數(shù)、決定模式、調用 createAgentSessionSession 持久化pi-coding-agentsession-manager.ts條目樹 JSONL 讀寫擴展系統(tǒng)pi-coding-agentcore/extensions/擴展加載、事件總線、生命周期內置工具pi-coding-agentcore/tools/read / write / edit / bash / grep / find / ls交互模式pi-coding-agentinteractive-mode.ts主循環(huán)、事件訂閱、UI 協(xié)調Agent 狀態(tài)機pi-agent-coreagent.ts_state 狀態(tài)、steering/followUp 隊列Agent Looppi-agent-coreagent-loop.tsrunAgentLoop / runLoop / 流式處理Agent Harnesspi-agent-coreharness/agent-harness.ts高層封裝Session Compaction Skills通用 Sessionpi-agent-coreharness/session/JSONL/Memory repo、buildContextCompactionpi-agent-coreharness/compaction/上下文壓縮 / 分支摘要流式 APIpi-aistream.tsstreamSimple 統(tǒng)一入口Provider 注冊pi-aiapi-registry.ts按 api 類型查找 Provider模型元數(shù)據(jù)pi-aimodels.tsmodels.generated.ts 靜態(tài)索引OAuthpi-aiutils/oauth/Claude / ChatGPT / Copilot OAuthTUI 主類pi-tuitui.ts組件樹 鍵盤事件循環(huán)編輯器pi-tuicomponents/editor.ts輸入框 歷史 自動補全差分渲染pi-tuitui.ts:extractSegments...按行比較僅重繪差異行7. 設計原則單向依賴L1 ← L2 ← L3 ← L4禁止反向。下層不知道上層存在pi-agent-core可被任意宿主復用。事件流而非命令流Agent Loop 通過emit(event)推送事件監(jiān)聽器按訂閱順序處理。UI 端訂閱 → Coding Agent 層訂閱 → Agent 處理 狀態(tài)。協(xié)議式工具調用LLM 返回的tool_use塊被解析為AgentTool調用工具執(zhí)行結果以toolResult消息回寫上下文。Session 與 State 解耦Agent 的_state是運行時內存SessionManager是 JSONL 持久層二者通過 AgentSession 橋接并雙寫。擴展點優(yōu)先于硬編碼擴展系統(tǒng)提供tool_call、before_agent_start、input、tool_result等鉤子業(yè)務能力大多可由擴展覆蓋??蓽y試的 Provider 邊界pi-ai內置fauxprovider所有上游代碼都可以在零成本下測試。