@hu3rror/pi-failover
v0.5.0
Published
Automatic API credential and provider failover for Pi coding agent.
Maintainers
Readme
pi-failover
面向 Pi coding agent >=0.84.2 的自动凭证与 provider 故障切换扩展。
pi install npm:@hu3rror/pi-failoverpi-failover 用于在当前凭证或 provider 不可用时,继续让 Pi 会话向下执行。它直接复用 Pi 现有的 auth.json,并增加两个扩展字段:backupKeys(API-key provider 的备用 key)与 isFallback(把某 provider 标记为 provider 级切换的合格目标)。旧拼写 key-backup 在读取时仍会被识别。
关于本分支(fork)
pi-failover 采用 MIT 许可,原作者为 gooyoung。
本仓库是其独立维护、独立发布的 fork,npm 分发名为
@hu3rror/pi-failover;运行时行为与 auth.json 约定保持不变。
快速开始
1. 安装扩展
pi install npm:@hu3rror/pi-failover2. 修改 auth.json
pi-failover 只读取 Pi getAgentDir() 下的 auth.json,默认位置通常是:
~/.pi/agent/auth.json如果设置了 PI_CODING_AGENT_DIR,仍然沿用 Pi 自身的 agent 目录解析规则。
保留 Pi 原有的主凭证,并在需要同 provider 备用 key 的 API-key provider 上增加 backupKeys 字段。若希望当前 provider 失败时可以切换到某个 provider,请给它加 isFallback: true。backupKeys 既可以是一个字面量、非空字符串,也可以是由字面量、非空字符串组成的非空数组:
{
"anthropic": {
"type": "api_key",
"key": "primary-api-key",
"backupKeys": ["backup-api-key-1", "backup-api-key-2"],
"isFallback": true
},
"openai-codex": {
"type": "oauth",
"access": "...",
"refresh": "...",
"expires": 1767225600000
}
}现有字符串形式等价于只含一项的数组,数组中的凭证按书写顺序尝试。如果数组为空或任一元素无效,整个备用字段都会被忽略,该 provider 仍只能使用主凭证。旧拼写 key-backup 仅在 backupKeys 缺失时才会被读取;两字段同时存在时,backupKeys 优先。
isFallback 默认为缺省(等价于 false):默认情况下 pi-failover 只会在当前 provider 内重试 key,之后把失败交还给 Pi 的内置重试,绝不切换 provider。要给一个或多个 provider 加 isFallback: true 才会启用 provider 级切换。
3. 验证故障切换已启用
启动 Pi 后执行:
/failover status该命令只显示脱敏后的运行时状态,不会输出原始凭证值。
当当前 key 在一次用户请求中遇到已接管的故障时,pi-failover 会按情况执行:
- 切到同一 provider 的下一把备用 key
- 在当前 provider 的所有备用 key 用尽之后,切到标记了
isFallback: true的 provider;只要没有任何 provider 被标记,就永远不会发生 provider 级切换 - 成功切换后自动重试同一次用户请求
- 当不存在可用的 fallback provider 时,把失败交还给 Pi 的内置重试
- 当所有 failover 选项都耗尽时,只显示最后一次 provider 错误
中间 provider 错误会被替换为隐藏的续跑消息,因此用户无需再次发送相同内容。TUI 和 RPC 模式仍会为每次实际生效的凭据或 provider 切换显示一条脱敏警告。
以下是切换到备用凭证及切换 provider 后显示的警告示例:


如果所有 failover 选项已经耗尽,但 Pi 仍有内置自动重试尚未执行,扩展会保留最后一个实际使用的凭证,直到该重试结束。重试成功时继续保留该凭证;最终仍失败时,扩展才恢复其运行时 override,并只报告一次 exhausted。这样可以避免 Pi 的重试意外切回已经失败的主凭证。
配置说明
pi-failover不会读取或写入keyrouter.json。backupKeys表示同一 provider 的一把或多把备用 key,不表示 provider 级切换。旧拼写key-backup在backupKeys缺失时仍会被识别。- provider 的切换顺序由
auth.json顶层字段的插入顺序决定。只有标记为isFallback: true的 provider 才是切换目标;未标记的 provider 永远不会被切换过去。 - OAuth 条目可以标记为切换目标,但不支持备用字段。
backupKeys中的每个值都按字面量字符串处理,不支持从环境变量或命令动态展开。- Pi 的
/login流程可能会重写auth.json并移除未知扩展字段,因此重新登录后可能需要再次补上backupKeys与isFallback。
故障切换规则
同一次用户请求内,失败的凭证或 provider 会先被禁用或进入冷却,再执行隐藏续跑。收到成功的 2xx 响应后,当前凭证或 provider 会被标记为健康。
| 故障类型 | pi-failover 的处理方式 |
| --- | --- |
| 401 / 403 | 将当前凭证在本次会话中标记为不可用,切换到下一把备用 key;key 用尽后切到标记了 isFallback 的 provider,然后重试同一次请求。没有标记任何 fallback provider 时,失败交还给 Pi 自己的重试。 |
| 429 | 按 Retry-After 冷却当前凭证;如果没有该响应头,则冷却 60 秒,切换到下一把备用 key 后重试。备用 key 全部用尽后,除非存在标记了 isFallback 的 provider,否则失败交还给 Pi 的内置重试。 |
| 529 或 overloaded 响应 | 按 Retry-After 冷却当前 provider;如果没有该响应头,则冷却 30 秒,切到标记了 isFallback 的 provider 后重试。 |
| 500、502、503、504、网络错误、超时 | 将当前 provider 冷却 30 秒,切到标记了 isFallback 的 provider 后重试。 |
| 其他故障 | 保持 Pi 原有的错误处理逻辑,不额外接管。 |
发生 provider 切换时,pi-failover 会优先保留当前 model ID;如果目标 provider 没有该 model,则退回到该 provider 的第一个可用 model。扩展内部会调用 Pi 的 setModel(),因此新的默认 model 会持续生效;后续不会自动切回原 provider。
状态和警告信息只显示脱敏后的凭证槽位:主凭证为 primary,第一把备用凭证为 backup,后续依次为 backup-2、backup-3……
provider 级切换是显式开启的。只有当某 provider 的 credential 记录在 auth.json 中带有 isFallback: true 时,它才会成为切换目标;没有任何标记 provider 时,pi-failover 绝不切换 provider,而是在当前 provider 的备用 key(如有)用尽后把失败交还给 Pi 自己的重试(settings.retry)。OAuth provider 也可以被标记,但它们永远不会持有 backupKeys。
与 Pi 的 retry 设置配合
pi-failover 与 Pi 的内置重试协作,而不是取代它。推荐的 settings.json 取值:
| 设置项 | 推荐值 | 原因 |
| --- | --- | --- |
| retry.enabled | true | 作为 pi-failover 刻意不接管的失败(例如没有标记任何 fallback provider 时)的兜底。 |
| retry.maxRetries | 3(默认值) | 更大的预算只会在所有 failover 选项耗尽后拖延最终错误出现的时间。 |
| retry.provider.maxRetries | 0(默认值) | SDK 层的重试会在 Pi 看到错误之前把失败吞掉,failover 将永远观察不到该错误。 |
| retry.provider.timeoutMs | 例如 60000 | SDK 默认是 1 小时;provider 挂起时,failover 的网络故障分类会被阻塞同样长的时间。 |
当没有标记任何 fallback provider、且当前 provider 的备用 key(如有)已用尽时,pi-failover 不替换错误消息,Pi 的内置重试会按自己的指数退避(retry.baseDelayMs)执行。存在标记了 isFallback 的 provider 时,pi-failover 会立即切换 key 或 provider 并重试,随后把控制权交还给 Pi。
命令
/failover login:交互式地为api_keyprovider 添加备用 key;不带参数时从现有 provider 中选择,也可直接指定 provider(/failover login <provider>,支持自动补全);key 在输入框中录入(绝不通过命令行参数传入),经确认后写入auth.json并立即重建 failover catalog,新 key 立即可用/failover status:查看脱敏后的故障切换状态/failover fallback <provider> [off]:把某 provider 标记为 fallback 目标(isFallback: true),或用off清除标记;provider 名支持自动补全,该标记非机密,可直接作为命令行参数传入,写入成功后立即重建 catalog/failover reload:恢复扩展接管的 override,然后重新读取auth.json
输出模式
| 模式 | 通知行为 | | --- | --- | | TUI | 显示通知 | | RPC | 显示通知 | | JSON | 不显示 UI 通知,但仍会执行透明重试 | | print | 不显示 UI 通知,但仍会执行透明重试 |
迁移说明
如果从 ~/.pi/keyrouter.json 迁移,需要把每个 provider 的主凭证搬到 Pi 的 auth.json 中,再把一把备用 key 字符串或按顺序排列的备用 key 数组写入 backupKeys。如需控制 provider 切换顺序,可直接调整 auth.json 顶层条目的顺序。
把希望作为切换目标的 provider 标记为 isFallback: true;未标记的 provider 永远不会被切换过去。
当前没有双读迁移模式,pi-failover 只读取 auth.json。
安全说明
- 将
auth.json视为敏感文件。 - 不要提交凭证内容。
- 应限制文件访问权限。
pi-failover的状态和错误信息默认保持脱敏。
开发
npm test
npm run typecheck
npm run audit
npm pack --dry-runnpm run audit 对官方 npm registry 检查仅用于开发的依赖树。发布包唯一的运行时依赖是 proper-lockfile,用于守卫 auth.json 的写入。
