从一个任务提醒开始,给 Pi 加上自己的第一个小功能
最近我一直在用 Pi,也装了一些别人写的 Extension。
用着用着,就会碰到一些想自己改的地方。别人觉得顺手的功能,未必完全符合我的习惯;装得多了,还得留意有没有重复功能,会不会互相影响。于是,我开始有了自己写 Extension 的念头。
前面发布相关内容的时候,也有人问过我,新手应该怎么开始自己的第一个 Extension。这篇就从这里讲起。
我想拿任务结束提醒来做个例子。需求容易说清楚,做出来以后也用得上。第一次动手,先给自己的 Pi 补上这样一个小功能,就够了。
一、先弄明白 Extension 能做什么
Extension 就是用来扩展 Pi 行为的一段程序。
列出了可以接入的位置。
你可以让它在某件事发生后做一个动作,也可以给 Pi 增加自己的命令,或者调整下面的状态栏。这篇要做的提醒,就是让它等 Pi 这一轮处理结束,再发出通知。
刚接触 Pi 的时候,可能还会遇到 Skill、Package 这些名字。放在一起看,会更容易分清。
| 名称 | 主要用途 | 放在这篇里怎么理解 |
|---|---|---|
| Skill | 提供完成某类工作的说明和相关材料 | 告诉 Pi 按什么方法做事 |
| Extension | 用代码扩展 Pi 的运行行为 | 让 Pi 结束处理时触发提醒 |
| Package | 组织和分发扩展、Skill、主题等资源 | 方便安装和分享做好的东西 |
写第一个 Extension,可以从一个 .ts 文件开始。暂时用不着先学会打包发布,也不用先把所有接口研究一遍。官方就有
,可以让 Pi 参考它,再按自己的需要改。
代码可以请 Pi 帮忙写。你需要把需求说清楚,并且看一眼它生成了什么、把文件放在哪里。Extension 会实际运行代码,安装别人的扩展时也一样,要知道它的来源和用途。
二、先说清楚我想要怎样的提醒
我的需求很具体。给 Pi 发出一个请求后,我想切去浏览器做别的事。等它这一轮处理结束,桌面上出现一条提醒,我再回来看看结果。
这条提醒要能在切换软件后看到。只在 Pi 对话界面里多显示一行字,对这个场景帮助不大。
第一版先用固定文案。
Pi 这一轮处理结束了,回来看看结果
这里没有直接写“任务成功”。Pi 停下来的时候,有可能已经给出了结果,也有可能遇到了错误,或者被手动中断。提醒负责叫我回来,结果还得自己看。
通知历史、手机推送这些先不加。等这个小功能能正常用,再看有没有必要继续做。需求越具体,后面就越容易判断生成的东西是不是自己要的。
三、用一个提醒扩展,走完第一次制作
下面按 macOS 加 iTerm2 来讲。准备这篇时,本机是 Pi 0.84.3、iTerm2 3.6.11。你需要已经能启动 Pi,并且能正常提交一个任务。使用其他终端的朋友,可以参考这个过程,让 Pi 根据自己的环境调整通知方式。
\1. 建一个练习目录,把需求交给 Pi
先在普通终端里执行下面几行。此时还没有进入 Pi 的对话界面。
1 | mkdir -p ~/pi-notify-practice |
这里单独建个目录,方便看清新文件,也方便试完以后停用。进入 Pi 后,把下面这段需求发给它。
1 | 帮我写自己的第一个 Pi Extension,只做任务结束提醒。 |
这段需求把触发时间、通知内容和文件位置都交代了,也说明了第一版做到哪里为止。Pi 生成代码后,先确认文件确实写到了 .pi/extensions/task-notify.ts,不要停在聊天里展示代码就算完成。
这也是我现在写 Extension 比较明显的一个感受。第一次只解决一个小问题。 你把它用起来以后,会更容易知道下一步该加什么。
下面是这次真实生成会话的记录。第一张保留了需求、运行环境和保存位置,第二张把生成代码、文件写入结果和测试方法放大,方便核对关键内容。
\2. 让 Pi 加载这个文件
文件生成了,还要让 Pi 重新读取它。在 Pi 的输入框里输入下面这个命令。
1 | /reload |
如果出现项目扩展的信任提示,确认当前目录和代码是自己刚才准备的内容,再决定加载。项目里的扩展需要在项目受信任后才会启用。第一次拿不准有没有加载,可以退出 Pi,在这个练习目录重新启动,留意启动时的提示和报错。
Pi 空闲后,输入下面这个命令测试。
1 | /notify-test |
它直接测试通知,不需要再让模型回答一个问题。如果提示找不到命令,先检查文件位置和加载错误;如果命令可用却看不到桌面通知,再查 iTerm 和系统的通知设置。这样能少绕一些弯路。
这里也顺便说一下 Global 和 Project。Pi 常用的自动加载位置有两个。
文件放置位置 使用范围 当前项目的 .pi/extensions/ 当前项目 用户目录的 ~/.pi/agent/extensions/ 多个项目共用
任务提醒属于比较通用的功能,试顺手以后可以移到全局目录。项目自己的部署、数据库操作或特殊规则,我更愿意留在项目里。每次打开 Pi,都能知道当前启用了哪些功能。
如果把这个文件移到全局,项目里的同一份就一起移走。两个位置都放着,可能会把同一个通知发两遍。
\3. 看懂这份小扩展,再跑一次任务
如果想先用一份现成代码走完整个过程,也可以把下面的内容保存为 .pi/extensions/task-notify.ts,然后回到上一步重新加载。
1 | import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; |
不用一行一行背代码。先找到中间的 agent_settled,它负责等 Pi 这次处理停稳。按照官方的事件说明,agent_end 后面还可能有自动重试或排队消息,做这种结束提醒时要考虑这些后续动作。
再看上面的 process.stdout.write,它把通知指令交给终端。这里用的是
。能不能显示横幅,还要看终端和系统设置,所以换终端时需要重新验证。
前面几个判断则把通知限制在终端交互界面,而且只在 Pi 空闲时发送。后面的 /notify-test 让你能单独试这条通知通道。第一次了解这些,就已经足够动手改文案了。
先发一个短请求试试。
1 | 给我三条周末出行准备建议,每条十个字以内。 |
发送后切到浏览器,观察有没有收到提醒,再回到 Pi 看结果。任务太短、来不及切换时,可以让它写一份稍长的出行清单。重点是走完“提交请求、离开 Pi、收到提醒、回来查看”的过程。
同一轮处理正常结束时,预期收到一条提醒。如果出现两条,先检查有没有同时加载别的通知扩展,或全局与项目各放了一份。
下面这张保留了扩展文件检查和 Pi 给出的行为说明。它能证明文件已经生成,也能核对手动测试命令。桌面横幅仍要以 iTerm 的实际画面为准。
准备文章时,我在独立的 Pi 交互会话里执行了 /notify-test,原始文案确实出现在 iTerm 通知里。修改文案并重新启动 Pi 后,再执行一次测试命令,通知也换成了新文字。这里验证的是当前这套 macOS 与 iTerm2 环境,换到其他终端仍要重新测试。
这个功能没有给模型增加新的 Tool。Extension 可以提供工具,也可以只监听事件、增加用户命令,这次用后两项就够了。
我现在会比较留意这件事。扩展写着写着,很容易把想到的功能全加进去。实际要给模型用哪些工具、要加载什么内容,最好跟着需求来,缺了再补。
\4. 改一句话,体验自己的第一次修改
找到文件最上面的 NOTIFICATION_BODY,把引号里的文字改成自己习惯的说法。比如下面这样。
1 | const NOTIFICATION_BODY = "Pi 这边处理结束啦,回来看看"; |
保存文件,在 Pi 里执行 /reload,等它加载完成,再输入 /notify-test。这次要看的是通知有没有换成新文案,以及有没有重复出现。改完文件就直接测,很容易还在测旧代码。
不想自己改,也可以告诉 Pi,只修改通知文案,其他行为保持原样。改动越小,越容易看清它到底改了哪里。
/reload 确实很适合这样来回试。以后想加提醒开关,再多想一步,关闭状态要不要在重新加载后保留。只存在内存里的变量,重新加载后未必还在;需要保留的设置,要另外设计保存和恢复方式。
这次的版本没有开关,也没有通知历史,先不用处理这些。后面真的嫌提醒太频繁,可以加一个耗时门槛,只提醒运行比较久的任务。每次补一个自己已经遇到的问题就好。
试完想停用,把 task-notify.ts 移出 .pi/extensions/,例如放到练习目录下的 disabled/,然后再执行 /reload。留一份文件,后面想继续改也方便。
四、第一次动手,容易卡在哪里
如果前面的效果没有出现,可以按下面这些情况检查。
| 遇到的情况 | 先检查什么 |
|---|---|
| 文件生成了,命令却找不到 | 是否保存为 .ts 文件,位置是否正确,项目是否受信任,加载时有没有代码错误 |
| Pi 里面有提示,切出去却看不到 | 生成的代码是否只用了 ctx.ui.notify,它显示的是 Pi 界面内提示 |
| /notify-test 可用,却没有桌面通知 | 当前终端是否支持对应协议,再检查 iTerm 与 macOS 通知设置、专注模式;先在普通本地终端测试 |
| 文案改了却没生效 | 是否保存并重新加载,正在修改的文件是否就是实际加载的那份 |
| 同一轮结束提醒了两次 | 检查全局和项目的重复副本,以及其他同类扩展,逐个停用定位 |
| 旧版本运行时报接口错误 | 让 Pi 对照当前安装版本的文档检查,本文代码按 Pi 0.84.3 核验 |
手动中断后收到提醒,也不一定是扩展出错。这里监听的是停止自动处理的时机,文案特意让你回来查看结果。如果以后只想在成功时提醒,就得先定义自己怎样判断成功,再继续修改。
其他终端可以参考官方通知示例,选择它支持的方式。通过 SSH 运行时,显示通知的通常是你本地使用的终端;中间还有 tmux 等工具时,也要检查通知指令能不能传过去。这些可以放到后面有需要时再研究。
最后
我刚开始用 Pi 的时候,也会到处找 Extension。后来开始删重复的,再慢慢补一些自己缺的功能。
现在我会先看一个扩展解决什么问题,自己有没有这个需求。现成的合适就用,有具体不满意的地方,也可以借助 Pi 开放的扩展能力自己改。工作台要慢慢搭,先从一个任务提醒开始就挺好。



