pi-ccswitch-auto-switch
v0.3.15
Published
Provider-first automatic model failover extension for Pi and CC Switch
Maintainers
Readme
Pi CCSwitch 自动故障转移
English: README.md
当 CC Switch 管理 Pi 的 Provider 时,为 Pi 提供更稳健的模型自动故障转移。
它只观察 Pi 的真实请求,保存脱敏健康记录;仅在 TUI/RPC 交互会话中,才会把失败请求平滑切到健康模型。额度耗尽、凭据失效或限流等 Provider 级问题会直接熔断整个 Provider,不会连续尝试同一 Provider 下的多个兄弟模型。
功能
- 以 Pi 的有效模型注册表为准,不读取 CC Switch 数据库、Pi 认证文件或 API Key。
- 对认证、额度、账单和限流实施 Provider 优先熔断。
- 对 DNS、连接、服务端和流中断实施端点熔断。
- 模型不存在或参数不兼容时仅隔离该模型。
- 内容审查失败会学习模型系列约束(例如
glm-4.5、GLM-4.6同属glm),在本轮内容审查故障转移中避开整个受限系列。该约束仅保存在当前扩展实例的内存中,不写入共享健康状态;当前实例的session_start只清除自身约束,因为新 session 处理的任务不一定涉及审查内容,模型系列恢复可用,直到本 session 再次观察到内容审查拒绝。 - 候选模型先经过健康、故障域、审查系列、输入模态和上下文窗口硬过滤,再按跨 Provider、模型等价性、能力兼容和历史稳定性排序。
- 首响应 90 秒、流式停滞 120 秒看门狗。
- 指数退避、
Retry-After支持和跨进程 half-open 单探针租约。 - 原子持久化状态、错误脱敏和有上限的日志。
- Pi 紧凑状态栏与健康管理面板。
--print/ JSON 非交互运行只监控和记录,不会注入可能与进程退出竞争的新请求。pi-ccswitch-run使用单个 Pi RPC 会话完成无头自动故障转移,只输出最终成功模型的回答。
要求
- Pi
0.84.4或更高版本。 - 建议使用 CC Switch
3.20+,其已支持原生维护 Pi 模型配置。 - 本地开发和测试需要 Node.js
22.19+;Pi 运行插件本身不需要额外安装 Node。
配置
插件不需要任何用户配置:它只观察 Pi 的真实请求,读取 Pi 已暴露的模型元数据;从不读取 CC Switch 数据库、Pi 认证文件、API Key、Cookie 或 .env 文件,也从不写入 Pi 模型设置或 CC Switch 数据。
以下开关全部可选,且有合理默认值:
| 设置项 | 作用域 | 默认值 | 说明 |
| --- | --- | --- | --- |
| PI_CODING_AGENT_DIR | 扩展状态 | ~/.pi/agent | 健康状态、日志与失败报告的存放目录;仅在你迁移了 Pi agent 目录时需要,插件跟随 Pi 自身约定。 |
| PI_BIN | 仅 headless runner | PATH 中的 pi | 必须指向真实 pi 可执行文件。历史自引用值 pi-ccswitch-run 或 ccswitch-run 会警告并降级到 pi;其他非法命令仍按配置错误处理。 |
| CCSWITCH_ROUND_LIMIT_MS | 故障转移 | 480000(8 分钟) | 本轮故障转移的时间限制(毫秒)。窗口从本轮开始或最后一次成功切换起算;超过后停止切换并报告已试模型及最后错误。 |
| 模型 scope(/model 等) | 故障转移候选 | 全量注册表 | Pi 启用了 model scope 时,只在 scope 内模型间切换;否则使用全量注册表。状态栏会显示当前数据源。 |
| baseUrl 元数据 | 端点隔离 | provider key | 端点级平台隔离按 baseUrl 分组模型(由 CC Switch 3.20+ 提供);缺失时退化为 provider 级分组,仍然可用。 |
安装
通过 Pi Package 安装(推荐)
pi install git:github.com/JunyWuuuu91/pi-ccswitch-auto-switch该命令在 macOS、Linux 和安装了 Git 的 Windows 上均可使用。npm 版本发布后,也可以执行:
pi install npm:pi-ccswitch-auto-switch安装或更新后重启 Pi,或执行 /reload。后续更新 Git 版本可执行 pi update --extensions。
无头自动化调用
pi-ccswitch-run(runner.mjs)是独立于 Pi 扩展的 headless 调用入口:它启动一个 pi --mode rpc 会话,把一次请求自动切换到健康模型后只返回最终成功结果。它不在 pi install 的扩展加载路径里自动暴露给下游项目,需要单独安装。
在消费方项目内安装(推荐,保证 require.resolve 可解析)
pi install git:... 只把扩展装进 Pi 全局目录(~/.pi/agent/...),不会把它放进下游项目的 node_modules 解析路径。因此消费方代码里 require.resolve('pi-ccswitch-auto-switch/runner.mjs') 需要把本包安装进自己的项目依赖:
# 在消费方项目目录内执行
npm i github:JunyWuuuu91/pi-ccswitch-auto-switch
# 或从 npm registry 安装最新版
npm i pi-ccswitch-auto-switch@latest安装后 require.resolve('pi-ccswitch-auto-switch/runner.mjs') 会命中项目自身 node_modules,bin pi-ccswitch-run 也可直接调用。
版本锁定警告(0.x caret 陷阱)
npm 对 ^0.1.6 的 caret 语义只匹配 0.1.x,不会自动升到含 runner.mjs 的 0.3.x。如果机器上 ~/.pi/agent/npm/node_modules/pi-ccswitch-auto-switch 仍停留在 0.1.6(该版本无 runner.mjs、无 pi-ccswitch-run bin),重复执行 pi install 也不会升级。请手动升级 npm 侧版本:
cd ~/.pi/agent/npm && npm install pi-ccswitch-auto-switch@latest升级后确认 ~/.pi/agent/npm/node_modules/pi-ccswitch-auto-switch/runner.mjs 存在。也可以在扩展内执行 /ccswitch-doctor 检查 runner.mjs 是否可解析。
运行方式
pi-ccswitch-run --no-tools --no-context-files @prompt.md "请总结附件"runner 内部只显式加载本扩展并启动一次 Pi RPC;PI_BIN 应指定内部真实 pi。为兼容旧配置,PI_BIN=pi-ccswitch-run 或 PI_BIN=ccswitch-run 会输出警告并降级到 PATH 中的 pi,避免递归和长驻消费方连续失败;其他任意命令仍会被拒绝。默认总超时为 10 分钟,可用 --timeout-ms 调整。退出码:成功 0、候选耗尽 1、参数/RPC 配置错误 2、超时 124、中断 130/143。支持文本及 PNG/JPEG/GIF/WebP @文件,按签名识别图片并传入 RPC images;损坏/不支持的图片及其他二进制附件明确拒绝。单附件上限 20 MiB,最多 20 张图片;不支持 stdin。
正常使用 CC Switch 配置 Provider 即可;本插件不会修改 Pi 模型设置或 CC Switch 数据。
命令
| 命令 | 作用 |
| --- | --- |
| /ccswitch 或 /ccswitch status | 打开健康面板。 |
| /ccswitch help | 在 Pi 内显示命令帮助。 |
| /ccswitch refresh | 刷新 Pi 模型注册表和状态栏。 |
| /ccswitch reactivate <provider/model\|all> | 解除熔断,下一次真实请求验证恢复情况;保留历史。 |
| /ccswitch disable <provider/model> | 手动排除模型。 |
| /ccswitch reset <provider/model\|all> | 确认后删除相应健康历史;all 同时清除已学习的审查约束。 |
| /ccswitch-test | 仅检查候选发现,不切换模型。 |
| /ccswitch-doctor | 诊断 runner.mjs 可解析性和安装情况。 |
状态栏
CCS v0.3.5 ✓70/131 · ⏳61 · ⛔0 · 🔄3 · provider/model-idv0.3.5:当前安装的 CCSwitch 扩展版本。✓70/131:Pi 有效范围内共有 131 个去重后的provider/model组合,其中 70 个健康;重复的 scope 条目只计一次。⏳61:有 61 个模型正受模型、Provider 或端点自动冷却影响;一条 Provider 熔断记录可能同时影响许多模型。⛔0:没有被手动禁用的模型。🔄3:本次 pi session 成功切换的模型次数(衡量扩展有效程度,0 时也显示图标)。/new、/fork、/resume等新 session 开始时归零;但失败记录与冷却状态不重置(它们是物理事实,跨 session 保留)。累计切换数(state.switches)与最近 20 条切换日志会持久化到状态文件,可在/ccswitch面板和/ccswitch-test中查看。provider/model-id:当前实际生效的模型(provider/id,切换后立即更新,长名自动截断)。- 切换中出现
CCS ↻2 provider/model,表示这是本轮的第 2 次切换尝试。切换次数只受本轮时间窗口限制,不再有固定次数上限;只有当所有候选都尝试过仍无可用模型时才会判定本轮失败。
四个状态(健康/冷却/禁用/切换)即使为 0 也始终显示,便于确认扩展处于监控中;全部健康时仍显示零计数,例如 CCS ✓131/131 · ⏳0 · ⛔0 · 🔄0 · provider/model-id。通过 /ccswitch 或 /ccswitch-test 可同时查看 Pi 原始 scope 条目数、去重模型数、受影响模型数、底层熔断记录数、本 session 切换数与累计切换数。
切换成功后扩展还会通过 appendEntry 向会话注入一条 ccswitch-switch custom entry(不参与 LLM 上下文),触发 TUI 底栏重绘——这样 Pi 右下角的模型名显示也会同步为切换后的模型。RPC 模式还会发出协议版本为 1 的 ccswitch-complete 或 ccswitch-exhausted 终态 entry,供 runner 判定最终结果。
故障转移逻辑
插件会先等待 Pi 内置重试结束和会话恢复 idle,再进行切换。新的用户输入会使旧轮次的待切换任务失效,从而避免重复发送。
| 失败类型 | 熔断范围 | 初始冷却 |
| --- | --- | --- |
| 401、403、额度或账单问题 | Provider | 30 分钟 |
| 429 | Provider | 配额/余额正文(如 AccountQuotaExceeded)→ 30 分钟;否则优先使用 Retry-After,无则 5 分钟 |
| DNS、网络、408、5xx、流中断 | 端点 | 2 分钟 |
| 404、模型不存在、参数不兼容 | 模型 | 15 分钟 |
| 内容审查/敏感拦截 | 当前模型 + 模型系列约束 | 模型冷却 2 分钟;系列约束按 session 隔离(session_start 时清除) |
| 上下文溢出 | 仅本轮 | 无 |
冷却时间会指数增长但有上限。发生内容审查时,插件只在审查故障转移链中避开已标记系列,普通限流、网络或模型配置故障仍可选择这些模型。上下文溢出时只会选择上下文窗口更大的模型;带图片的请求只选择显式声明支持 image 的模型。无法归类的异常按单模型故障处理并正常切换。用户主动取消是唯一不会触发故障转移的异常终止;看门狗取消会记录为超时。
模态预检(OCR / 图片请求自动切换多模态模型)
Pi 在把请求发给 Provider 时,会根据当前模型的 input 能力静默处理图片:如果模型不支持图片(input 不含 image,即非多模态模型),Pi 会把图片替换成一段文本提示 (image omitted: model does not support images) 再发送——请求不会报错,因此普通的“失败后切换”永远不会触发,模型只会回答“看不到图片”,OCR 结果拿不到。
插件因此在发送前主动预检,不等失败:
- 用户输入带图片时(
input事件含images),如果当前模型不支持图片,立即切换到健康的多模态候选(input明确含image)再处理,图片被保留; - 工具执行返回图片时(如
read工具读取图片文件,工具结果含imagecontent),同样在下一轮 LLM 调用前切到多模态模型,确保图片不被剥除; - 候选只选明确声明支持图片的模型(
input含image);元数据缺失的模型不冒险选择; - 图片能力要求贯穿整个故障转移轮次,包括重试验证阶段工具返回图片以及此后的再次切换;
- 切换原因记为
modality,计入本 session 切换数与累计切换; - 如果没有可用的多模态候选,RPC 图片输入会返回 exhausted 终态并在发出剥图请求前停止;交互式 TUI 保持原有通知行为。
模态预检只在 TUI/RPC 交互模式下生效(与故障转移一致);print/json 模式只监控不切换。
数据与隐私
健康状态保存在 Pi agent 目录的 ccswitch-auto-switch-state.json。其中只有计数、时间、冷却信息和脱敏/截断的错误摘要;模型系列审查约束只保存在 session 内存中;插件不会访问凭据、Authorization 请求头、CC Switch 数据库或 Pi 的 auth.json。
开发
状态 schema 3 兼容加载 schema 2 的健康记录,将原有累计数保留为共同基线;每个写入实例独立计数,合并时不丢增量、不重复累计。旧版本无法读取 schema 3,新进程中的代码无法修复仍在运行的旧代码。**禁止 schema-2 与 schema-3 版本共用同一目录混跑。**升级时必须依次:① 退出所有使用同一 PI_CODING_AGENT_DIR 的旧 Pi 进程并停止相关定时 runner;② 在进程停止后备份 ccswitch-auto-switch-state.json;③ 升级使用该目录的所有安装;④ 仅启动升级后的进程。当前版本遇到不支持的 schema,或已观察到 schema 3 后又读到 schema 2 时,会拒绝写入、保留原文件,并在 ccswitch-auto-switch.log 记录原因。这不能撤销旧代码已经造成的破坏,因此必须执行上述停机升级步骤。人工启用/禁用按本地单调时间戳选择较新操作;时间戳完全相同时保守保留禁用(旧记录缺字段时也如此)。reset 标记阻止旧快照恢复已清除的记录。计数元数据随实际记录失败或切换的实例数增长。
npm install
npm run typecheck
npm testTypeScript 已显式列为开发依赖。npm test 开启 Node 原生 TypeScript 类型剥离,在 Node 22.19+ 上运行 health、integration、logic、runner 全部测试。测试使用 Node 内置测试运行器,覆盖失败分类矩阵、系列级审查避让、Provider 优先选择、输入兼容、冷却、状态持久化以及 Windows 路径。
可选任务复杂度
--task-complexity auto 根据任务指令、输入文字长度和图片数量估计推理强度:短文本使用 low;结构化摘要或图片使用 medium;至少 20,000 个字符、4 张图片或跨来源综合分析使用 high。也可显式指定 low|medium|high。这是确定性的任务估计,不是模型质量排名。
默认沿用 Pi 当前模型;需要健康或视觉候选时由 CCSwitch 切换。Pi 会按模型能力限制推理强度。显式 --thinking 优先;省略 --task-complexity 时保留现有推理行为。runner 不写入全局设置。
RPC 图片请求没有可选的视觉模型时返回 exhausted 终态,避免发送丢失图片的请求。交互式 TUI 行为保持不变。超过 1.5 MiB base64 的大图会通过已安装 Pi 的图片处理功能压缩后传入 RPC,保留原图;处理失败时明确报错。
