@cobia/pi-onward0.5.2
pi 出错或空回复时,按阶段策略恢复并调用扩展命令或具名动作
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
⏩ pi-onward
pi 出错或空回复时,按规则和阶段自动续跑,也可以调用其他插件的命令或动作
📦 安装
pi install npm:@cobia/pi-onward
安装后重新打开 Pi,或执行 /reload,再输入 /onward 检查插件是否加载
🚀 开始使用
1. 配置恢复规则
pi-onward 没有默认规则。复制包里的 example.json 到 ~/.pi/agent/onward.json,再按自己的需求修改
示例会在额度不足时停止,在临时服务错误或网络错误时重发任务提示词,在空回复时提示继续;连续失败达到示例中的停止阶段后,交由用户处理。规则、次数和间隔都可以调整,写法见规则与阶段
只想在当前项目使用时,也可以放到 <项目>/.pi/onward.json;项目需要先获得 Pi 信任,详见作用域与位置
2. 加载并检查
在 Pi 中执行:
/reload
/onward status
/onward show rules
确认状态为已启用、规则已加载后,照常发送任务。Pi 完成自身的重试和恢复后,如果仍以错误或空回复结束,onward 会按配置执行恢复动作
💬 日常使用
自动恢复
onward 处理两类失败:Pi 明确以错误结束,或者正常结束但没有文字、工具调用。规则按顺序匹配,第一条命中的规则生效;再根据连续失败次数选择该规则的一个阶段。每个阶段只执行一个具名动作
| 内置动作 | 作用 |
|---|---|
pi.message |
追加一条自定义消息,继续当前任务 |
pi.command |
等当前轮次完全结束后,调用已加载的扩展命令 |
onward.stop |
停止当前恢复过程,保留动作结果供查看 |
pi.message 和 pi.command 随 onward 一起提供,无需另外安装。pi.* 是 onward 对接 Pi 的动作命名空间,并非 Pi 官方 API
查看状态与开关
用 /onward 打开菜单,或直接执行:
/onward status
/onward off
/onward on
status 显示命中的规则、当前阶段、连续失败次数、已启动续跑次数和动作结果;查询不会改变恢复状态,也不会把这些信息发给模型
off、on 默认修改全局配置并立即生效,同时取消当前恢复。项目级开关优先于全局;只修改当前项目时,使用 /onward --scope project off 或 on。启用开关不会立即发起模型请求
onward.stop 只结束本轮恢复;需要持续停用自动恢复时,使用 /onward off
状态栏
状态栏采用 emoji onward · 失败次数 的短格式,例如 ⏳ onward · 失败3。数字表示本轮连续失败次数,规则、动作名和完整原因通过 /onward status 查看
| Emoji | 含义 |
|---|---|
| ⏳ | 等待间隔、提议等待启动或动作待执行 |
| ⏩ | 已启动续跑 |
| 🚀 | 正在执行动作 |
| 🎉 | 动作完成 |
| 📤 | 命令已分派,业务结果由目标插件报告 |
| 🔀 | 已接受接管 |
| 🛑 | 本轮恢复停止,例如规则停止、未命中规则或达到次数上限 |
| 🚫 | 恢复已取消 |
| 💥 | 动作失败,同时显示“动作失败” |
| 🎲 | 结果未知,同时显示“结果未知” |
空闲时隐藏状态栏;终止结果保留到当前恢复状态被清除。异常提示示例:🎲 onward 结果未知 · 失败3
续跑消息与任务提示词
pi.message 的 prompt 默认为 继续,可以使用以下变量,也可以与正文拼接:
| 变量 | 内容 |
|---|---|
{failures} |
本轮连续失败次数,包含当前失败 |
{rule} |
当前命中的规则名称 |
{error} |
当前错误信息;空回复时为“空回复” |
{taskPrompt} |
本轮已接收的任务提示词文本 |
例如,在阶段的 action 中填写:
{
"use": "pi.message",
"with": { "prompt": "请重新尝试:\n{taskPrompt}" }
}
上次输入为 检查并修复登录接口 时,会追加 请重新尝试: 换行后接该任务文本。"prompt": "{taskPrompt}" 直接重发任务文本,"prompt": "继续{taskPrompt}" 则在前面加上“继续”。这些写法都会追加一条新消息,保留历史回复
模板只替换一次:任务文本或错误信息中包含的 {error}、{taskPrompt} 等文字保持原样,未知变量也保持原文
{taskPrompt} 使用真正进入会话的用户消息,包含输入扩展改写、Pi 技能及提示词模板展开后的结果。人工或 RPC 消息被接收后才更新任务来源和恢复计数;被拦截、尚未消费或已取消的输入不会成为新任务。自动续跑保留原任务;新会话首次由扩展发起任务时,以该消息为任务来源
重载、恢复会话或切换分支时,onward 根据当前分支的来源记录重建任务。来源记录不重复保存提示词正文,也不进入模型上下文。重发只复用文字,不复制图片附件或整个请求上下文;缺少任务文本、来源记录或无法确定排队消息来源时,使用 {taskPrompt} 的动作会明确失败并停止本次恢复
调用其他插件
目标命令由 Pi 加载后,就可以通过 pi.command 调用,目标扩展无需修改、无需注册 onward 动作:
{
"use": "pi.command",
"with": {
"name": "example-command",
"args": "-- 继续执行当前任务"
}
}
example-command 是占位名称,替换成实际已加载的扩展命令,不带开头的 /。args 按目标命令的格式填写,原样传递,不经过 shell、不替换 onward 模板,也不需要模型执行。/model 等 Pi 内置交互命令不属于扩展命令,不支持这个入口
结果“已分派”表示命令已交给 Pi,业务是否成功由目标插件报告。onward 不能强制取消已经进入目标命令处理器的操作,也不会自动重放命令。通用命令的跨会话、跨进程防循环由目标插件负责,maxHandoffs 不限制这类调用
计数与停止
连续失败次数属于整轮恢复,换错误或换规则不会清零。一次失败以 Pi 完成本轮重试后的最终结果为准,不包含 Pi 内建重试期间的每个 HTTP 请求
- 正常模型回复(包括工具轮)结束本轮恢复。
- 已接收的人工新任务、Esc、关闭自动恢复、Pi 重载、切换分支和配置修改会取消未执行动作;Esc 保留本次失败的诊断状态。
- 扩展自动发送的续跑消息保留当前恢复过程和失败计数。
- 没有匹配规则、超过
maxFailures、动作要求停止,或动作完成后没有安排新请求时,本轮停止。 - 动作失败、超时、抛出异常或返回非法结果时,不自动进入下一阶段;超时、异常及非法返回标记为“结果未知”,不自动重放可能已经产生副作用的动作。
终止状态会保留动作结果,等待新的人工任务
📝 配置文件
用 /onward show 查看已加载配置、每项来源和文件位置。修改顶层参数可以直接使用命令:
/onward set maxFailures=10 actionTimeout=45s
/onward unset maxHandoffs
/onward --scope project set maxFailures=5
/onward --scope project show
规则和动作写在 JSON 的 rules 中;set 只修改恢复上限、动作时限和全局 quietStartup,开关用 on、off
作用域与位置
优先级:内置默认值 < 全局 < 项目
| 作用域 | 适用范围 | 配置文件 |
|---|---|---|
global |
同一系统用户下的 Pi 会话 | ~/.pi/agent/onward.json |
project |
启动 Pi 的工作目录 | <工作目录>/.pi/onward.json |
设置 PI_CODING_AGENT_DIR 时,全局配置跟随 Pi 的用户目录。项目配置只读取启动目录下这一份,不向父目录查找
项目配置只在 Pi 已信任当前项目 时读写。未受信任时不读取文件、不参与合并,也不允许 /onward --scope project 修改;全局配置照常生效,show 会说明项目层已跳过。检查项目内容后,可用 Pi 的 --approve 为本次启动授权,或用 /trust 保存决定并重新加载。仅有 onward.json 不一定触发 Pi 的自动信任提示
--scope global|project写在动作前。不指定范围时,修改写全局,show显示合并结果;指定范围后只查看或修改那一层。- 普通字段逐项覆盖,
unset删除本层值并恢复继承。 - 项目级
rules整份替换全局规则,不拼接;不写则继承,写[]则不使用全局规则。 quietStartup只能写在全局;不写时跟随 Pi。配置错误、动作注册问题和规则遮挡提醒仍会显示。
配置示例
下面的规则在第 1、2、3 次服务错误后重发任务文本,第 4 次失败时停止:
{
"$schema": "https://raw.githubusercontent.com/cobia68/pi-labs/main/packages/pi-onward/onward.schema.json",
"enabled": true,
"maxFailures": 20,
"maxHandoffs": 3,
"actionTimeout": "30s",
"rules": [
{
"name": "server",
"when": { "failure": "502|503|Connection error" },
"stages": [
{
"minFailures": 1,
"delay": "3s..15s",
"action": {
"use": "pi.message",
"with": { "prompt": "{taskPrompt}" }
}
},
{
"minFailures": 4,
"action": {
"use": "onward.stop",
"with": { "reason": "连续失败,请检查服务状态" }
}
}
]
}
]
}
$schema 用于编辑器补全和校验;实际配置是否可用以 /onward show 为准。希望失败后调用其他插件时,把对应阶段的 action 换成命令动作或已加载的具名动作
| 字段 | 默认值 | 含义 |
|---|---|---|
enabled |
true |
是否启用自动恢复 |
maxFailures |
20 |
一轮恢复最多处理的连续失败数;超过后停止 |
maxHandoffs |
3 |
结构化恢复链最多跨会话接管的次数;0 禁止接管 |
actionTimeout |
"30s" |
单次动作执行时限,等待 delay 不计入 |
quietStartup |
跟随 Pi | 是否隐藏正常启动提示,仅限全局 |
rules |
[] |
按顺序匹配的恢复规则 |
规则与阶段
一条规则由匹配条件 when 和恢复阶段 stages 组成:
when.failure是大小写不敏感的正则。空回复用空字符串匹配,所以^$只匹配空回复,.+只匹配普通错误,.*匹配所有失败。when.provider、when.model匹配整串名称,只有*是通配符;多个条件必须同时满足。不写when时匹配任何失败,通常放在最后作为兜底。- 规则可以用
enabled: false停用;按顺序选择第一条启用且匹配的规则。 minFailures是连续失败次数下限,包含当前失败。第一阶段必须为1,之后严格递增;每次选择已经达到下限的最后一个阶段。- 每个阶段引用一个
action,结构为{ "use": "动作名", "with": { "参数": "值" } },with可省略;不会隐式切换到其他动作。
例如,要先续跑 10 次、再停止,可在 minFailures: 1 设置消息动作,在 minFailures: 11 设置停止动作,并让 maxFailures 至少为 11
delay 默认为 0s,使用序号 连续失败次数 - minFailures + 1 选择间隔。达到阶段阈值的那次失败使用第一个间隔;换规则不会重置连续失败次数:
| 写法 | 等待时间 |
|---|---|
"10s" |
每次 10 秒 |
"5s,15s,35s,1m" |
5、15、35、60、60… 秒;列表用完后重复最后一项 |
"3s..15s" |
3、6、9、12、15、15… 秒;以起始值递增,到上限后保持 |
修改何时生效
- 通过命令修改:
/onward on/off/set/unset/reset写入配置后,立即在当前运行中生效,无需重载 Pi;成功的修改会取消当前恢复。 - 直接编辑文件:使用 Pi 的
/reload或重启加载;会话开始时也会重新读取配置。其他已打开的 Pi 会话需要各自重新加载。 - 查询配置:
show、status、actions只读当前运行状态,不重读配置文件、不清零计数。
set 先检查全部参数,有一项不合法就一项都不改。文件无法读取时不改文件;reset 即使无法修改文件,也会取消本轮恢复并清零计数
写入失败时,本次运行仍立即应用该层修改,show 标记“未保存”;修改另一层不会丢掉它们。再次修改同一层时,先重读文件,合并尚未保存的设置和删除操作,再一起尝试落盘,保留未涉及字段的手工编辑。Pi 的 /reload、切换会话或重启会清除未保存修改,重新以磁盘内容为准
未知字段、非法正则、空阶段、阶段阈值错误或重复规则都会使整份配置无效。已启用规则引用未加载的动作、冲突的动作或非法参数时,也不会启用部分配置。未被引用的动作注册失败只报告警告;动作参数由提供者的 JSON Schema 校验,运行模式在调用前检查
🧰 命令速查
以下命令在 Pi 中执行,支持 Tab 补全;--help 只显示帮助,不执行修改
| 命令 | 作用 |
|---|---|
/onward |
打开状态和配置菜单,默认修改全局配置 |
/onward actions |
查看已加载的具名动作及注册失败原因 |
/onward off |
停用自动恢复并取消当前恢复过程 |
/onward on |
启用自动恢复,不立即请求模型 |
/onward reset |
删除本层开关、恢复上限和 quietStartup,保留规则及其他手写内容;重置运行状态 |
/onward set 字段=值 … |
修改上限、动作时限或全局 quietStartup,全部参数先校验 |
/onward show [rules] |
查看已加载配置、来源、规则和文件位置;rules 只列规则 |
/onward status |
查看当前阶段、失败数、已启动续跑数及动作结果 |
/onward unset 字段 … |
删除指定配置项,采用下层值或默认值 |
/onward --help |
查看完整用法;单个动作的帮助用 /onward <动作> --help |
修改或查看指定层时,把 --scope 写在动作前,例如 /onward --scope project set maxFailures=5。status、actions 不接受 --scope
解析规则
命令顺序固定,支持以下四种形式:
/onward
/onward --help
/onward --scope <global|project>
/onward [--scope <global|project>] <动作> [动作参数] [--help]
前两种打开默认菜单或显示总帮助,第三种打开对应作用域的配置菜单。带作用域查看帮助时必须明确动作,例如 /onward --scope project set --help;/onward --scope project --help 报错
- 一条命令只能占一行,以空格或 Tab 分隔,允许首尾及连续空白。动作、字段、作用域和
rules均区分大小写,不支持缩写、引号或转义。 --scope只能出现一次,只接受--scope global、--scope project,不接受--scope=project或动作后的作用域选项。--help只能出现一次,且必须是最后一个独立参数;不支持-h、help动作和--结束符。status/actions/on/off/reset不接受位置参数;show只接受可选的rules;set、unset分别要求至少一个赋值或字段名。set的每个参数必须是完整的字段=值,恰好一个等号、两侧非空;不能拆成字段 = 值。unset只接受裸字段名。重复字段均报错,即使值相同。- 帮助只豁免
set/unset完全没填参数的情况。已填写的参数仍须合法:set --help显示帮助,set maxFailures=0 --help报错。 - 结构错误从左到右只报告第一个;结构通过后汇总未知字段、重复字段、非法值及作用域限制。帮助和报错都不写配置、不重载文件、不改变恢复状态。
Tab 补全沿用同一套校验:当前参数可以尚未输入完整;前面已由空格或 Tab 结束的参数若有错误,先修正才会提供后续候选。输入 --help 后不再补全
❓ 常见问题
已启用,但没有自动恢复
先用 /onward show rules 确认有启用的规则,再用 /onward status 查看停止原因。没有匹配规则、配置无效、用户主动取消或已有排队消息时不会插入恢复。空回复是正常结束但没有文字和工具调用,正常工具轮不会触发空回复规则
修改配置后仍使用旧值
用 /onward show 检查字段来源,项目配置可能覆盖全局配置。命令修改立即作用于当前运行;手工编辑文件后用 Pi 的 /reload。如果显示“未保存”,先处理写入问题再重试,重载会丢弃这部分内存修改
提示没有可用的任务提示词
{taskPrompt} 需要已接收的任务文本和可确认的来源。缺少来源记录或排队消息来源不明确时,onward 会停止,避免重发错误任务。重新发送人工任务后再继续;只需要发送固定文本时,可以把 prompt 写成 继续