14 个包The 14 packages#
一句话结论Takeaway从这里进入每个包的子页面。核心栈是 coding-agent → agent-core → pi-ai,外加 tui;其余包提供 MCP、代码沙箱、遥测、持久化运行时与远程会话。Enter each package's page from here. The core stack is coding-agent → agent-core → pi-ai, plus tui; the rest provide MCP, the code sandbox, telemetry, the durable runtime and remote sessions.
通用 Agent:状态、事件循环、工具执行与钩子General-purpose agent with transport abstraction, state management, and attachment support
2,519 LOC4 tests1 depspi-ai已完成Done统一的 LLM API:模型目录、认证、42 个 provider、事件流Unified LLM API with automatic model discovery and provider configuration
26,797 LOC167 tests1 depscoding-agent已完成Done编码智能体 CLI:工具、会话树、压缩、扩展与运行模式Coding agent CLI with read, bash, edit, write tools and session management
85,816 LOC314 tests6 depstui已完成Done差分渲染的终端 UI 库Terminal User Interface library with differential rendering for efficient text-based applications
19,409 LOC43 tests0 deps独立的 Model Context Protocol 客户端Standalone Model Context Protocol client for pi and other applications
3,243 LOC5 tests0 depscodemode已完成Done沙箱化 JavaScript 执行:唯一能力是调用注入的工具Sandboxed JavaScript execution where the only capability is calling injected tools
1,837 LOC3 tests0 depstelemetry已完成Done与厂商无关的遥测契约与类型化 schema 工具Vendor-neutral telemetry contracts and typed schema utilities for pi
935 LOC2 tests0 deps应用组合运行时:服务、复制状态、RPC 与插件Application composition runtime for services, replicated state, RPC, and plugins
8,817 LOC21 tests0 depsdurable已完成Done持久化的会话、任务与文档运行时Durable conversation, task, and document runtime for Pi
20,404 LOC49 tests2 depsenv已完成DonePi Durable 的远程执行环境(经 SSH 部署的小型守护进程)Remote execution environments for Pi Durable: a small daemon deployed over SSH and its ExecutionEnv client
2,073 LOC5 tests2 deps远程 pi 会话的传输无关 CBOR 协议Transport-neutral CBOR protocol for remote pi sessions
869 LOC3 tests1 depsclient已完成Done基于分帧 CBOR 的远程 pi 会话客户端Transport-neutral client for remote pi sessions over framed CBOR bytes
1,135 LOC3 tests2 depsserver已完成Done实验性的 pi 服务端experimental server package for pi
1,958 LOC6 tests2 depsindex.html#loop 等会自动跳转):First-edition sections that belong to one package now live on that package's page (old links such as index.html#loop redirect automatically):- Agent 循环Agent loop →
agent-core - 工具调用执行Tool call execution →
agent-core - Provider 抽象Provider abstraction →
pi-ai - 会话持久化与分支Session persistence & branching →
coding-agent - 上下文压缩Compaction →
coding-agent - 扩展生命周期Extension lifecycle →
coding-agent - 运行模式Run modes →
coding-agent - TUI 渲染TUI rendering →
tui
如何阅读这些图How to read the diagrams
- 颜色 = 代码所在的层 / 包,所有页面、图、表与幻灯片一致。Colour = the layer / package the code lives in, identical across every page, diagram, table and slide.
- 圆角容器 = 包或层;卡片 = 类、函数或组件;深色胶囊 = 起止点;红色 = 错误路径。Rounded containers = packages or layers; cards = classes, functions or components; dark pill = start / end; red = error path.
- 实线箭头 = 调用 / 依赖;虚线 = 事件、异步返回或 devDependency;流动的虚线标出主路径;圆形数字 = 执行顺序。Solid arrow = call / dependency; dashed = event, async return or devDependency; animated dashes mark the main path; numbered circles = execution order.
- 每张图都带图例。鼠标悬停某个组件会高亮它的连线;点击图可放大、滚轮缩放、拖动平移。Every diagram carries its own legend. Hover a component to highlight its connections; click to enlarge, wheel to zoom, drag to pan.
包依赖图Package dependency graph#
一句话结论Takeaway14 个 npm workspace 包,pi-coding-agent 位于顶端;运行时栈只有四层,其余包互相解耦。14 npm workspace packages with pi-coding-agent on top; the runtime stack is only four packages deep and everything else is decoupled.
要点Key points
pi-coding-agent直接依赖pi-agent-core、pi-ai、pi-tui、pi-mcp、pi-codemode和chord。pi-coding-agentdepends onpi-agent-core,pi-ai,pi-tui,pi-mcp,pi-codemodeandchord.pi-ai唯一的内部依赖是pi-telemetry;pi-tui、pi-mcp、pi-codemode、chord没有任何内部依赖,可以独立使用。pi-ai's only internal dependency ispi-telemetry;pi-tui,pi-mcp,pi-codemodeandchordhave none and can be used standalone.- Durable 与远程会话是一组独立的包:
pi-durable、pi-env、pi-protocol、pi-client、pi-server,都构建在chord之上。Durable and remote sessions form a separate cluster —pi-durable,pi-env,pi-protocol,pi-client,pi-server— all built onchord. - 虚线是
devDependencies:pi-coding-agent只在测试中使用 client / protocol / server;pi-evals依赖 coding-agent 与 ai。Dashed edges aredevDependencies:pi-coding-agentonly uses client / protocol / server in tests;pi-evalsdepends on coding-agent and ai.
工作原理How it works
- 根
package.json用 npm workspaces 管理packages/*。The rootpackage.jsonmanagespackages/*with npm workspaces. npm run build按拓扑顺序依次构建:chord → tui → telemetry → codemode → mcp → ai → durable → env → agent → protocol → client → server → coding-agent。npm run buildbuilds in topological order: chord → tui → telemetry → codemode → mcp → ai → durable → env → agent → protocol → client → server → coding-agent.- 图中的边直接取自每个包
package.json里的@earendil-works/*依赖。Edges are read from each package's@earendil-works/*entries inpackage.json.
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| package.jsonL15 | scripts.build | workspace 与构建顺序workspaces and build order |
| packages/coding-agent/package.jsonL49 | dependencies | 顶层 CLI 的依赖top-level CLI dependencies |
| packages/agent/package.jsonL25 | dependencies | agent core 只依赖 pi-aiagent core depends only on pi-ai |
| packages/ai/package.jsonL69 | dependencies | LLM 层与 vendor SDKLLM layer and vendor SDKs |
分层架构Layered architecture#
一句话结论Takeaway请求自上而下穿过四层:运行模式 → AgentSession → Agent 循环 → pi-ai 统一事件流。A request passes down four layers: run mode → AgentSession → the Agent loop → pi-ai's normalized event stream.
要点Key points
- pi-ai:把 42 个内置 provider 归一为一套流式事件协议
AssistantMessageEventStream。pi-ai normalizes 42 built-in providers into one streaming protocol,AssistantMessageEventStream. - pi-agent-core:与具体产品无关的工具调用循环,所有策略通过
AgentLoopConfig钩子注入。pi-agent-core is a product-agnostic tool-calling loop; all policy is injected throughAgentLoopConfighooks. - pi-coding-agent:
AgentSession组装会话、8 个内置工具、扩展、压缩、设置与模型解析。pi-coding-agent:AgentSessionwires in sessions, 8 built-in tools, extensions, compaction, settings and model resolution. - 运行模式:interactive、print(text / json)和 rpc 共享同一个
AgentSessionRuntime;只有 interactive 使用pi-tui。Run modes: interactive, print (text / json) and rpc share oneAgentSessionRuntime; only interactive usespi-tui.
工作原理How it works
- 模式层调用
AgentSessionRuntime,它持有当前AgentSession,并在 new / switch / fork 时整体替换会话。Modes callAgentSessionRuntime, which owns the currentAgentSessionand replaces it wholesale on new / switch / fork. AgentSession把自己的逻辑挂到Agent的钩子上:prepareNextTurn、prepareRequest、finishTurn、beforeToolCall等。AgentSessionattaches its logic to theAgenthooks:prepareNextTurn,prepareRequest,finishTurn,beforeToolCalland more.sdk.ts把streamFn设为modelRuntime.streamSimple(),由Models注册表找到 provider 和对应的 API 实现。sdk.tssetsstreamFntomodelRuntime.streamSimple(); theModelsregistry resolves the provider and its API implementation.
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/coding-agent/src/core/agent-session.tsL378 | AgentSession | 核心编排对象(约 4.4k 行)the core orchestrator (~4.4k lines) |
| packages/coding-agent/src/core/agent-session-runtime.tsL74 | AgentSessionRuntime | 会话生命周期与替换session lifecycle and replacement |
| packages/coding-agent/src/core/sdk.tsL420 | streamFn | 把 Agent 接到 ModelRuntimeconnects Agent to ModelRuntime |
| packages/agent/src/agent.tsL188 | Agent | 状态、队列与钩子state, queues and hooks |
| packages/ai/src/models.tsL250 | Models | provider / model 注册表provider / model registry |
一次提示的完整时序One prompt, end to end#
一句话结论Takeaway一次用户输入会经过扩展拦截、两次 LLM 请求和一次工具执行;每条消息在 message_end 时写入会话文件。One user prompt passes extension interception, two LLM requests and a tool run; every message is persisted to the session file on message_end.
要点Key points
AgentSession.prompt()的顺序:扩展命令 →input事件 → 展开 skill 与 prompt template → 若正在流式输出则排队为 steer / follow-up → 预检压缩 →before_agent_start→agent.prompt()。AgentSession.prompt()order: extension commands →inputevent → expand skills and prompt templates → queue as steer / follow-up if streaming → pre-prompt compaction check →before_agent_start→agent.prompt().- pi-ai 的流事件(
text_delta、toolcall_delta等)在 agent 层变成message_update。pi-ai stream events (text_delta,toolcall_delta, …) becomemessage_updateagent events. transformContext在 coding agent 中调用emitContext(),扩展可以在每次请求前改写消息。In the coding agenttransformContextcallsemitContext(), so extensions can rewrite messages before every request.
工作原理How it works
- Interactive 模式订阅会话事件,每个 delta 都触发一次(批处理后的)重绘。Interactive mode subscribes to session events; each delta triggers a (batched) re-render.
AgentSession在每个message_end时调用sessionManager.appendMessage(),会话文件随每条完成的消息增量写入。AgentSessioncallssessionManager.appendMessage()on everymessage_end, so the session file grows with each completed message.- 工具结果追加到上下文后,循环自动发起下一次请求,直到模型以
stop结束。After tool results join the context the loop issues the next request automatically, until the model ends withstop.
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/coding-agent/src/core/agent-session.tsL1968 | AgentSession.prompt() | 提示预处理流水线prompt preprocessing pipeline |
| packages/coding-agent/src/core/agent-session.tsL1162 | appendMessage | message_end 时持久化persists on message_end |
| packages/coding-agent/src/core/sdk.tsL439 | emitContext | transformContext → 扩展transformContext → extensions |
| packages/ai/src/types.tsL788 | AssistantMessageEvent | 12 种流事件the 12 stream event types |
核心类型Key types#
一句话结论TakeawayAgentSessionRuntime 持有 AgentSession,后者组合 Agent、SessionManager、ExtensionRunner 和 ModelRuntime。AgentSessionRuntime owns an AgentSession, which composes Agent, SessionManager, ExtensionRunner and ModelRuntime.
要点Key points
Agent的钩子都是公开字段(beforeToolCall、prepareRequest、finishTurn…),由上层直接赋值或包装。Agenthooks are public fields (beforeToolCall,prepareRequest,finishTurn, …) that the layer above assigns or wraps.ModelRuntime实现 pi-ai 的Models接口,并允许扩展通过registerProvider注册 provider。ModelRuntimeimplements pi-ai'sModelsinterface and lets extensions register providers viaregisterProvider.ExtensionRunner在AgentSession内部创建,bindCore()把会话动作暴露给扩展。ExtensionRunneris created insideAgentSession;bindCore()exposes session actions to extensions.
工作原理How it works
Agent维护 steering 与 follow-up 两个队列(PendingMessageQueue),转化为循环的getSteeringMessages/getFollowUpMessages。Agentkeeps two queues (PendingMessageQueue) for steering and follow-up and exposes them to the loop asgetSteeringMessages/getFollowUpMessages.AgentSessionRuntime.fork()/switchSession()先发出session_before_*扩展事件,再拆除当前会话并创建新会话。AgentSessionRuntime.fork()/switchSession()emitsession_before_*extension events, then tear down the current session and create a new one.
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/agent/src/agent.tsL188 | Agent | 队列、状态与订阅queues, state, subscription |
| packages/coding-agent/src/core/agent-session-runtime.tsL262 | fork() | 会话替换session replacement |
| packages/coding-agent/src/core/session-manager.tsL987 | SessionManager | JSONL 树存储JSONL tree store |
| packages/coding-agent/src/core/extensions/runner.tsL357 | ExtensionRunner | 事件分发event dispatch |
| packages/coding-agent/src/core/model-runtime.tsL172 | ModelRuntime | implements Modelsimplements Models |
仓库统计Repository stats#
一句话结论Takeaway约 177k 行源码、185k 行测试;coding-agent 一个包就占了 48% 的源码,测试代码量与源码相当。About 177k lines of source and 185k of tests; coding-agent alone is 48% of the source, and test code roughly matches source code.
统计自标签 v1.1.0(abe508e):只计 .ts(不含 .d.ts),排除 node_modules 与 dist;src = src/ 下,test = test*/ 下或 *.test.*。Counted at tag v1.1.0 (abe508e): .ts only (no .d.ts), node_modules and dist excluded; src = under src/, test = under test*/ or *.test.*.
| 包Package | 源文件src files | 源码行src LOC | 测试文件test files | 测试行test LOC | 全部 .tsall .ts |
|---|---|---|---|---|---|
| coding-agent | 298 | 85,816 | 331 | 71,137 | 735 |
| ai | 196 | 26,797 | 173 | 43,028 | 379 |
| durable | 67 | 20,404 | 90 | 29,837 | 159 |
| tui | 46 | 19,409 | 51 | 19,967 | 97 |
| chord | 29 | 8,817 | 30 | 9,726 | 59 |
| mcp | 18 | 3,243 | 6 | 1,520 | 25 |
| agent | 6 | 2,519 | 7 | 4,058 | 16 |
| env | 6 | 2,073 | 6 | 897 | 13 |
| server | 16 | 1,958 | 6 | 1,054 | 23 |
| codemode | 10 | 1,837 | 4 | 1,114 | 15 |
| evals | 5 | 1,446 | 7 | 829 | 23 |
| client | 8 | 1,135 | 4 | 799 | 13 |
| telemetry | 6 | 935 | 2 | 243 | 8 |
| protocol | 8 | 869 | 3 | 567 | 12 |
| 合计Total | 719 | 177,258 | 720 | 184,776 | 1,577 |