v1.1.0Pi v1.1.0 源码分析Analysis of Pi v1.1.0 · 2026-10-07

coding-agentcoding-agent

编码智能体 CLI:工具、会话树、压缩、扩展与运行模式Coding agent CLI with read, bash, edit, write tools and session management

pi-coding-agentInfrapi-agent-core

← → 翻页 · F 全屏 · O 目录 · T 明暗 · L 语言← → navigate · F fullscreen · O overview · T theme · L language

图解 Pi Agent · Pi v1.1.0Pi Agent, Illustrated · Pi v1.1.001
01 · CLI 启动流程01 · CLI start-upRun modes

CLI 启动流程CLI start-up

pi startup (cli.ts → main.ts)setupCli()进程标题 · 环境变量process title · env flagsconfigureHttpDispatcher()main(args)内置扩展 + 自定义工厂built-in + custom factories--offline → PI_OFFLINE一次性命令one-shot commandsauth · package · config · mcp处理后直接退出handled → exitparseArgs(args)诊断错误 → exit 1diagnostics → exit 1--version · --export → 退出--version · --export → exitresolveAppMode()rpc · json · print · interactive非交互 → 接管 stdoutnon-TTY → takeOverStdout()runMigrations(cwd)auth · 会话 · 工具 · 键位auth · sessions · tools · keys弃用警告(交互模式显示)deprecation warningsSettingsManager全局 + 项目设置global + project settings首次运行设置(仅 TTY)first-time setup (TTY)createSessionManager()--session · --resume · --fork--no-session → 内存--no-session → in memoryProjectTrustStore按 cwd 记录项目信任project trust per cwd决定是否加载 .pi/ 资源gates project .pi/ resourcescreateAgentSessionRuntime()传入 createRuntime 工厂takes a createRuntime factory之后的会话替换也用它reused for every replacementcreateAgentSessionServices()ModelRuntime · ResourceLoader扩展注册的 provider 入表extension providers registeredcreateAgentSession()经 …FromServices() 进入 sdk.tssdk.ts, via …FromServices()模型 · thinking · 工具model · thinking · toolsprepareInitialMessage()管道 stdin + @文件参数piped stdin + @file args图片自动缩放images auto-resizedinitTheme() · diagnostics运行时错误 → exit 1runtime errors → exit 1非交互且无模型 → exit 1no model (non-TTY) → exit 1runRpcMode(runtime)InteractiveMode.run()runPrintMode(runtime)createRuntime()按模式分派DISPATCH BY MODErpc 模式不读管道 stdin(stdin 用于 JSONL 命令);--help / --list-models 在运行时创建后退出rpc mode never reads piped stdin (stdin carries JSONL commands); --help / --list-models exit after the runtime exists1234567891011121314启动顺序startup order1步骤stepcoremodes门控 / 退出gate / exit一次性one-shot

resolveAppMode() 同时看参数和 stdin/stdout 是否为 TTY:-p、或 stdin / stdout 任一不是 TTY 时走 print,--mode json / --mode rpc 显式指定。resolveAppMode() looks at both args and whether stdin/stdout are TTYs: -p, or a non-TTY stdin or stdout, means print; --mode json / --mode rpc are explicit.

图解 Pi Agent · Pi v1.1.0Pi Agent, Illustrated · Pi v1.1.002
02 · AgentSession 如何装配 Agent02 · How AgentSession wires the Agentpi-coding-agent

AgentSession 如何装配 AgentHow AgentSession wires the Agent

  • 事件先交给扩展、再交给 UI 监听器(_handleAgentEvent),所以扩展总能先看到并改写。Events reach extensions before UI listeners (_handleAgentEvent), so extensions always see and rewrite first.
  • 一次运行结束后由 _handlePostAgentRun() 决定是否再跑一次:可重试错误 → 退避重试;超出上下文或超过阈值 → 压缩;还有排队消息 → continue()。After a run, _handlePostAgentRun() decides whether to go again: retryable error → back off and retry; context overflow or over threshold → compact; queued messages → continue().
How AgentSession wires the AgentAgent(pi-agent-core)运行之后:_runAgentPrompt() 的外层循环After a run: the outer loop in _runAgentPrompt()sdk.tsstreamFnModelRuntime.streamSimple(model, ctx, opts)会话请求顺带启动 CacheWarmersession requests also start the CacheWarmerModelRuntimesdk.tsconvertToLlmmessages.ts convertToLlm()blockImages 开启时再过滤一次图片filters images again when blockImages is onmessages.tssdk.tstransformContextExtensionRunner.emitContext(messages)扩展的 "context" 事件可改写上下文the extension "context" event can rewrite contextExtensionRunnerAgentSessionprepareRequest请求投影 · 虚拟模型路由request projection · virtual-model routingresolveModel() 只影响本次请求resolveModel() affects this request onlyModelRuntimeAgentSessionbeforeToolCall扩展 "tool_call" 事件extension "tool_call" event可阻止执行;扩展出错也会阻止may block; an extension error blocks tooExtensionRunnerAgentSessionafterToolCall扩展 "tool_result" 事件 + 图片规范化extension "tool_result" + image normalization可改写 content / detailsmay rewrite content / detailsExtensionRunnerAgentSessionfinishTurn"turn_end" 边界:扩展可追加条目"turn_end" boundary: extensions may appendemitBoundary() 先预演再写入会话emitBoundary() previews, then persistsExtensionRunnerAgentSessionprepareNextTurn超阈值先压缩 · 重建 system 提示与工具threshold compaction · rebuild prompt + tools_compactBeforeNextAssistantResponse()SessionManagerAgentSessionsubscribe()_handleAgentEvent:先扩展,后监听器_handleAgentEvent: extensions, then listenersmessage_end → SessionManager.appendMessage()SessionManageragent.prompt()或 agent.continue()or agent.continue()_handlePostAgentRun()检查最后一条 assistantinspect the last assistant可重试错误?retryable error?_prepareRetry() → 退避_prepareRetry() → backoff_checkCompaction()overflow / threshold还有排队消息?queued messages?hasQueuedMessages()agent_settledagent_before_settle 之后after agent_before_settle安装者INSTALLED BYAgentSession 的实现AGENTSESSION'S IMPLEMENTATION协作者COLLABORATOR是 → continue()yes → continue()压缩后 / 有排队 → 再跑一次compacted / queued → run againAgentSession 安装的钩子hook installed by AgentSessionsdk.ts 在 new Agent() 时传入passed by sdk.ts to new Agent()循环回到 continue()loops back to continue()pi-agent-core扩展extensions
图解 Pi Agent · Pi v1.1.0Pi Agent, Illustrated · Pi v1.1.003
03 · AgentSessionRuntime:替换会话03 · AgentSessionRuntime: replacing the sessionpi-coding-agent

AgentSessionRuntime:替换会话AgentSessionRuntime: replacing the session

AgentSessionRuntime: replacing the session«class»AgentSessionRuntime−_session: AgentSession−_services: AgentSessionServices−createRuntime: Factory−rebindSession?(session)−beforeSessionInvalidate?()+switchSession(path)+newSession({ parentSession })+fork(entryId, { position })+importFromJsonl(path)+dispose()«cwd-bound»AgentSessionServices+cwd · agentDir+modelRuntime: ModelRuntime+settingsManager: SettingsManager+resourceLoader: ResourceLoader+diagnostics[]emitBeforeSwitch / emitBeforeForksession_before_switch · session_before_fork打开 / 新建 SessionManageropen / create the SessionManageropen() · create() · createBranchedSession()teardownCurrent(reason)abort() → session_shutdown → dispose()createRuntime({ cwd, sessionManager })新的 services + AgentSessionfresh services + AgentSessionapply(result)替换 session · services · diagnosticsswap session · services · diagnosticsfinishSessionReplacement()rebindSession() → withSession(ctx)cancel: true→ { cancelled: true }session_start { reason }新会话的扩展收到启动事件the new session's extensions startbeforeSessionInvalidate()同步卸下扩展的 TUI 组件detach extension TUI widgets (sync)createAgentSessionServices()+ createAgentSessionFromServices()switchSession()newSession()fork()importFromJsonl()dispose()扩展取消ext cancelssession_start.reason→ resume→ new→ fork→ resume→ quit (shutdown)启动与 /reload 的 reason 是 startup / reloadstartup and /reload use reason startup / reload123456

session_before_switch / session_before_fork 返回 { cancel: true } 时,整个替换中止,方法返回 { cancelled: true }。If session_before_switch / session_before_fork returns { cancel: true }, the replacement stops and the method returns { cancelled: true }.

图解 Pi Agent · Pi v1.1.0Pi Agent, Illustrated · Pi v1.1.004
04 · 内置工具04 · Built-in toolspi-coding-agent

内置工具Built-in tools

The 8 built-in tools一个工具如何接入How a tool is plugged inreadpath · offset? · limit?文本截断到 2000 行 / 50KBtext capped at 2000 lines / 50KBbashcommand · timeout?保留尾部输出,完整输出写临时文件keeps the tail; full output to a temp fileeditpath · edits[{ oldText, newText }]每个 oldText 唯一且不重叠each oldText unique, non-overlappingwritepath · content递归创建目录后整体覆盖mkdir -p, then overwritegreppattern · path? · glob? …ripgrep · 默认 100 条匹配ripgrep · 100 matches by defaultfindpattern · path? · limit?fd · 默认 1000 个结果fd · 1000 results by defaultlspath? · limit?默认 500 个条目500 entries by defaultpowershellcommand · timeout?Windows 上 bash 的替代the Windows alternative to bashreadbasheditwritecreateXToolDefinition(cwd, opts)ToolDefinition:schema + executeToolDefinition: schema + executewrapToolDefinition(def)→ AgentTool(pi-agent-core)→ AgentTool (pi-agent-core)AgentSession 工具表AgentSession tool table内置 + 扩展 registerTool()built-in + extension registerTool()agent.state.tools当前激活的子集the active subsetReadOperationsBashOperationsEditOperations · WriteOperationsGrep / Find / LsOperations图片作为附件发送images sent as attachments超时 / abort → 杀进程树timeout / abort → kill process tree精确匹配失败 → 模糊匹配 · 返回 diffexact fails → fuzzy match · returns diff与 edit 共用按文件的变更队列shares the per-file mutation queue遵守 .gitignore · 每行 ≤ 500 字符respects .gitignore · lines ≤ 500 chars遵守 .gitignorerespects .gitignore含点文件 · 目录带 /includes dotfiles · dirs end in /与 bash 共用 shell 执行器shares the bash shell executor默认启用(DEFAULT_TOOL_NAMES):ACTIVE BY DEFAULT (DEFAULT_TOOL_NAMES): 只读集合:read · grep · find · lsread-only set: read · grep · find · ls可替换的 *Operations(默认 = 本地文件系统 / shell)Swappable *Operations (default = local filesystem / shell)readFile · access · detectImageMimeTypeexec(command, cwd, { onData, signal, timeout })readFile · writeFile · mkdir可换成远程 / 沙箱实现swap in remote / sandboxed backendswithFileMutationQueue(path):同一文件(realpath)上的 edit / write 串行,不同文件仍可并行withFileMutationQueue(path): edits / writes to the same file (by realpath) run serially; different files still run in parallel默认工具default tools可选工具optional toolsWindows装配顺序assembly order

read 从头截断(truncateHead),bash 从尾截断(truncateTail)——命令最后的输出通常最重要。read truncates from the head (truncateHead), bash from the tail (truncateTail) — the end of a command's output usually matters most.

图解 Pi Agent · Pi v1.1.0Pi Agent, Illustrated · Pi v1.1.005
05 · 会话文件:JSONL 格式05 · The session file: JSONL formatpi-coding-agent

会话文件:JSONL 格式The session file: JSONL format

  • 文件按 cwd 分目录存放在 ~/.pi/agent/sessions/ 下,文件名带时间戳与 UUIDv7。Files live under ~/.pi/agent/sessions/, one directory per cwd, named with a timestamp and a UUIDv7.
  • 写入是惰性的:出现第一条 user 或 assistant 消息之前不落盘,首次写入用 wx 标志,避免并发覆盖。Writes are lazy: nothing hits disk before the first user or assistant message, and the first write uses the wx flag to avoid clobbering.
The session file: JSONL anatomy, write & read paths条目类型Entry types11 种 · 都有 id / parentId / timestamp11 kinds · all carry id / parentId / timestampmessagecustom_messagemodel_changethinking_level_changesession_infolabelcompactionbranch_summarycontext_editusagecustomappendMessage() …append*() 方法之一one of the append*() methods_appendEntry(e)入内存索引 · leafId = e.idindex in memory · leafId = e.id还没有对话?no conversation yet?只有设置条目 → 不建文件setup entries only → no file首次 user / assistantfirst user / assistantopenSync("wx") 写出全部缓冲openSync("wx") flushes the bufferappendFileSync()之后每条追加一行one line per entry afterwardsloadEntriesFromFile()逐行解析,跳过坏行line by line, skips bad linesmigrate → v3v1→v2 补 id · v2→v3 hookMessage→customv1→v2 ids · v2→v3 hookMessage→custom_rewriteFile()迁移后整体重写rewrite if migratedbuildSessionProjection(leaf)根→leaf · context_edit · 最新压缩root→leaf · context_edit · newest compactionSessionContextmessages · model · thinkingLevel位置:每个 cwd 一个目录LOCATION: one directory per cwd~/.pi/agent/sessions/--home-me-proj--/2026-10-07T09-12-33-123Z_<uuidv7>.jsonl内容:第 1 行是头,其余每行一个条目CONTENT: line 1 is the header, one entry per line after{"type":"session","version":3,"id":"…","cwd":"/home/me/proj"}{"type":"model_change","id":"a1","parentId":null,…}{"type":"thinking_level_change","id":"b2","parentId":"a1"}{"type":"message","id":"c3","parentId":"b2","message":{role:"user"}}{"type":"message","id":"d4","parentId":"c3",…assistant}{"type":"compaction","id":"e5","firstKeptEntryId":"c3",…}{"type":"message","id":"f6","parentId":"c3",…} ← 分支{"type":"message","id":"f6","parentId":"c3",…} ← branch对话conversation状态state上下文改写context rewrites记账bookkeepingCustomMessage / bashExecution 等宿主消息不直接作为 message 写入;Host messages (custom, bashExecution) are not written as plain message entries;压缩与分支摘要必须是顶层条目。compaction and branch summaries must be top-level entries.写入路径WRITE PATH读取路径READ PATH分支不是复制:fork / navigateTree 只移动 leafId,或用 createBranchedSession() 把根到 leaf 的路径写进新文件。Branching copies nothing: fork / navigateTree just moves leafId, or createBranchedSession() writes the root → leaf path into a new file.SessionManager.inMemory() 用于 --no-session、--help、测试:同一套 API,只是从不落盘。SessionManager.inMemory() backs --no-session, --help and tests: the same API, never written to disk.数据流data flow写入write加载与迁移load & migrate投影成上下文project into context
图解 Pi Agent · Pi v1.1.0Pi Agent, Illustrated · Pi v1.1.006
06 · 扩展 API:能力面与事件06 · The extension API: capabilities and eventsExtensions

扩展 API:能力面与事件The extension API: capabilities and events

  • 每个处理器的第二个参数是 ctx:ExtensionContext 有 18 个成员(cwd、模型、会话、ui …),命令处理器拿到的 ExtensionCommandContext 还能新建 / 分叉 / 切换会话。Every handler's second argument is ctx: ExtensionContext has 18 members (cwd, model, session, ui …); command handlers get ExtensionCommandContext, which can also create / fork / switch sessions.
  • ctx.ui 有 28 个成员:对话框、通知、状态栏、widget、自定义组件;在 RPC 模式下它们变成 extension_ui_request。ctx.ui has 28 members: dialogs, notifications, status, widgets, custom components; in RPC mode they become extension_ui_requests.
The extension API: capabilities and the 41 eventspi: ExtensionAPI32 个方法(含 on)32 methods incl. on()处理器的第二个参数 ctxctx, every handler's 2nd argumentpi.on(event, handler)41 种事件 · 18 种可返回结果41 events · 18 may return a resultregisterCommand()registerEntryRenderer()registerFlag()registerMarkdownTransformer()registerMcpServer()registerMessageRenderer()registerProvider()registerShortcut()registerTool()registerToolRenderer()registerVirtualModel()unregisterMcpServer()unregisterProvider()unregisterVirtualModel()appendEntry()exec()sendMessage()sendUserMessage()setActiveTools()setLabel()setModel()setSessionName()setThinkingLevel()getActiveTools()getAllTools()getCommands()getFlag()getMcpServers()getSessionName()getSettings()getThinkingLevel()session_before_compactsession_before_forksession_before_switchsession_before_treesession_compactsession_compact_failedsession_info_changedsession_shutdownsession_startsession_treeproject_trustresources_discovermcp_servers_changeinputbefore_agent_startagent_startturn_startturn_endagent_endagent_before_settleagent_settleduser_bashmessage_startmessage_updatemessage_endtool_calltool_execution_starttool_execution_updatetool_execution_endtool_resultcontextcontext_with_systembefore_provider_requestbefore_provider_headersafter_provider_responseprovider_stream_eventcache_warming_decisionmodel_selectthinking_level_selectui_prompt_startui_prompt_endinputtool_calltool_resultcontextsession_before_*turn_endexport default (pi) => { … }注册register注销unregister行动act读取readExtensionContext18 个成员18 membersui · cwd · sessionManager · model · signal · compact …ExtensionCommandContext7 个成员7 membersnewSession · fork · navigateTree · switchSession · reload …ctx.ui28 个成员28 membersselect · confirm · input · notify · setWidget · custom …会话session运行与轮次run & turn消息messages工具tools上下文与 providercontext & provider模型与界面model & UI返回值能做什么(实心 = 可返回结果)What a returned result can do (solid = may return a result)→ { action: "transform" | "handled" }→ { block: true, reason }→ 改写 content / details→ rewrite content / details→ { messages } 替换本次上下文→ { messages } replaces this context→ { cancel: true }→ 边界条目:在轮次之间写入会话→ boundary entries written between turns注册能力register行动 / 会话act / session运行run消息 · providermessages · providerctx · UI
图解 Pi Agent · Pi v1.1.0Pi Agent, Illustrated · Pi v1.1.007
07 · RPC 协议07 · The RPC protocolRun modes

RPC 协议The RPC protocol

  • prompt 不等运行结束:预检通过就回响应(带 disposition),之后的一切以事件到达。prompt does not wait for the run: it responds once preflight passes (with a disposition), and everything after arrives as events.
  • 需要回答的扩展 UI(select / confirm / input / editor)发出 extension_ui_request,宿主用同一个 id 回 extension_ui_response;通知类请求不需要回答。Extension UI that needs an answer (select / confirm / input / editor) emits an extension_ui_request; the host replies with an extension_ui_response carrying the same id. Notification-style requests need no answer.
RPC mode: a JSONL protocol over stdin/stdout (33 commands)RpcCommand33 种 · 按 rpc-types.ts 中的分组33 types · grouped as in rpc-types.ts宿主进程host processIDE · 编排器 · RpcClientIDE · orchestrator · RpcClientpi --mode rpc或 rpc-entry.tsor rpc-entry.tsrunRpcMode(runtime)handleCommand(cmd) · switchAgentSessionRuntimesession.prompt() · fork() …stdinstdoutstdoutstdoutstdinpromptsteerfollow_upabortclear_queuenew_sessionget_stateset_modelcycle_modelget_available_modelsset_thinking_levelcycle_thinking_levelget_available_thinking_levelsset_steering_modeset_follow_up_modecompactset_auto_compactionset_auto_retryabort_retrybashabort_bashget_session_statsexport_htmlswitch_sessionforkcloneget_fork_messagesget_entriesget_treeget_last_assistant_textset_session_nameget_messagesget_commands命令:{ id?, type, … }commands: { id?, type, … }响应:{ type:"response", id, success, data | error }responses: { type:"response", id, success, data | error }事件:AgentSessionEvent → toJsonEvent()events: AgentSessionEvent → toJsonEvent()扩展 UI 请求:extension_ui_request { id, method }UI request: extension_ui_request { id, method }回答:extension_ui_response { id, value | … }answer: extension_ui_response { id, value | … }jsonl.ts:只按 \n 切分(JSON 字符串里可以有 U+2028/2029),去掉行尾 \r;不用 readline。jsonl.ts: split on \n only (JSON strings may contain U+2028/2029), strip a trailing \r; no readline.事件输出受 stdout 背压控制:Agent 监听器会等待 drain。Event output honours stdout backpressure: an Agent listener awaits drain.PromptingStateModelThinkingQueue modesCompactionRetryBashSessionMessagesCommandsprompt 先完成预检再回响应(disposition),之后的一切都以事件到达prompt replies after preflight (disposition); everything after arrives as eventsselect / confirm / input / editor 等待响应;notify / setStatus / setWidget / setTitle 只发不收select / confirm / input / editor await a response; notify / setStatus / setWidget / setTitle are fire-and-forget1122334455stdin → pipi → stdout会话session模型model扩展 / bashextensions / bash
图解 Pi Agent · Pi v1.1.0Pi Agent, Illustrated · Pi v1.1.008
08 · 设置、资源与 system prompt08 · Settings, resources and the system promptpi-coding-agent

设置、资源与 system promptSettings, resources and the system prompt

Configuration: settings merge, ResourceLoader.reload(), system prompt sectionsSettingsManager两层 JSON,项目层受信任门控two JSON layers; the project layer is trust-gatedDefaultResourceLoader.reload()启动和 /reload 时运行runs at startup and on /reload资源从哪里来Where resources come frombuildSystemPromptSections()有序、可单独替换的分段ordered, independently replaceable全局global~/.pi/agent/settings.jsonProjectTrustStore门控项目层gates the project layer项目project<cwd>/.pi/settings.jsondeepMergeSettings()项目覆盖全局 · 对象逐键合并project wins · objects merge per keyresolveProjectTrust先加载处理 project_trust 的扩展project_trust extensions firstsettings.reload()按信任状态重读re-read for trust stateresolve()packageManagerCLI paths-e · --skill · --theme …loadFinalExtensionSetjiti 加载 · 工厂函数jiti import · factories其余资源other resourcesskills · prompts · themesAGENTS.override.mdAGENTS.mdAGENTS.MDCLAUDE.mdCLAUDE.MDpreamble<tools><rules><docs><addendum><project_context><skills><cwd><custom…>~/.pi/agent/extensions/ skills/ prompts/ themes/settings.json auth.json models.jsonSYSTEM.md APPEND_SYSTEM.md AGENTS.md<cwd>/.pi/ ← 仅限受信任项目<cwd>/.pi/ ← trusted projects onlyextensions/ skills/ prompts/ themes/settings.json SYSTEM.md APPEND_SYSTEM.md上下文文件:全局 agentDir + cwd 及每一级祖先目录,每处取第一个存在的Context files: global agentDir + cwd and every ancestor; first match per directorySYSTEM.md / APPEND_SYSTEM.md:项目优先于全局SYSTEM.md / APPEND_SYSTEM.md: project beats globalSYSTEM.md 存在时整段替换,并去掉 tools/rules/docsSYSTEM.md replaces it and drops tools/rules/docs可见工具的一行说明one-line snippet per visible tool工具准则 + 扩展 promptGuidelinestool guidelines + extension promptGuidelinespi 自身文档的位置where pi's own docs liveAPPEND_SYSTEM.mdAGENTS.md / CLAUDE.md …技能清单(需 read 或 bash)skill index (needs read or bash)工作目录working directory扩展通过 sections 追加extensions add via sections123456settings信任门trust gate加载流程load pipeline资源resourcessystem prompt

deepMergeSettings(global, project):项目值覆盖全局值,嵌套对象逐键合并。deepMergeSettings(global, project): project values win, nested objects merge key by key.

图解 Pi Agent · Pi v1.1.0Pi Agent, Illustrated · Pi v1.1.009
扩展点Extension pointspi-coding-agent

coding-agent 的扩展点Where to plug into coding-agent

1
pi.registerTool()pi.registerTool()

增加模型可调用的工具,与内置工具并列。Add tools the model can call, alongside the built-ins.

2
pi.on(event, handler)pi.on(event, handler)

41 种事件,18 种可返回结果来改写或拦截。41 events; 18 can return a result to rewrite or intercept.

3
pi.registerCommand() · registerShortcut()pi.registerCommand() · registerShortcut()

斜杠命令与快捷键。Slash commands and keyboard shortcuts.

4
pi.registerProvider() · registerVirtualModel()pi.registerProvider() · registerVirtualModel()

接入新的模型 provider 或虚拟模型路由。Add model providers or virtual-model routing.

5
ctx.ui.custom() · setWidget()ctx.ui.custom() · setWidget()

在 TUI 中放入自定义组件。Put custom components into the TUI.

图解 Pi Agent · Pi v1.1.0Pi Agent, Illustrated · Pi v1.1.010
←
1 / 10