Skip to content

6.4 扩展系统

@pi/coding-agent 允许第三方通过**扩展(Extension)**增强功能:自定义工具、监听事件、注入系统提示、自定义 UI 组件等。这一节讲扩展的两种形态和核心机制。

两种形态

  1. 内联扩展(InlineExtension):代码里直接定义,随应用一起加载。
  2. 文件扩展:从 extensions/ 目录发现并加载(.ts/.js),可独立分发(discoverAndLoadExtensionsloader.ts)。

Extension 的组织

一个扩展主要由两部分组成:

  • 工具:通过 defineTool 定义的 ToolDefinition
  • 事件处理器:监听 ExtensionEvent(见下)。
ts
import { defineTool, type Extension } from "@earendil-works/pi-coding-agent";
import { Type } from "@earendil-works/pi-ai";

const myExtension: Extension = {
	name: "my-extension",
	config: { tools: [myTool] },   // 注册工具
	// 或 handlers: { ... } 监听事件
};

defineTool:定义自定义工具

defineTooltypes.ts:509)让你用类型安全的方式定义 ToolDefinition

ts
const myTool = defineTool({
	name: "hello",
	label: "问好",
	description: "向指定的人问好",
	parameters: Type.Object({ name: Type.String() }),
	async execute(toolCallId, params) {
		return { content: [{ type: "text", text: `你好,${params.name}` }], details: {} };
	},
});

ToolDefinitiontypes.ts:449)比 @pi/agent-coreAgentTool 多了**渲染(render)状态(state)**能力,因为它要跑在 TUI/RPC 等具体 UI 里。

事件处理器:扩展能做什么

扩展通过 ExtensionEvent 事件总线挂接生命周期。常见事件(types.ts:562-646):

事件时机
session_start / session_shutdown会话开始/结束
message_start / message_update / message_end消息生命周期
tool_call工具被调用前(可拦截/改写)
session_compact / session_before_compact上下文压缩前后
session_before_fork / session_before_switch分支/切换前
before_provider_request / before_provider_headers发给模型前,可改请求/头

扩展可以:

  • 自定义工具,模型可调用。
  • 监听/改写会话事件(如自动记录、注入上下文)。
  • 改系统提示BuildSystemPromptOptions)。
  • 自定义 UIExtensionUIDialogOptionsWidgetPlacementmdx 组件)。
  • 定义斜杠命令/命令)。

runner.ts:事件的编排

ExtensionRunnerrunner.ts)负责:

  • 维护所有已加载扩展的处理器。
  • 按事件类型分发给对应处理器。
  • 处理返回结果(如 tool_call 的拦截决定)。

前面 sdk.ts 里能看到 runner 的注入点:

ts
// sdk.ts
transformContext: async (messages) => runner.emitContext(messages),   // 扩展可改上下文
transformHeaders: async (headers) => runner.emitBeforeProviderHeaders(headers),  // 可改请求头

与 @pi/agent-core 事件的关系

两层事件是叠加的,不是替代:

  • @pi/agent-coreAgentEvent:内核级,无 UI 概念。
  • @pi/coding-agentExtensionEvent:产品级,含 UI/会话/压缩等。

AgentSession 订阅内核的 AgentEvent,翻译成产品级事件再分发给扩展。扩展一般只需关心产品级事件。

扩展的配置与发现

ts
// loader.ts
discoverAndLoadExtensions(agentDir)   // 从 ~/.pi/agent/extensions 加载

扩展可通过 Extension.meta 声明依赖、图标等。错误加载单个扩展不会使整个应用崩溃(有 LoadExtensionsResult 上报错误)。

小结

  • 扩展 = 自定义工具 + 事件处理器,有内联/文件两种形态。
  • defineTool 类型安全地定义工具。
  • ExtensionEvent 覆盖会话/消息/工具/压缩/请求全生命周期。
  • ExtensionRunner 负责分发与编排。
  • 扩展事件是内核事件的"产品化"包装。
真实源码位置
  • 扩展类型:packages/coding-agent/src/core/extensions/types.ts
  • defineTooltypes.ts:509
  • 事件定义:types.ts:562-646
  • 编排:core/extensions/runner.ts
  • 加载:core/extensions/loader.ts

下一步看 Demo:SDK 最小调用