Skip to content

扩展系统 ​

扩展是 Pi 应用层的核心扩展点。实现在 packages/coding-agent/src/core/extensions/,主要文件是 types.ts(接口与事件)和 runner.ts(派发)。

组成 ​

text
ResourceLoader 负责发现和加载扩展
ExtensionRunner 由 AgentSession 持有,reload 时整体替换
ExtensionContext 是每个 handler 收到的上下文

AgentSession._buildRuntime() 创建 runner,并通过 _bindExtensionCore() 把 AgentSession 的能力暴露给扩展。

扩展拿到的上下文 ​

ExtensionContext 提供:

能力说明
uiExtensionUIContext,对话框、状态、自定义组件、编辑器、主题
mode / hasUI运行模式(tui/rpc/json/print)和是否有对话框能力
cwd / sessionManager / modelRegistry环境信息
model / scopedModels / thinkingLevel当前选择
isIdle() / hasPendingMessages()运行状态
isProjectTrusted()项目信任状态
signal / abort()当前 run 的取消能力
shutdown()退出 Pi
getContextUsage() / compact() / getSystemPrompt()上下文管理

工具执行时拿到的是 ExtensionToolContext,在基础上下文上加:

  • tools:可调用的工具列表
  • executeTool(name, args, options):走完整校验和钩子的嵌套调用

命令 handler 拿到的是 ExtensionCommandContext,额外提供 waitForIdle()、newSession()、fork()、navigateTree()、switchSession()、reload()、getSystemPromptOptions()。会话被替换后,withSession() 回调收到的是绑定新会话的 ReplacedSessionContext。

事件分类 ​

类别事件
会话生命周期session_start、session_shutdown、session_before_switch、session_before_fork、session_before_compact、session_before_tree
run/turnagent_start、agent_end、turn_start、turn_end、agent_before_settle、agent_settled
消息message_start、message_update、message_end、before_agent_start
工具tool_call、tool_result、tool_execution_start、tool_execution_update、tool_execution_end
选择model_select、thinking_level_select
输入input、user_bash
UI/进度ui_prompt_start、ui_prompt_end、bash_execution_update
资源resources_discover

派发语义 ​

runner 用 snapshotEventHandlers() 按加载顺序遍历所有 handler。handler 抛错不会中断 run:错误通过 emitError 报告(带扩展路径、事件名、错误、堆栈),然后继续下一个 handler。

不同事件的返回值语义不同:

方法语义
emit()通用派发;session_before_* 的 cancel 会立即短路
emitBeforeAgentStart()收集自定义消息;systemPrompt 覆盖会记录到 forceSystemPrompt
emitMessageEnd()handler 可以替换消息,但必须保持原 role
emitToolCall()第一个 block: true 生效;改参数靠原地修改 event.input
emitToolResult()逐字段合并;替换 content 时 structuredContent 默认丢弃
emitBoundary()收集 drafts 和 continue,每个 handler 之后重建一次预览上下文
emitResourcesDiscover()收集 skill / prompt / theme 路径

tool_call 是例外:handler 抛错会向外冒泡,变成阻止工具执行的错误。

边界事件 ​

turn_end 和 agent_before_settle 共享 BoundaryState:

ts
{
  entries: SessionBoundaryDraft[];
  continue: boolean;
  context: BoundaryContextPreview;
  outcome: "completed" | "aborted" | "error";
}

draft 类型:

draft效果
custom追加不参与 LLM 上下文的 entry
custom_message追加参与上下文的 custom 消息
context_edit替换或省略早期 entry 的内容
compaction追加 compaction entry

AgentSession._buildBoundaryContext() 负责判断 canContinue:模型上下文必须存在且最后一条不是 assistant,或者有待投递的自定义消息/队列消息。agent_before_settle 更严格:只有最后一条是 assistant 且队列非空时才允许继续。

如果 handler 返回了非法 drafts,runner 会丢弃这一轮所有 drafts,并把 continue 置为 false。

注册型 API ​

扩展还能注册各种静态资源:

API作用
registerTool(tool)注册工具,进入工具注册表
registerCommand(name, options)注册 /command,在 prompt() 入口优先执行
registerShortcut(shortcut, options)注册键盘快捷键
registerFlag(name, options) / getFlag(name)注册和读取 CLI flag
registerMessageRenderer(customType, fn)自定义 custom 消息渲染
registerEntryRenderer(customType, fn)自定义非上下文 entry 渲染
registerMarkdownTransformer(fn)在渲染前转换 Markdown
registerToolRenderer(resolver)决定工具调用如何渲染
registerProvider / registerVirtualModel 等通过绑定的 core 能力扩展模型目录

主动动作 ​

text
ctx.sendMessage(msg, { triggerTurn, deliverAs })
ctx.sendUserMessage(content, { deliverAs })
ctx.appendEntry(customType, data)
ctx.setSessionName / getSessionName / setLabel
ctx.executeTool(name, args)

deliverAs 有 steer、followUp、nextTurn 三种,分别对应运行中插入、结束后执行、随下一条用户消息一起发送。

建议阅读顺序 ​

  1. packages/coding-agent/src/core/extensions/types.ts

    • ExtensionContext / ExtensionToolContext / ExtensionCommandContext
    • 事件类型和对应的 Result 类型
    • ToolDefinition
  2. packages/coding-agent/src/core/extensions/runner.ts

    • emit() / emitBoundary() / emitBeforeAgentStart()
    • emitMessageEnd() / emitToolCall() / emitToolResult()
    • bindCore() 暴露的能力
  3. packages/coding-agent/src/core/agent-session.ts

    • _bindExtensionCore()
    • _emitExtensionEvent()
    • _dispatchTurnEndBoundary() / _runBeforeSettleBoundary()