一个可扩展编码智能体内核的架构The architecture of an extensible coding-agent core
← → 翻页 · F 全屏 · O 目录 · T 明暗 · L 语言← → navigate · F fullscreen · O overview · T theme · L language
运行模式 → AgentSession → Agent 循环 → pi-ai 事件流。产品逻辑全部以钩子形式注入通用循环。Run mode → AgentSession → agent loop → pi-ai event stream. All product logic is injected into a generic loop as hooks.
pi-ai 只依赖 pi-telemetry;pi-tui、pi-mcp、pi-codemode、chord 零内部依赖。pi-ai depends only on pi-telemetry; pi-tui, pi-mcp, pi-codemode and chord have no internal deps.
AgentSessionRuntime 对话Modes only talk to AgentSessionRuntimeAgentSession 把策略挂到 Agent 钩子上AgentSession hangs policy on Agent hooksstreamFn = modelRuntime.streamSimple()streamFn = modelRuntime.streamSimple()pi-tuiOnly interactive mode uses pi-tuistopReason: length → 所有工具调用失败stopReason: length → every tool call failsfinishTurn 可返回 end / continuefinishTurn may return end / continue当前轮工具执行完成后、下一次 LLM 请求前注入。适合“停,换个方向”。Injected after the current turn's tools finish, before the next LLM request. For “stop, go another way”.
agent.steer() · getSteeringMessages()只在 Agent 本该停止时投递,触发外层循环。适合“做完之后再……”。Delivered only when the agent would stop, driving the outer loop. For “when you’re done, also…”.
agent.followUp() · getFollowUpMessages()每轮结束的决策钩子:end 立即结束;continue 在无新消息时再跑一轮仅含上下文的请求。End-of-turn decision hook: end stops now; continue runs one more context-only turn when nothing is queued.
AgentLoopConfig.finishTurn失败永远是结果而不是异常。并行模式:准备按顺序、执行并发、结果按原顺序发出;任何一个 sequential 工具会让整批串行。Failures are results, never throws. Parallel mode: prepare in order, execute concurrently, emit results in source order; one sequential tool serializes the batch.
input → before_agent_startExtensions intercept first: input → before_agent_startmessage_updateEvery delta becomes message_updatemessage_end 都写入 JSONLEvery message_end is written to JSONLstarttext_starttext_deltatext_endthinking_startthinking_deltathinking_endtoolcall_starttoolcall_deltatoolcall_enddoneerroragent_startturn_startmessage_startmessage_updatemessage_endtool_execution_starttool_execution_updatetool_execution_endturn_endagent_endprovider 增量在 agent 层变成 message_update;工具与轮次事件由循环自己发出。StreamFn 约定:不抛异常,失败以 error 事件编码。Provider deltas become message_update in the agent layer; tool and turn events are emitted by the loop itself. StreamFn contract: never throw, encode failures as error.
ModelRuntime 实现 pi-ai 的 Models 接口;ExtensionRunner 由 AgentSession 创建。ModelRuntime implements pi-ai's Models; ExtensionRunner is created by AgentSession.
id + parentIdEvery entry has id + parentIdleafId 指向当前位置leafId marks the current positioncompaction、context_edit11 entry types incl. compaction, context_edit~/.pi/agent/extensions、.pi/extensions、settings packages、-eSources: ~/.pi/agent/extensions, .pi/extensions, settings packages, -ebindCore() 之后注册才连到真实会话Registrations reach the real session after bindCore()bindExtensions() 提供UI is supplied by the mode via bindExtensions()registerToolregisterCommandregisterShortcutregisterFlagregisterProviderregisterMcpServerregisterMessageRendererregisterEntryRendererregisterToolRendererregisterVirtualModelsendMessagesendUserMessageappendEntryexecsetActiveToolssetSessionNamesetLabelon(event)input改写或吞掉输入rewrite or swallow inputcontext改写发给模型的消息rewrite messages sent to the modelbefore_provider_request改写请求负载rewrite the request payloadtool_call阻止工具调用block a tool calltool_result改写工具结果rewrite a tool resultsession_before_compact取消或替换压缩cancel or replace compactionRPC 模式:33 种 JSONL 命令,扩展 UI 请求以 extension_ui_request 代理给宿主。RPC mode: 33 JSONL command types; extension UI requests are proxied as extension_ui_request.
API 模块经 lazyApi() 在首次调用时才 import;失败编码为 error 事件,从不抛出。API modules are imported on first use via lazyApi(); failures become error events, never throws.
组件只实现 render(width) → string[];requestRender() 在 nextTick 合并,两帧间隔 ≥ 16 ms,再与 previousLines 做差分,在同步输出中只写变化的行。Components implement only render(width) → string[]; requestRender() coalesces on nextTick, frames are ≥ 16 ms apart, then a diff against previousLines writes only changed lines inside synchronized output.
实色 = 源码,浅色 = 测试。仅 .ts,不含 .d.ts。Solid = source, light = tests. .ts only, no .d.ts.
pi-agent-core 不知道“编码”;压缩、权限、工具清单全部通过 AgentLoopConfig 注入。pi-agent-core knows nothing about coding; compaction, permissions and tool loadout arrive through AgentLoopConfig.
流错误是 error 事件,工具错误是 isError 结果——循环从不需要 try/catch 逃逸。Stream errors are error events and tool errors are isError results — the loop never unwinds.
分支、压缩、上下文编辑都是新条目,历史永不改写。Branches, compactions and context edits are all new entries; history is never rewritten.
42 个 provider 复用 10 种对话 API(KnownApi),并且按需懒加载。42 providers reuse 10 chat APIs (KnownApi), loaded lazily.
41 种事件 + register* API,用 jiti 直接加载 TypeScript。41 events plus the register* API, TypeScript loaded directly with jiti.