图解 Pi AgentPi Agent, Illustratedv1.1.0
包Packages· coding-agent
演示Slides
pi-coding-agent已完成Donepackages/coding-agent · v1.1.0

coding-agent@earendil-works/pi-coding-agent

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

1.1.0
版本version
298
源文件src files
85,816
源码行src LOC
314
测试文件test files
2,593
测试用例test cases
4
导出路径export paths
依赖Depends onchordagent-corepi-aicodemodemcptui被依赖Used by—devclientprotocolserver

这个包是什么What this package ispi-coding-agent 是产品本身:pi 命令、SDK 与 RPC 服务器都从这里出来。它把 pi-agent-core 的通用 Agent 装配成一个编码智能体——加上会话树(JSONL)、内置工具、扩展系统、设置与资源加载,以及 interactive / print / json / rpc 四种运行模式。pi-coding-agent is the product: the pi command, the SDK and the RPC server all come from here. It turns the generic Agent from pi-agent-core into a coding agent — adding the session tree (JSONL), built-in tools, the extension system, settings and resource loading, and four run modes: interactive, print, json and rpc.

位于最上层:依赖 pi-agent-core、pi-ai、pi-tui,以及 pi-mcp、pi-codemode、chord。这里的核心类是 AgentSession(一次会话)和 AgentSessionRuntime(可替换会话的宿主)。The top layer: depends on pi-agent-core, pi-ai, pi-tui, plus pi-mcp, pi-codemode and chord. The central classes are AgentSession (one session) and AgentSessionRuntime (the host that can swap sessions).

01pi-coding-agent

模块结构Module structure#

一句话结论Takeaway四个入口共用一个内核:cli.ts(pi 命令)与 rpc-entry.ts 都进入 main.ts;index.ts 是 SDK 入口。真正的逻辑在 core/,三种 UI 形态在 modes/。Four entry points share one core: cli.ts (the pi command) and rpc-entry.ts both enter main.ts; index.ts is the SDK entry. The real logic lives in core/; the three UI shapes live in modes/.

四个入口、core/ 的主要模块(标签为行数)与依赖Four entry points, the main core/ modules (tags = lines) and dependencies
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
pi-coding-agent modulessrc/core/94 个文件 · 35,147 行94 files · 35,147 linessrc/modes/23,891 行23,891 linescli.tsbin: pi → setupCli()rpc-entry.tsmain(["--mode","rpc",…])main.ts参数 → 会话 → 模式args → session → mode999 行999 linesindex.tsSDK 入口SDK entry point43 条 export 语句43 export statementsagent-session.ts提示 · 队列 · 压缩 · 重试prompt · queues · compact · retry4,398 行4,398 linesagent-session-runtime.ts替换会话:new · switch · forkreplace: new · switch · fork447 行447 linessdk.tscreateAgentSession():组装 AgentcreateAgentSession(): wires Agent487 行487 linessession-manager.tsJSONL 会话树 · 11 种条目JSONL session tree · 11 entry types2,013 行2,013 linescompaction/压缩与分支摘要compaction · branch summaries1,671 行1,671 linestools/8 个内置工具 · 截断8 built-in tools · truncation4,619 行4,619 linesextensions/jiti 加载 · runner · 41 种事件jiti loader · runner · 41 events5,005 行5,005 linesmodel-runtime.tsprovider · 认证 · 模型路由providers · auth · routing1,034 行1,034 linessettings-manager.ts全局 + 项目 settings.jsonglobal + project settings.json1,556 行1,556 linesresource-loader.ts扩展 · 技能 · 提示模板extensions · skills · prompts1,283 行1,283 linespackage-manager.tsnpm / git 包 · pi 清单npm / git packages · pi manifest2,760 行2,760 linessystem-prompt.ts分段构建 system 提示sectioned system prompt229 行229 linesinteractive/InteractiveMode · TUI21,848 行21,848 linesprint-mode.tstext · json 事件流text · json event stream169 行169 linesrpc/JSONL stdin/stdoutJSONL over stdin/stdout1,797 行1,797 linessrc/extensions/内置扩展 · 7,454 行built-in · 7,454 linessrc/experimental/实验功能 · 9,950 行experimental · 9,950 lineschordpi-agent-corepi-aipi-codemodepi-mcppi-tui入口ENTRY POINTS驱动drive内部依赖Internal deps+ 17 个外部依赖+ 17 external deps主路径main pathimport / 调用import / callcoremodes扩展extensions其他other

要点Key points

  • core/agent-session.ts 是 core/ 里最大的文件(interactive 模式的 interactive-mode.ts 更大):它持有 Agent、SessionManager、ExtensionRunner 与模型运行时,并负责重试、压缩和排队消息。core/agent-session.ts is the largest file in core/ (only interactive mode's interactive-mode.ts is bigger): it owns the Agent, the SessionManager, the ExtensionRunner and the model runtime, and handles retry, compaction and queued messages.
  • rpc-entry.ts 只做一件事:调用 main(["--mode", "rpc", …]),并通过 ./rpc-entry 导出路径对外提供。rpc-entry.ts does one thing: call main(["--mode", "rpc", …]); it is published as the ./rpc-entry export path.
  • src/extensions/ 里是随包附带的内置扩展(MCP、codemode、tool-search 等),走的是和用户扩展相同的 API。src/extensions/ holds the bundled built-in extensions (MCP, codemode, tool-search …); they use the same API as user extensions.

工作原理How it works

  1. pi → setupCli() → main(argv):解析参数、决定模式、建会话。pi → setupCli() → main(argv): parse args, pick a mode, build the session.
  2. SDK 用户直接调用 createAgentSession() 或 createAgentSessionRuntime(),跳过 CLI。SDK users call createAgentSession() or createAgentSessionRuntime() directly and skip the CLI.
  3. 所有模式拿到的都是同一个 AgentSessionRuntime,区别只在输入输出方式。Every mode receives the same AgentSessionRuntime; they differ only in how input and output flow.

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/cli/setup.tsL4setupCli()bin 入口的准备工作bin-entry setup
packages/coding-agent/src/main.tsL573main()CLI 主流程the CLI main flow
packages/coding-agent/src/rpc-entry.tsL13main(["--mode","rpc"])RPC 入口RPC entry
packages/coding-agent/src/index.tsL259export …SDK 入口SDK entry
packages/coding-agent/src/core/agent-session.tsL378AgentSession一次会话的全部状态all state of one session
02pi-coding-agent

公共 APIPublic API#

一句话结论Takeaway一个命令(pi → dist/bundle/cli.js)加 4 个导入路径。SDK 根入口从 40 个模块重新导出 154 个值和 304 个类型;最常用的是 createAgentSession、createAgentSessionRuntime、SessionManager、SettingsManager、createCodingTools 和扩展类型。One command (pi → dist/bundle/cli.js) plus 4 import paths. The SDK root re-exports 154 values and 304 types from 40 modules; the most used are createAgentSession, createAgentSessionRuntime, SessionManager, SettingsManager, createCodingTools and the extension types.

导入路径Import path目标Target说明Notes
@earendil-works/pi-coding-agent./dist/index.jsSDK:createAgentSession、AgentSessionRuntime、SessionManager、工具、扩展类型、主题与组件SDK: createAgentSession, AgentSessionRuntime, SessionManager, tools, extension types, theme and components
@earendil-works/pi-coding-agent/rpc-entry./dist/bundle/rpc-entry.js以 RPC 模式启动(等同 pi --mode rpc)start in RPC mode (same as pi --mode rpc)
@earendil-works/pi-coding-agent/client./src/client/index.ts源码入口:客户端(仓库内使用)source entry: client (used inside the repo)
@earendil-works/pi-coding-agent/experimental/plugin./src/experimental/plugin.ts源码入口:实验性插件 APIsource entry: experimental plugin API

package.json · exportsL14

常用导出Key exports

根入口 index.ts 的全部导出(按来源模块)Every root index.ts export, by source module

展开全部 40 个来源模块Show all 40 source modules154 values304 types
来源模块Source module值导出Value exports类型导出Type exports
packages/coding-agent/src/cli/args.tsparseArgsArgs
packages/coding-agent/src/config.tsCONFIG_DIR_NAME getAgentDir getDocsPath getExamplesPath getPackageDir getReadmePath VERSION—
packages/coding-agent/src/core/agent-session.tsAgentSession parseSkillBlockAgentSessionConfig AgentSessionEvent AgentSessionEventListener ModelCycleResult ParsedSkillBlock PromptOptions SessionStats
packages/coding-agent/src/core/auth-storage.tsreadStoredCredential—
packages/coding-agent/src/core/cache-warmer.ts—CacheWarmingDecision CacheWarmingStatus
packages/coding-agent/src/core/compaction/index.tscalculateContextTokens collectEntriesForBranchSummary compact DEFAULT_COMPACTION_SETTINGS estimateTokens findCutPoint findTurnStartIndex generateBranchSummary generateSummary generateSummaryWithUsage getLastAssistantUsage prepareBranchEntries serializeConversation shouldCompactBranchPreparation BranchSummaryResult CollectEntriesResult CompactionResult CutPointResult FileOperations GenerateBranchSummaryOptions
packages/coding-agent/src/core/event-bus.tscreateEventBusEventBus EventBusController
packages/coding-agent/src/core/extensions/index.tscreateExtensionRuntime defineTool discoverAndLoadExtensions ExtensionRunner isBashToolResult isEditToolResult isFindToolResult isGrepToolResult isLsToolResult isPowerShellToolResult isReadToolResult isToolCallEventType isWriteToolResult wrapRegisteredTool +1AfterProviderResponseEvent AgentActivityOutcome AgentBeforeSettleEvent AgentBeforeSettleEventResult AgentEndEvent AgentSettledEvent AgentStartEvent AgentToolResult AgentToolUpdateCallback AppKeybinding +133
packages/coding-agent/src/core/footer-data-provider.ts—ReadonlyFooterDataProvider
packages/coding-agent/src/core/mcp-servers.ts—RegisteredMcpServer
packages/coding-agent/src/core/messages.tsconvertToLlm—
packages/coding-agent/src/core/model-registry.tsModelRegistry—
packages/coding-agent/src/core/model-resolver.tsresolveCliModel resolveModelScopeWithDiagnosticsModelScopeDiagnostic ResolveCliModelResult ResolveModelScopeResult ScopedModel
packages/coding-agent/src/core/model-runtime.tsCredentialSynchronizationError ModelRuntimeCreateModelRuntimeOptions CredentialSynchronizationOperation ModelRuntimeAuthOverrides
packages/coding-agent/src/core/package-manager.tsDefaultPackageManagerPackageManager PathMetadata ProgressCallback ProgressEvent ResolvedPaths ResolvedResource
packages/coding-agent/src/core/resource-loader.tsDefaultResourceLoader loadProjectContextFilesResourceCollision ResourceDiagnostic ResourceLoader
packages/coding-agent/src/core/sdk.tsAgentSessionRuntime createAgentSessionFromServices createAgentSessionRuntime createAgentSessionServices createBashTool createEditTool createFindTool createGrepTool createLsTool createPowerShellTool createReadOnlyTools createReadTool createWriteToolAgentSessionRuntimeDiagnostic AgentSessionServices CreateAgentSessionFromServicesOptions CreateAgentSessionOptions CreateAgentSessionResult CreateAgentSessionRuntimeFactory CreateAgentSessionRuntimeResult CreateAgentSessionServicesOptions PromptTemplate
packages/coding-agent/src/core/session-manager.tsbuildContextEntries buildSessionContext buildSessionProjection CURRENT_SESSION_VERSION getLatestCompactionEntry migrateSessionEntries parseSessionEntries SessionManager sessionEntryToContextMessagesBranchSummaryEntry CompactionEntry ContextEditableContent ContextEditEntry CustomEntry CustomMessageEntry FileEntry ModelChangeEntry NewSessionOptions ProjectedSessionEntry +10
packages/coding-agent/src/core/settings-manager.tsSettingsManagerCacheWarmingMode CompactionModelOverride CompactionSettings DefaultProjectTrust FullscreenExitOutput ImageSettings PackageSource QuietStartup RetrySettings SettingsManagerCreateOptions +1
packages/coding-agent/src/core/skills.tsformatSkillsForPrompt loadSkills loadSkillsFromDirLoadSkillsFromDirOptions LoadSkillsResult Skill SkillFrontmatter
packages/coding-agent/src/core/source-info.tscreateSyntheticSourceInfo—
packages/coding-agent/src/core/tools/edit-diff.tsgenerateDiffString generateUnifiedPatchEditDiffResult
packages/coding-agent/src/core/tools/index.tscreateBashToolDefinition createEditToolDefinition createFindToolDefinition createGrepToolDefinition createLocalBashOperations createLocalPowerShellOperations createLsToolDefinition createPowerShellToolDefinition createReadToolDefinition createWriteToolDefinition DEFAULT_MAX_BYTES DEFAULT_MAX_LINES formatSize truncateHead +3BashOperations BashSpawnContext BashSpawnHook BashToolDetails BashToolInput BashToolOptions EditOperations EditToolDetails EditToolInput EditToolOptions +28
packages/coding-agent/src/core/trust-manager.tshasTrustRequiringProjectResources ProjectTrustStoreProjectTrustDecision ProjectTrustStoreEntry ProjectTrustUpdate
packages/coding-agent/src/core/virtual-models.tsVIRTUAL_MODEL_STATE_ENTRYModelRoute ModelRouteReason ModelRouteRequest VirtualModelDefinition VirtualModelStateData
packages/coding-agent/src/extensions/codemode/index.tscreateCodemodeExtensionCodemodeExtensionOptions
packages/coding-agent/src/extensions/codemode/tool.ts—CodemodeStoreEntryData CodemodeToolDetails
packages/coding-agent/src/extensions/mcp/config.ts—LoadedMcpConfig McpExposure McpServerConfig McpServerEntry
packages/coding-agent/src/extensions/mcp/index.tscreateMcpExtensionMcpExtensionOptions McpTransportFactory
packages/coding-agent/src/extensions/tool-search/index.tscreateToolSearchExtension—
packages/coding-agent/src/main.tsmainMainOptions
packages/coding-agent/src/modes/index.tsInteractiveMode RpcClient runPrintMode runRpcModeInteractiveModeOptions JsonAgentSessionEvent ModelInfo PrintModeOptions RpcClientOptions RpcCommand RpcEventListener RpcExtensionUIRequest RpcExtensionUIResponse RpcResponse +1
packages/coding-agent/src/modes/interactive/components/index.tsArminComponent AssistantMessageComponent BashExecutionComponent BorderedLoader BranchSummaryMessageComponent CompactionSummaryMessageComponent CustomEditor CustomMessageComponent DynamicBorder ExtensionEditorComponent ExtensionInputComponent ExtensionSelectorComponent FooterComponent keyHint +17CustomEditorOptions RenderDiffOptions SettingsCallbacks SettingsConfig ToolExecutionOptions VisualTruncateResult
packages/coding-agent/src/modes/interactive/theme/theme.tsgetLanguageFromPath getMarkdownTheme getSelectListTheme getSettingsListTheme highlightCode initTheme ThemeThemeAppearance ThemeBg ThemeColor ThemeStyle ThemeToken
packages/coding-agent/src/utils/clipboard.tscopyToClipboard—
packages/coding-agent/src/utils/frontmatter.tsparseFrontmatter stripFrontmatter—
packages/coding-agent/src/utils/image-convert.tsconvertToPng—
packages/coding-agent/src/utils/image-resize.tsformatDimensionNote resizeImageResizedImage
packages/coding-agent/src/utils/mime.tsdetectSupportedImageMimeTypeFromFile—
packages/coding-agent/src/utils/shell.tsgetPowerShellConfig getShellConfig—

由构建脚本解析 export { … } from 语句生成;每个模块最多列出 14 个值、10 个类型。Generated by parsing the export { … } from statements at build time; at most 14 values and 10 types are listed per module.

03Run modes

CLI 启动流程CLI start-up#

一句话结论Takeawaymain() 是一条直线:先处理一次性命令,再解析参数、决定模式、跑迁移、读设置、建 SessionManager、确认项目信任、创建 runtime,最后把 runtime 交给 RPC、interactive 或 print 模式。main() is a straight line: handle one-shot commands, then parse args, resolve the mode, run migrations, load settings, create the SessionManager, settle project trust, create the runtime, and hand it to RPC, interactive or print mode.

main() 从参数到运行模式的 14 步The 14 steps in main(), from arguments to run mode
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
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

要点Key points

  • 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.
  • runMigrations(cwd) 在任何会话读写之前执行,迁移旧的认证文件、会话目录、工具目录、按键配置与扩展布局。runMigrations(cwd) runs before any session I/O and migrates old auth files, session directories, tool dirs, keybinding config and extension layout.
  • 项目信任(ProjectTrustStore)决定是否加载 <cwd>/.pi/ 下的设置与扩展;它在创建 runtime 之前确定。Project trust (ProjectTrustStore) decides whether settings and extensions under <cwd>/.pi/ load at all; it is settled before the runtime is created.
  • prepareInitialMessage() 把命令行里的文字、@file 附件和管道输入合成第一条用户消息。prepareInitialMessage() combines command-line text, @file attachments and piped stdin into the first user message.

工作原理How it works

  1. parseArgs(argv) → resolveAppMode(parsed, stdinIsTTY, stdoutIsTTY)。parseArgs(argv) → resolveAppMode(parsed, stdinIsTTY, stdoutIsTTY).
  2. createSessionManager():按 --no-session / --fork / --session / --resume / --continue 选择内存会话、分叉、打开指定会话或选择器。createSessionManager(): in-memory, fork, open a given session or show the picker according to --no-session / --fork / --session / --resume / --continue.
  3. createAgentSessionRuntime() 构造 services 与第一个 AgentSession。createAgentSessionRuntime() builds the services and the first AgentSession.
  4. 按模式分派:runRpcMode(runtime)、new InteractiveMode(runtime).run() 或 runPrintMode(runtime, …)。Dispatch by mode: runRpcMode(runtime), new InteractiveMode(runtime).run() or runPrintMode(runtime, …).

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/cli/args.tsL72parseArgs()参数解析argument parsing
packages/coding-agent/src/main.tsL112resolveAppMode()选择运行模式pick the run mode
packages/coding-agent/src/main.tsL211prepareInitialMessage()第一条消息the first message
packages/coding-agent/src/main.tsL358createSessionManager()打开 / 新建会话open / create a session
packages/coding-agent/src/migrations.tsL305runMigrations()布局迁移layout migrations
packages/coding-agent/src/core/trust-manager.tsL210ProjectTrustStore项目信任project trust
04Run modes

运行模式Run modes#

一句话结论TakeawayresolveAppMode() 根据参数和 TTY 选出四种模式之一;它们都驱动同一个 AgentSessionRuntime。resolveAppMode() picks one of four modes from flags and TTY state; all of them drive the same AgentSessionRuntime.

本节沿用第一版的图(原位于总览页),已按 v1.1.0 重新核对。This section keeps its first-edition diagram (formerly on the overview page), re-checked against v1.1.0.

resolveAppMode() 的分派Dispatch in resolveAppMode()
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
Run modespi <args>命令行入口CLI entryresolveAppMode()1--mode rpc→ rpc2--mode json→ json3-p · stdin/stdout ≠ TTY→ print4否则otherwise→ interactivestdiorunRpcMode()33 种 JSONL 命令 · 响应与事件33 JSONL commands · events outstdoutrunPrintMode() · json每个事件一行 JSONevery event as a JSON linestdoutrunPrintMode() · text一次性运行,只输出最终文本one-shot, prints the final textTTYInteractiveMode编辑器 · 聊天视图 · /命令editor · chat viewport · /commandsAgentSessionRuntime→ AgentSession四种模式驱动同一个运行时all four modes drive one runtime并各自调用and each callsbindExtensions({ mode })非交互模式会先接管non-interactive modesstdout,日志转到 stderrtake over stdout firstso logs go to stderrRPC 把扩展 UI 请求RPC forwards extension转成UI requests asextension_ui_requestpi-tuiTuiMainScreen | TuiAltScreencreateInteractiveTui()调用 / 驱动calls / drives运行模式run modepi-coding-agentpi-tui

要点Key points

  • --mode rpc → rpc;--mode json → json;-p 或 stdin / stdout 非 TTY → print;否则 interactive。--mode rpc → rpc; --mode json → json; -p or non-TTY stdin / stdout → print; otherwise interactive.
  • RPC 模式读取 JSONL 命令(共 33 种:prompt、steer、follow_up、abort、compact、set_model、fork、get_tree、bash …),回写响应与事件。RPC mode reads JSONL commands (33 kinds: prompt, steer, follow_up, abort, compact, set_model, fork, get_tree, bash, …) and writes responses and events.
  • RPC 通过 extension_ui_request 把扩展的 UI 请求代理给宿主。RPC proxies extension UI requests to the host as extension_ui_request.

工作原理How it works

  1. 非 interactive 模式会先接管 stdout,避免日志污染协议输出。Non-interactive modes take over stdout first so logs cannot corrupt protocol output.
  2. 每种模式都调用 session.bindExtensions(),传入各自的 mode 和 UI 上下文。Each mode calls session.bindExtensions() with its own mode and UI context.
  3. interactive 模式通过 createInteractiveTui() 选择 TuiMainScreen(regular)或 TuiAltScreen(fullscreen)。Interactive mode uses createInteractiveTui() to pick TuiMainScreen (regular) or TuiAltScreen (fullscreen).

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/main.tsL112resolveAppMode()模式选择mode selection
packages/coding-agent/src/modes/rpc/rpc-types.tsL20RpcCommandRPC 命令联合类型RPC command union
packages/coding-agent/src/modes/rpc/rpc-mode.tsL54runRpcMode()JSONL 服务循环JSONL service loop
packages/coding-agent/src/modes/print-mode.tsL33runPrintMode()一次性输出one-shot output
packages/coding-agent/src/modes/interactive/interactive-mode.tsL451InteractiveMode终端交互界面terminal UI
05pi-coding-agent

AgentSession 如何装配 AgentHow AgentSession wires the Agent#

一句话结论TakeawayAgentSession 不改写 Agent 的循环,而是把每个钩子接到编码场景的实现上:streamFn 走 ModelRuntime,transformContext 交给扩展的 context 事件,beforeToolCall / afterToolCall 交给 tool_call / tool_result 事件,subscribe() 把每条消息写进会话文件。AgentSession does not rewrite the Agent loop; it plugs each hook into a coding-specific implementation: streamFn goes through ModelRuntime, transformContext to the extensions' context event, beforeToolCall / afterToolCall to the tool_call / tool_result events, and subscribe() writes every message into the session file.

AgentSession 为 Agent 的每个钩子安装的实现,以及运行后的外层循环What AgentSession installs into each Agent hook, and the post-run outer loop
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
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

要点Key points

  • 事件先交给扩展、再交给 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().
  • 扩展的 tool_call 处理器出错时,工具调用会被阻止,而不是放行。If an extension's tool_call handler throws, the tool call is blocked rather than allowed.
  • turn_end 是边界点:扩展可以在两轮之间往会话里追加条目。turn_end is a boundary: extensions may append entries to the session between turns.

工作原理How it works

  1. createAgentSession()(sdk.ts)构造 new Agent({ streamFn, convertToLlm, … }),再把它交给 new AgentSession(…)。createAgentSession() (sdk.ts) builds new Agent({ streamFn, convertToLlm, … }) and passes it to new AgentSession(…).
  2. AgentSession 构造时安装其余钩子并 agent.subscribe()。The AgentSession constructor installs the remaining hooks and calls agent.subscribe().
  3. prompt(text):运行中按 streamingBehavior 转成 steer() / followUp(),空闲时开始新一轮。prompt(text): while running it becomes steer() / followUp() per streamingBehavior; when idle it starts a run.
  4. 运行结束 → _handlePostAgentRun() → 必要时再次 continue(),直到 agent_settled。Run ends → _handlePostAgentRun() → continue() again if needed, until agent_settled.

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/core/sdk.tsL191createAgentSession()构造 Agent 与 AgentSessionbuild Agent and AgentSession
packages/coding-agent/src/core/agent-session.tsL378AgentSession钩子与状态hooks and state
packages/coding-agent/src/core/agent-session.tsL1968prompt()入口entry point
packages/coding-agent/src/core/agent-session.tsL1853_handlePostAgentRun()重试 · 压缩 · 排队retry · compact · queue
packages/coding-agent/src/core/agent-session.tsL2947_checkCompaction()自动压缩判断auto-compaction check
packages/coding-agent/src/core/agent-session.tsL1369subscribe()UI 监听UI listeners
06pi-coding-agent

AgentSessionRuntime:替换会话AgentSessionRuntime: replacing the session#

一句话结论Takeaway/new、/resume、/fork、导入都不是在原会话上“改”,而是整个换掉:先问扩展是否取消,再关闭旧 AgentSession,用新的 SessionManager 和新的 services 建一个新 AgentSession,最后让 UI 和扩展重新绑定。/new, /resume, /fork and import never edit the current session; they replace it: ask extensions whether to cancel, shut down the old AgentSession, build a fresh one with a new SessionManager and fresh services, then let the UI and extensions rebind.

替换会话的 6 步与取消分支The six steps of replacing a session, and the cancel branch
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
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

要点Key points

  • 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 }.
  • 旧会话按 abort → session_shutdown → dispose() 的顺序关闭;扩展的 TUI 组件被同步卸下。The old session closes in the order abort → session_shutdown → dispose(); extension TUI widgets are detached synchronously.
  • 扩展中捕获的旧 ctx 在替换后失效;需要在替换后继续工作的扩展应使用 withSession 回调里的新 ctx。A captured ctx goes stale after replacement; extensions that must keep working should use the fresh ctx passed to withSession.

工作原理How it works

  1. switchSession() / newSession() / fork() 先触发对应的 session_before_* 事件。switchSession() / newSession() / fork() first emit the matching session_before_* event.
  2. 打开或新建 SessionManager(fork 时 newSession({ parentSession }) 记录来源)。Open or create a SessionManager (fork records the origin via newSession({ parentSession })).
  3. createAgentSessionServices() + createAgentSessionFromServices() 建新会话。createAgentSessionServices() + createAgentSessionFromServices() build the new session.
  4. 替换 runtime 内的 session / services / diagnostics,再 rebindSession()。Swap session / services / diagnostics inside the runtime, then rebindSession().

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/core/agent-session-runtime.tsL74AgentSessionRuntime可替换会话的宿主the host that swaps sessions
packages/coding-agent/src/core/agent-session-runtime.tsL196switchSession()切换 / 恢复switch / resume
packages/coding-agent/src/core/agent-session-runtime.tsL262fork()分叉fork
packages/coding-agent/src/core/agent-session-runtime.tsL420createAgentSessionRuntime()首次创建first creation
packages/coding-agent/src/core/agent-session-services.tsL135createAgentSessionServices()模型运行时 · 设置 · 资源model runtime · settings · resources
07pi-coding-agent

内置工具Built-in tools#

一句话结论Takeaway8 个内置工具(read、bash、powershell、edit、write、grep、find、ls),默认启用 read / bash / edit / write。所有输出都经过统一截断(2000 行或 50KB),文件与进程操作通过可替换的 *Operations 接口完成。Eight built-in tools (read, bash, powershell, edit, write, grep, find, ls), with read / bash / edit / write on by default. All output goes through one truncation policy (2000 lines or 50 KB), and file and process access goes through swappable *Operations interfaces.

8 个内置工具、截断上限与可替换的 OperationsThe eight built-in tools, truncation limits and swappable Operations
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
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

要点Key points

  • 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.
  • *Operations 接口让 SDK 宿主把文件系统和 shell 换成远程、容器或测试实现,而不改工具逻辑。The *Operations interfaces let SDK hosts swap the filesystem and shell for remote, container or test implementations without touching tool logic.
  • 扩展用 pi.registerTool() 注册的工具与内置工具并列,可通过 setActiveTools() 开关。Tools registered by extensions via pi.registerTool() sit alongside the built-ins and are toggled with setActiveTools().

工作原理How it works

  1. createAllTools(cwd, options) 返回 Record<ToolName, Tool>;createCodingTools() / createReadOnlyTools() 是常用子集。createAllTools(cwd, options) returns Record<ToolName, Tool>; createCodingTools() / createReadOnlyTools() are the common subsets.
  2. 工具执行结果 → 截断 → 必要时写临时文件并在结果里给出路径。Tool result → truncation → when needed, the full output goes to a temp file and the result names its path.
  3. afterToolCall 再把结果交给扩展的 tool_result 事件。afterToolCall then hands the result to the extensions' tool_result event.

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/core/tools/index.tsL95ToolName8 个工具名the eight tool names
packages/coding-agent/src/core/tools/index.tsL213createAllTools()工具工厂tool factory
packages/coding-agent/src/core/tools/truncate.tsL11DEFAULT_MAX_LINES2000 行 / 50KB2000 lines / 50 KB
packages/coding-agent/src/core/tools/truncate.tsL168truncateTail()bash 的尾部截断tail truncation for bash
packages/coding-agent/src/core/tools/edit.tsL43edit精确替换exact replacement
08pi-coding-agent

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

一句话结论Takeaway每个会话是一个追加写入的 JSONL 文件:第 1 行是会话头(version: 3),之后每行一个条目,共 11 种条目类型。条目用 id / parentId 组成树,分支、标签和压缩摘要都只是新的条目。Each session is an append-only JSONL file: line 1 is the header (version: 3), then one entry per line across 11 entry types. Entries form a tree through id / parentId; branches, labels and compaction summaries are just more entries.

会话文件的位置、内容、条目类型与读写路径Session file location, contents, entry types, and the write and read paths
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
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

要点Key points

  • 文件按 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.
  • 读取时按版本迁移(v1 → v2 → v3),必要时整文件重写,然后从叶子沿 parentId 回溯得到当前上下文。On load, entries migrate by version (v1 → v2 → v3), the file is rewritten if needed, and the current context is rebuilt by walking parentId back from the leaf.

工作原理How it works

  1. SessionManager.create() / open() → loadEntriesFromFile()。SessionManager.create() / open() → loadEntriesFromFile().
  2. migrateSessionEntries() 原地升级到 CURRENT_SESSION_VERSION。migrateSessionEntries() upgrades in place to CURRENT_SESSION_VERSION.
  3. buildSessionContext() 处理压缩条目与分支摘要,产出发给模型的消息列表。buildSessionContext() applies compaction entries and branch summaries to produce the messages sent to the model.

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/core/session-manager.tsL41CURRENT_SESSION_VERSION= 3= 3
packages/coding-agent/src/core/session-manager.tsL183SessionEntry11 种条目11 entry types
packages/coding-agent/src/core/session-manager.tsL350migrateSessionEntries()版本迁移version migration
packages/coding-agent/src/core/session-manager.tsL576buildSessionContext()树 → 上下文tree → context
packages/coding-agent/src/core/session-manager.tsL987SessionManager读写与分支I/O and branching
09pi-coding-agent

会话持久化与分支Session persistence & branching#

一句话结论Takeaway会话是只追加的 JSONL 文件;每个条目带 id 与 parentId,所以一个文件就是一棵树,leafId 指向当前位置。A session is an append-only JSONL file; every entry has id and parentId, so one file is a tree and leafId marks the current position.

本节沿用第一版的图(原位于总览页),已按 v1.1.0 重新核对。This section keeps its first-edition diagram (formerly on the overview page), re-checked against v1.1.0.

一个会话文件中的条目树(示例)The entry tree inside one session file (example)
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
Session persistence & branching~/.pi/agent/sessions/<cwd>/<id>.jsonl只追加append-onlysessionmessagemessagemessagemessagemodel_changemessagemessagebranch_summarymessagea1f0 · messageuser · 修复失败的测试user · fix the failing testb2c4 · messageassistant · toolCall(bash)c3d9 · messagetoolResult · exit 0d4e1 · messageassistant · “已修复”assistant · “fixed”e5a2 · model_changeprovider · modelIdf6b3 · messageuser · 顺便加测试user · also add testsg7c8 · messageassistant · …h8d5 · branch_summaryfromId: g7c8 · summaryi9e6 · messageuser · 换个思路user · try another approachleafIdmessagethinking_level_changemodel_changeusagecompactionbranch_summarycustomcustom_messagelabelsession_infocontext_edit1文件头 · version 3 · id · cwd · parentSession?header · version 3 · id · cwd · parentSession?2a1f0← nulluser · 修复失败的测试user · fix the failing test3b2c4← a1f0assistant · toolCall(bash)4c3d9← b2c4toolResult · exit 05d4e1← c3d9assistant · “已修复”assistant · “fixed”6e5a2← d4e1provider · modelId7f6b3← e5a2user · 顺便加测试user · also add tests8g7c8← f6b3assistant · …9h8d5← d4e1fromId: g7c8 · summary10i9e6← h8d5user · 换个思路user · try another approach每行一个 JSON 对象;id 为 8 位 hex,← 是 parentIdone JSON object per line · 8-hex ids · ← is parentId分支点branch pointleaf 移回 d4e1 后追加leaf → d4e1, then appendfromId被放弃的路径仍留在文件里abandoned path stays in the filebuildSessionContext()leaf → root11 种条目11 entry types当前分支(进入上下文)active branch (in context)引用字段reference field上下文重建方向context rebuild direction

要点Key points

  • 第 1 行是 session 头(version 3、id、cwd、可选 parentSession)。Line 1 is the session header (version 3, id, cwd, optional parentSession).
  • 11 种条目:message、thinking_level_change、model_change、usage、compaction、branch_summary、custom、custom_message、label、session_info、context_edit。11 entry types: message, thinking_level_change, model_change, usage, compaction, branch_summary, custom, custom_message, label, session_info, context_edit.
  • 分支不会改写历史:把 leaf 移回旧条目,下一次追加自然形成兄弟分支。Branching never rewrites history: move the leaf to an older entry and the next append becomes a sibling branch.
  • context_edit 只追加,能把某个旧条目从模型上下文中删除(replacement: null)或替换其内容。context_edit is append-only and can drop an earlier entry from model context (replacement: null) or replace its content.

工作原理How it works

  1. branchWithSummary() 把 leaf 移到分支点,并追加一个 branch_summary(fromId 指向被放弃的 leaf),记录那条路径做过什么。branchWithSummary() moves the leaf to the branch point and appends a branch_summary (with fromId pointing at the abandoned leaf) describing that path.
  2. buildSessionContext() 从 leaf 走到根,应用最新的 compaction 与 context_edit,再转换为 LLM 消息。buildSessionContext() walks from leaf to root, applies the latest compaction and context edits, and converts entries to LLM messages.
  3. 文件位于 ~/.pi/agent/sessions/<cwd>/,custom 条目供扩展保存状态但不进入上下文,custom_message 则会进入。Files live under ~/.pi/agent/sessions/<cwd>/; custom entries store extension state outside the context, custom_message entries enter it.

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/core/session-manager.tsL43SessionHeader文件头file header
packages/coding-agent/src/core/session-manager.tsL183SessionEntry条目联合类型entry union type
packages/coding-agent/src/core/session-manager.tsL1600branchWithSummary()带摘要的分支branch with summary
packages/coding-agent/src/core/session-manager.tsL175ContextEditEntry追加式上下文编辑append-only context edit
10pi-coding-agent

上下文压缩Compaction#

一句话结论Takeaway三种触发(manual / threshold / overflow)走同一条路径:保留最近的尾部,用 LLM 总结更早的部分,存为一个 compaction 条目。Three triggers (manual / threshold / overflow) share one path: keep the recent tail, summarize the rest with the LLM, store it as a compaction entry.

本节沿用第一版的图(原位于总览页),已按 v1.1.0 重新核对。This section keeps its first-edition diagram (formerly on the overview page), re-checked against v1.1.0.

三种触发方式共享的压缩路径One compaction path shared by three triggers
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
Compaction上下文窗口里发生了什么WHAT HAPPENS TO THE CONTEXT WINDOW手动manual/compact · compact()阈值threshold超过 window − reservetokens > window − reserve溢出overflow上下文溢出 / 截断context overflow / truncationprepareCompaction()getBranch() → findCutPoint()compaction_start(reason)session_before_compact扩展钩子extension hook已取消cancelled不追加任何条目nothing appended扩展自带结果extension's resultfromExtension: truecompact()generateSummary() · LLMappendCompaction(summary, firstKeptEntryId, tokensBefore, …)随后 session_compact · compaction_endthen session_compact · compaction_endagent.continue()overflow 且 willRetry:仅一次overflow + willRetry: once完成done否则:等待下一次提示otherwise: wait for next promptcancelcompaction无nonewillRetry压缩前before较早的条目 → 交给 LLM 总结older entries → summarized by the LLM保留尾部 ≈ keepRecentTokens 20,000kept tail ≈ keepRecentTokens 20,000reserveTokens 16,384切点:user 或 assistant 消息,绝不切在 toolResult(firstKeptEntryId)cut point: a user or assistant message, never a toolResult (firstKeptEntryId)压缩后aftercompaction 摘要compaction summary同一段保留尾部the same kept tail腾出的空间freed space阈值:contextTokens > contextWindow − reserveTokens · 保留尾部按 estimateTokens()(chars/4)累加threshold: contextTokens > contextWindow − reserveTokens · kept tail sized with estimateTokens() (chars / 4)12345

要点Key points

  • threshold:contextTokens > contextWindow − reserveTokens(默认 reserveTokens = 16384)。threshold: contextTokens > contextWindow − reserveTokens (default reserveTokens = 16384).
  • overflow:provider 返回上下文溢出错误或可恢复的 length 截断;删除失败消息、压缩,并只重试一次。overflow: a context-overflow error or a recoverable length stop; drop the failed message, compact, and retry exactly once.
  • findCutPoint() 保留约 keepRecentTokens(默认 20000)的最近内容,并让切点落在轮次边界上。findCutPoint() keeps about keepRecentTokens (default 20000) of recent content and puts the cut on a turn boundary.
  • 扩展可在 session_before_compact 中取消压缩,或直接提供自己的压缩结果。Extensions can cancel compaction in session_before_compact or supply their own result.

工作原理How it works

  1. 自动检查发生在三处:agent_end 之后、提交新提示之前,以及 prepareNextTurn 中(同一次运行的轮次之间)。Automatic checks run in three places: after agent_end, before a new prompt, and inside prepareNextTurn (between turns of one run).
  2. token 数优先取最后一条 assistant 的 usage;出错或 usage 为 0 时按 chars/4 估算。Token counts come from the last assistant usage; on errors or zero usage they are estimated at chars/4.
  3. appendCompaction(summary, firstKeptEntryId, tokensBefore, …) 之后,上下文重建为“摘要 + 保留的消息”。After appendCompaction(summary, firstKeptEntryId, tokensBefore, …) the context is rebuilt as summary + kept messages.

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/core/compaction/compaction.tsL267shouldCompact()阈值判断threshold test
packages/coding-agent/src/core/compaction/compaction.tsL446findCutPoint()选择保留的尾部chooses the kept tail
packages/coding-agent/src/core/agent-session.tsL2947_checkCompaction()三种自动情形the automatic cases
packages/coding-agent/src/core/agent-session.tsL3097_runAutoCompaction()扩展钩子与追加extension hook and append
packages/coding-agent/src/core/compaction/compaction.tsL126DEFAULT_COMPACTION_SETTINGS默认 token 参数default token budgets
11Extensions

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

一句话结论Takeaway扩展是一个默认导出函数 (pi) => { … }。pi 上有 32 个方法(注册工具 / 命令 / 快捷键 / provider / 渲染器,行动,读取),pi.on() 可以订阅 41 种事件,其中 18 种的处理器可以返回结果来改写或拦截。An extension is a default-exported function (pi) => { … }. pi has 32 methods (register tools / commands / shortcuts / providers / renderers, act, read), and pi.on() subscribes to 41 events, 18 of which let handlers return a result that rewrites or intercepts.

pi 对象的方法分组、41 种事件与 ctxMethod groups on pi, the 41 events, and ctx
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
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

要点Key points

  • 每个处理器的第二个参数是 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.
  • 可拦截事件的典型用法:input 改写或接管输入,tool_call 阻止工具,context 替换本次上下文,session_before_* 取消会话操作。Typical interceptions: input rewrites or handles input, tool_call blocks a tool, context replaces this request's context, session_before_* cancels a session operation.

工作原理How it works

  1. 加载器用 jiti 导入扩展文件,调用工厂函数,把注册内容收集到 ExtensionRunner。The loader imports extension files with jiti, calls the factory, and collects registrations into the ExtensionRunner.
  2. AgentSession 在各个时机调用 runner.emit*();有结果的事件按扩展顺序依次处理。AgentSession calls runner.emit*() at each point; result-returning events run through extensions in order.
  3. /reload 重新执行整个加载过程;旧的 pi 与 ctx 随之失效。/reload reruns the whole load; the old pi and ctx become stale.

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/core/extensions/types.tsL1564ExtensionAPIpi 对象the pi object
packages/coding-agent/src/core/extensions/types.tsL325ExtensionContext处理器的 ctxthe handler ctx
packages/coding-agent/src/core/extensions/types.tsL149ExtensionUIContextctx.uictx.ui
packages/coding-agent/src/core/extensions/types.tsL574ToolDefinitionregisterTool 的参数registerTool's argument
packages/coding-agent/src/core/extensions/runner.tsL357ExtensionRunner事件分发event dispatch
packages/coding-agent/src/core/extensions/loader.tsL718loadExtensions()加载loading
12Extensions

扩展生命周期Extension lifecycle#

一句话结论Takeaway扩展是用 jiti 加载的 TypeScript 模块:工厂函数拿到 ExtensionAPI 注册能力,ExtensionRunner 在 41 个事件上分发。Extensions are TypeScript modules loaded with jiti: a factory receives an ExtensionAPI to register capabilities, and ExtensionRunner dispatches 41 events.

本节沿用第一版的图(原位于总览页),已按 v1.1.0 重新核对。This section keeps its first-edition diagram (formerly on the overview page), re-checked against v1.1.0.

从发现、加载到事件分发From discovery and loading to event dispatch
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
Extension lifecyclemain.ts · ResourceLoader扩展模块extension moduleAgentSession · ExtensionRunner运行模式run modereload()packageManager.resolve()loadExtensionsCached()按路径加载by resolved pathAgentSession由运行时创建created by runtime~/.pi/agent/extensions.pi/extensionssettings 里的包settings packages-e <path>factory(pi)jiti.import(path)registerTool · on(event)…ExtensionRunnerbindCore():接上真实动作bindCore(): real actionsbindExtensions(){ uiContext, mode }setUIContext()UI 由模式提供UI from the modesession_startresources_discoveremit(event)分发 41 种事件dispatches 41 event typesinputcontexttool_calltool_resultturn_endmessage_endagent_endmodel_selectsession_compactsession_shutdown发现Discover加载Load绑定核心Bind core绑定 UIBind UI运行期Runtime动作先是占位桩actions start as stubsregisterProvider 排队registerProvider queued来源sourcesimportnew注册表registrations事件为 41 种中的节选 · 实心 = 处理器可改写数据events: a selection of 41 · solid = handler may change data12345主流程main flow事件 / 回传event / hand-back调用call

要点Key points

  • 发现来源:全局 ~/.pi/agent/extensions、项目 .pi/extensions、settings 中的 packages,以及命令行 -e。Sources: global ~/.pi/agent/extensions, project .pi/extensions, packages in settings, and CLI -e.
  • register* 家族:Tool、Command、Shortcut、Flag、Provider、McpServer、MessageRenderer、EntryRenderer、ToolRenderer、VirtualModel 等。The register* family: Tool, Command, Shortcut, Flag, Provider, McpServer, MessageRenderer, EntryRenderer, ToolRenderer, VirtualModel and more.
  • 可改写数据的事件:input、context、before_provider_request、tool_call(可阻止)、tool_result、session_before_compact(可取消)。Events that can change data: input, context, before_provider_request, tool_call (block), tool_result, session_before_compact (cancel).

工作原理How it works

  1. createAgentSessionServices() 创建 DefaultResourceLoader,reload() 解析路径并调用 loadExtensionsCached()。createAgentSessionServices() creates a DefaultResourceLoader; reload() resolves paths and calls loadExtensionsCached().
  2. 加载期间 ExtensionRuntime 的动作方法是会抛错的占位,registerProvider 则先排队;AgentSession 创建 ExtensionRunner 并 bindCore() 后换成真实动作。While loading, ExtensionRuntime action methods are throwing stubs and registerProvider calls are queued; once AgentSession creates the ExtensionRunner, bindCore() swaps in real actions.
  3. 模式调用 session.bindExtensions({ uiContext, mode }) 绑定 UI,随后发出 session_start 与 resources_discover。The mode calls session.bindExtensions({ uiContext, mode }) to bind UI, then session_start and resources_discover fire.

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/core/extensions/loader.tsL828discoverAndLoadExtensions()目录发现directory discovery
packages/coding-agent/src/core/resource-loader.tsL695loadCurrentExtensionSet()实际加载路径the real load path
packages/coding-agent/src/core/extensions/types.tsL1564ExtensionAPI扩展可用的全部 APIthe full extension API
packages/coding-agent/src/core/extensions/runner.tsL410bindCore()接入会话动作binds session actions
packages/coding-agent/src/core/agent-session.tsL3258bindExtensions()UI 绑定与 session_startUI binding and session_start
13Run modes

RPC 协议The RPC protocol#

一句话结论Takeawaypi --mode rpc 把智能体变成一个子进程服务:stdin 每行一个 JSON 命令(33 种,分 11 组),stdout 每行一个 JSON——命令响应、会话事件流、扩展 UI 请求混在同一条流里,靠 type 字段区分。pi --mode rpc turns the agent into a subprocess service: one JSON command per stdin line (33 types in 11 groups), one JSON value per stdout line — command responses, the session event stream and extension UI requests share one stream, told apart by type.

stdin / stdout 上的五种消息与全部 RPC 命令The five message kinds on stdin / stdout and every RPC command
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
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

要点Key points

  • 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.
  • JSONL 读取器只按 \n 切分:JSON 字符串里合法的 U+2028 / U+2029 不会把一行切断(Node 的 readline 会)。The JSONL reader splits on \n only: U+2028 / U+2029, legal inside JSON strings, never break a line (Node's readline would).
  • TypeScript 宿主可以直接用 RpcClient,它负责启动子进程、配对请求与响应。TypeScript hosts can use RpcClient, which spawns the process and pairs requests with responses.

工作原理How it works

  1. runRpcMode(runtime) 接管 stdout,订阅会话事件并逐条输出 toJsonEvent(event)。runRpcMode(runtime) takes over stdout, subscribes to session events and writes toJsonEvent(event) for each.
  2. attachJsonlLineReader(stdin) 逐行解析命令,handleCommand() 按 type 分派。attachJsonlLineReader(stdin) parses commands line by line; handleCommand() dispatches on type.
  3. 响应形如 { type: "response", id, command, success, data | error }。Responses look like { type: "response", id, command, success, data | error }.

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/modes/rpc/rpc-types.tsL20RpcCommand33 种命令33 commands
packages/coding-agent/src/modes/rpc/rpc-types.tsL116RpcResponse响应responses
packages/coding-agent/src/modes/rpc/rpc-mode.tsL54runRpcMode()服务循环the service loop
packages/coding-agent/src/modes/rpc/jsonl.tsL21attachJsonlLineReader()按 \n 切行split on \n
packages/coding-agent/src/modes/rpc/rpc-client.tsL56RpcClientTS 客户端TS client
14pi-coding-agent

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

一句话结论Takeaway配置分全局(~/.pi/agent/)和项目(<cwd>/.pi/)两层,项目层只在项目受信任时生效。DefaultResourceLoader.reload() 依次确定信任、重读设置、解析 pi 包、加载扩展与其余资源;system prompt 由一组有序、可单独替换的分段组成。Configuration has a global layer (~/.pi/agent/) and a project layer (<cwd>/.pi/); the project layer applies only to trusted projects. DefaultResourceLoader.reload() settles trust, re-reads settings, resolves pi packages, then loads extensions and the other resources; the system prompt is a set of ordered, independently replaceable sections.

设置合并、资源加载流程与 system prompt 分段Settings merge, the resource load pipeline and system prompt sections
← 左右滑动查看,点击放大 →← swipe to scroll, tap to enlarge →
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

要点Key points

  • deepMergeSettings(global, project):项目值覆盖全局值,嵌套对象逐键合并。deepMergeSettings(global, project): project values win, nested objects merge key by key.
  • pi 包可以来自 npm:、git: 或本地路径,一个包里可以同时带扩展、技能、提示模板和主题。pi packages come from npm:, git: or local paths; one package can ship extensions, skills, prompt templates and themes together.
  • SYSTEM.md 整段替换默认开头,并去掉 tools / rules / docs 分段;APPEND_SYSTEM.md 只追加 <addendum>。两者都是项目优先于全局。SYSTEM.md replaces the default preamble and drops the tools / rules / docs sections; APPEND_SYSTEM.md only adds <addendum>. For both, project beats global.
  • 上下文文件(AGENTS.md、CLAUDE.md …)从全局目录和 cwd 的每一级祖先目录收集,放进 <project_context>。Context files (AGENTS.md, CLAUDE.md …) are collected from the global dir and every ancestor of cwd into <project_context>.

工作原理How it works

  1. createAgentSessionServices() 创建 SettingsManager、ModelRuntime 与 DefaultResourceLoader,并调用 reload()。createAgentSessionServices() creates the SettingsManager, ModelRuntime and DefaultResourceLoader, and calls reload().
  2. reload():resolveProjectTrust → settingsManager.reload() → packageManager.resolve() → CLI 路径 → loadFinalExtensionSet() → 技能 / 提示 / 主题。reload(): resolveProjectTrust → settingsManager.reload() → packageManager.resolve() → CLI paths → loadFinalExtensionSet() → skills / prompts / themes.
  3. buildSystemPromptSections() 组装 preamble、tools、rules、docs、addendum、project_context、skills、cwd 与扩展追加的分段。buildSystemPromptSections() assembles preamble, tools, rules, docs, addendum, project_context, skills, cwd and extension-added sections.

关键文件Key files · v1.1.0

文件File符号Symbol作用Role
packages/coding-agent/src/core/settings-manager.tsL273deepMergeSettings()两层合并two-layer merge
packages/coding-agent/src/core/settings-manager.tsL402SettingsManager设置读写settings I/O
packages/coding-agent/src/core/resource-loader.tsL509reload()资源加载流程the load pipeline
packages/coding-agent/src/core/resource-loader.tsL1210SYSTEM.md项目优先project first
packages/coding-agent/src/core/system-prompt.tsL128buildSystemPromptSections()分段组装section assembly
15pi-coding-agent

扩展点Extension points#

pi.registerTool()增加模型可调用的工具,与内置工具并列。Add tools the model can call, alongside the built-ins.
pi.on(event, handler)41 种事件,18 种可返回结果来改写或拦截。41 events; 18 can return a result to rewrite or intercept.
pi.registerCommand() · registerShortcut()斜杠命令与快捷键。Slash commands and keyboard shortcuts.
pi.registerProvider() · registerVirtualModel()接入新的模型 provider 或虚拟模型路由。Add model providers or virtual-model routing.
ctx.ui.custom() · setWidget()在 TUI 中放入自定义组件。Put custom components into the TUI.
*OperationsSDK 宿主替换文件系统与 shell 的实现。SDK hosts swap the filesystem and shell implementations.
SYSTEM.md · APPEND_SYSTEM.md · AGENTS.md不写代码也能改 system prompt。Change the system prompt without code.
--mode rpc作为子进程嵌入任何语言的宿主:33 种 JSONL 命令。Embed as a subprocess from any language: 33 JSONL commands.
16pi-coding-agent

测试Tests#

一句话结论Takeaway测试最多的是会话与交互:AgentSession(重试、压缩、排队)、SessionManager 的树与迁移、扩展事件、RPC 协议与各个工具都有独立测试文件。Most tests cover sessions and interaction: AgentSession (retry, compaction, queues), the SessionManager tree and migrations, extension events, the RPC protocol and each tool have their own test files.

另有 294 个测试文件未列出(共 314 个,2593 个用例)。294 more test files not listed (314 files, 2593 cases in total).

用例数 = 源码中 it( / test( 的出现次数(静态统计,不运行测试)。Cases = occurrences of it( / test( in the source (static count; tests were not run).

17pi-coding-agent

交叉链接Cross-links#