92 lines
3.0 KiB
Markdown
92 lines
3.0 KiB
Markdown
# L1 · 工具与命令
|
||
|
||
> 前置:[L0](./01-hello-plugin.md)。`api.pi` 就是 pi 的原生 `ExtensionAPI`——pi CLI 扩展能做的这里都能做,语义一致。
|
||
|
||
## 1. 注册一个带参数的工具
|
||
|
||
工具是 Agent 的「手」:注册后自动进入系统提示词与工具列表,受审批拦截管理。
|
||
|
||
```js
|
||
export default function definePlugin(api) {
|
||
api.pi.registerTool({
|
||
name: 'dice_roll',
|
||
description: '掷一个 N 面骰子,返回点数',
|
||
parameters: {
|
||
type: 'object',
|
||
properties: {
|
||
sides: { type: 'number', description: '面数,默认 6' }
|
||
}
|
||
},
|
||
async execute(_id, params) {
|
||
const sides = Number(params.sides) || 6
|
||
const value = 1 + Math.floor(Math.random() * sides)
|
||
api.log.info('dice rolled', { sides, value })
|
||
return { output: String(value), metadata: { sides, value } }
|
||
}
|
||
})
|
||
}
|
||
```
|
||
|
||
要点:
|
||
- `description` 会注入系统提示词,写清楚「什么时候该用这个工具」,Agent 的调用准确率取决于它
|
||
- `execute` 返回 `{ output: string }`——output 是喂回模型的内容,保持精炼
|
||
- 工具名全局唯一,用 `<插件名>_<动作>` 前缀避免撞名
|
||
|
||
## 2. 注册斜杠命令
|
||
|
||
命令是用户的「入口」:聊天框输入 `/` 出现,回车触发。
|
||
|
||
```js
|
||
export default function definePlugin(api) {
|
||
api.pi.registerCommand({
|
||
name: 'dice',
|
||
description: '掷骰子',
|
||
handler: async (ctx, args) => {
|
||
const sides = Number(args) || 6
|
||
ctx.notify(`🎲 ${1 + Math.floor(Math.random() * sides)} / ${sides}`)
|
||
}
|
||
})
|
||
}
|
||
```
|
||
|
||
## 3. 订阅事件
|
||
|
||
在 Agent 生命周期钩子上挂逻辑(发消息前注入、工具调用前后处理等):
|
||
|
||
```js
|
||
export default function definePlugin(api) {
|
||
const off = api.pi.on('before_agent_start', (event) => {
|
||
api.log.debug('agent starting', { prompt: event.prompt?.slice(0, 50) })
|
||
})
|
||
// 返回的取消函数放进 dispose,宿主在禁用/重载时调用
|
||
return () => off()
|
||
}
|
||
```
|
||
|
||
常用事件:`before_agent_start` / `agent_start` / `tool_call` / `tool_result` / `before_provider_request` / `agent_end`。全集见 pi 的 `ExtensionAPI` 类型(`@earendil-works/pi-coding-agent`)。
|
||
|
||
## 4. 与插件私有存储配合
|
||
|
||
需要跨回合记住状态时用 `api.storage`(按插件隔离,落盘 `aso-plugin-storage.json`):
|
||
|
||
```js
|
||
let count = api.storage.get('count') ?? 0
|
||
api.storage.set('count', ++count)
|
||
```
|
||
|
||
## 5. 验证
|
||
|
||
1. 重载插件(开关切换或重启)
|
||
2. 日志确认 `plugin activated`
|
||
3. 聊天框输入 `/dice` 回车 → 收到点数;对 Agent 说「掷个 20 面骰」→ 观察它调用 `dice_roll`
|
||
4. 日志中应出现 `dice rolled sides=20 value=…`
|
||
|
||
## 排障
|
||
|
||
- 工具没出现在 Agent 里:日志搜 `plugin activated` 确认激活成功;`registerTool` 抛错会记为 `plugin activation failed`
|
||
- 命令没出现在 `/` 面板:命令名冲突(重名被去重),换名再试
|
||
|
||
---
|
||
|
||
**上一篇** [L0](./01-hello-plugin.md) · **下一篇**:[L2 设置表单](./03-settings.md)——让用户能配置你的插件。
|