Extensions 扩展系统
概述
Extensions(扩展)是 TypeScript 模块,用于扩展 Pi 的行为:
- 订阅生命周期事件
- 注册自定义工具
- 添加命令
- 拦截/修改工具调用
- 自定义 UI
快速开始
创建 ~/.pi/agent/extensions/my-extension.ts:
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { Type } from "@sinclair/typebox";
export default function (pi: ExtensionAPI) {
// 监听事件
pi.on("session_start", async (_event, ctx) => {
ctx.ui.notify("扩展已加载!", "info");
});
// 拦截危险操作
pi.on("tool_call", async (event, ctx) => {
if (event.toolName === "bash" && event.input.command?.includes("rm -rf")) {
const ok = await ctx.ui.confirm("危险!", "允许 rm -rf?");
if (!ok) return { block: true, reason: "被用户阻止" };
}
});
// 注册自定义工具
pi.registerTool({
name: "greet",
label: "问候",
description: "向某人打招呼",
parameters: Type.Object({
name: Type.String({ description: "要问候的名字" }),
}),
async execute(toolCallId, params, signal, onUpdate, ctx) {
return {
content: [{ type: "text", text: `你好,${params.name}!` }],
details: {},
};
},
});
// 注册命令
pi.registerCommand("hello", {
description: "打招呼",
handler: async (args, ctx) => {
ctx.ui.notify(`你好 ${args || "世界"}!`, "info");
},
});
}
测试:
pi -e ./my-extension.ts
扩展位置
⚠️ 安全注意:扩展以完整系统权限运行,可以执行任意代码。只安装来自可信来源的扩展。
| 位置 | 范围 |
|---|---|
~/.pi/agent/extensions/*.ts | 全局 |
~/.pi/agent/extensions/*/index.ts | 全局(子目录) |
.pi/extensions/*.ts | 项目本地 |
.pi/extensions/*/index.ts | 项目本地(子目录) |
可用导入
| 包 | 用途 |
|---|---|
@mariozechner/pi-coding-agent | 扩展类型 |
@sinclair/typebox | 工具参数 Schema |
@mariozechner/pi-ai | AI 工具 |
@mariozechner/pi-tui | TUI 组件 |
事件系统
生命周期事件
| 事件 | 说明 |
|---|---|
session_start | 会话开始 |
session_end | 会话结束 |
agent_start | Agent 开始处理 |
agent_end | Agent 处理完成 |
工具事件
| 事件 | 说明 |
|---|---|
tool_call | 工具被调用(可拦截) |
tool_result | 工具执行结果 |
ExtensionContext
扩展上下文提供:
ctx.ui— 用户交互(select、confirm、input、notify)ctx.ui.custom()— 自定义 TUI 组件ctx.appendEntry()— 添加会话条目ctx.getConfig()— 获取配置
自定义工具示例
pi.registerTool({
name: "search",
label: "搜索",
description: "搜索网页",
parameters: Type.Object({
query: Type.String({ description: "搜索关键词" }),
}),
async execute(toolCallId, params, signal, onUpdate, ctx) {
const results = await webSearch(params.query);
return {
content: [{ type: "text", text: JSON.stringify(results) }],
details: {},
};
},
});
自定义 UI
// 显示确认对话框
const ok = await ctx.ui.confirm("确认", "是否继续?");
// 显示输入框
const name = await ctx.ui.input("请输入名称:");
// 显示选择列表
const choice = await ctx.ui.select("选择操作", ["创建", "删除", "取消"]);
// 自定义 TUI 组件
await ctx.ui.custom((terminal, state) => {
// 渲染自定义界面
terminal.write("自定义界面\n");
});
常见用例
- 权限控制 — 删除前确认
- Git 检查点 — 每轮保存 stash
- 路径保护 — 阻止写入
.env、node_modules/ - 自定义压缩 — 按自定义方式总结对话
- 交互式工具 — 向导、对话框
- 状态持久化 — 待办列表、连接池
- 外部集成 — 文件监视器、Webhook