pi-relay-switch
v0.1.1
Published
Manage multiple OpenAI/Anthropic-compatible API relays in pi: switch relays, pull model lists, manage API keys, and wire thinking levels (shift+tab) through to the relay.
Maintainers
Readme
pi-relay-switch — 第三方中转站管理插件
为 pi 提供多中转站(API Relay)管理:切换中转站、拉取模型列表、管理 API Key,并把推理档位(thinking level)真正打通到中转站。
English docs: README.md
特性
- 一个命令管所有:
/switch覆盖添加 / 删除 / 更换中转站 - 权威模型元数据:从
/models响应读取supports_reasoning/supports_vision/context_length/ 定价,不靠猜 - 推理档位打通:支持推理的模型自动带上
reasoning_effort配置,shift+tab循环档位真实生效 - 可视化反馈:启动时编辑器上方常驻中转站列表 widget(含状态、模型数、当前模型)
- 旧配置迁移:首次运行自动从
models.json迁移 providers,不丢历史配置 - 兼容 OpenAI 兼容(
/v1)与 Anthropic 原生(/v1/messages)两类接口
安装
npm 安装(推荐)
pi install npm:pi-relay-switchgit 安装
pi install git:github.com/<你的用户名>/[email protected]手动拷贝(开发调试)
插件即目录,直接放在 pi 的扩展目录:
~/.pi/agent/extensions/pi-relay-switch/
├── index.ts # 命令入口 / UI
├── config.ts # 配置读写 / 迁移
├── detect.ts # 连通性检测
└── models.ts # 模型元数据提取 / 配置推断修改代码后重启 pi(或 /reload)生效。
快速上手
/switch # 操作菜单:更换 / 更新模型列表 / 添加 / 删除
/switch add # 直接添加中转站(交互式:类型 → Base URL → API Key)
/switch remove <id> # 直接删除中转站
/switch refresh [id] # 重新拉取中转站的模型列表(多站无 id 时弹选择器)
/switch my-relay # 直接更换到该中转站(随后弹出模型列表确认模型)命令参考
/switch — 更换 / 更新 / 添加 / 删除
| 输入 | 行为 |
| --- | --- |
| /switch | 打开操作菜单:更换中转站 / 更新模型列表 / 添加中转站 / 删除中转站,选中后进入对应流程 |
| /switch <id> | 直接更换到该中转站(如 /switch my-relay),随后弹模型列表确认/换模型(🧠 推理标记 + 上下文窗口) |
| /switch refresh [id] | 重新拉取中转站的 /models 列表并刷新缓存元数据;展示新模型列表(enter 切换、不二次弹窗)。不写 id 且多站时弹选择器 |
| /switch add | 交互式添加中转站(类型 / Base URL / API Key / 显示名),添加后检测并可选立即更换 |
| /switch remove <id> | 删除中转站(交互式确认,删除当前站会清空默认设置);不写 id 则弹选择器 |
接口类型选择(添加时第一步):
| 类型 | 协议 | 请求头 | 适用场景 |
| --- | --- | --- | --- |
| OpenAI 兼容 (/v1) | Chat Completions | Authorization: Bearer | 绝大多数中转站/聚合站(默认选这个) |
| OpenAI Responses (/v1/responses) | Responses API | Authorization: Bearer | 中转站支持 Responses 协议、需要原生能力(web search 等)时 |
| Anthropic 原生 (/v1/messages) | Anthropic Messages API | x-api-key + anthropic-version | 中转站原生转发 Claude 原始接口时 |
选错类型会在检测阶段暴露(401 认证头不对 / 404 端点不存在),删掉重加即可。
参数补全:第一参数同时补全子命令和中转站 id(如输入
/switch my直接补全my-relay)。 选择器支持打字即时过滤:打开选择器后直接输入字符即可前缀过滤(如输入deep只剩 deepseek 模型),backspace删除过滤词,esc先清空过滤再关闭。
快捷键
| 快捷键 | 行为 |
|---|---|
| ctrl+shift+r | 快速切换中转站(打开选择器,单站时直接切换) |
小便利
- 只有一个中转站时,
/switch/ctrl+shift+r直接更换,不弹选择器 - 模型切换自动同步:用 pi 的
/model/ctrl+l切换模型后,插件自动更新对应中转站的lastModel(当前站跟随切换到的模型所属中转站),列表 widget 实时刷新
交互流程
切换:选站 → (模型缓存为空时自动检测+拉取)→ 注册 provider → 弹模型列表(预选中上次用的模型,enter 确认 / esc 保持默认)→ 写入 relays.json + settings.json → 通知当前推理档位。
刷新:拉取 /models → 更新缓存元数据 → 弹模型列表 → 选中即切站(不重复弹模型选择)。
删除当前站:自动注销 provider 并清除 settings.json 的默认 provider/model。
推理档位(thinking level)
pi 内置 shift+tab 循环推理档位:off → minimal → low → medium → high → xhigh → max。
插件做的事:
标记推理模型:优先读取
/models响应里的supports_reasoning字段(权威);中继不提供该字段时,按模型 id 启发式兜底(deepseek / kimi-k2 / glm-4.5+ / qwen3 / minimax-m2 / gemini-2.5+ / claude-4+ / o1-o4 / reasoner·thinking 等)打通发送:推理模型(OpenAI 兼容类型)自动附加:
compat: { supportsReasoningEffort: true }, thinkingLevelMap: { minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: "high", // 收敛到 high,避免中继拒绝 max: "high", }—— 没有这层配置,pi 的 OpenAI 兼容适配器不会把
reasoning_effort发给中转站。可视化:模型选择列表里带能力标记——🧠 = 支持推理档位(shift+tab),右侧显示上下文窗口(如
1M ctx);切换成功通知带上当前档位(如推理档位: high)。
手动覆盖
若某模型被误判(中继拒绝 reasoning_effort 报 400),在 relays.json 里对该模型条目设置手动覆盖 reasoning:
{ "id": "some-model", "reasoning": false }手动覆盖优先于 /models 权威数据,刷新模型列表时会被保留、不会被冲掉。
字段分工:
reasoning= 手动覆盖(你写的);supportsReasoning=/models拉取的权威数据(刷新时自动更新)。
模型元数据
添加/更换中转站时,会从 /models 响应提取并缓存每个模型的:
| 字段 | 来源 | 用途 |
| --- | --- | --- |
| supportsReasoning | supports_reasoning | 是否支持推理档位(shift+tab);reasoning 手动覆盖优先于它 |
| vision | supports_vision | 是否支持图片输入 |
| contextWindow | context_length | pi 的上下文窗口统计 |
| maxTokens | max_completion_tokens | 最大输出 token |
| cost | *_price_per_million | pi 的成本统计(元/百万 token) |
中继不提供这些字段时回退到保守默认值(推理按 id 启发式,价格记 0,上下文 128k)。
配置文件 relays.json
位于 ~/.pi/agent/relays.json,结构示例:
{
"version": 1,
"currentRelay": "my-relay",
"relays": [
{
"id": "my-relay",
"name": "my-relay",
"type": "openai",
"baseUrl": "https://api.example.com/v1",
"apiKey": "sk_xxx",
"headers": { "User-Agent": "MyClient/1.0" },
"models": [
{
"id": "gpt-4o-mini",
"supportsReasoning": true,
"contextWindow": 1000000,
"cost": { "input": 1, "output": 2, "cacheRead": 0.2, "cacheWrite": 0 }
}
],
"status": "ok",
"lastModel": "gpt-4o-mini",
"latencyMs": 142,
"lastChecked": 1786700250424
}
]
}type:openai(OpenAI 兼容/v1)、openai-responses或anthropic(Anthropic 原生/v1/messages)headers:可选,覆盖默认请求头(如某些站要求特定 User-Agent)models[].supportsReasoning:来自/models的权威数据,刷新时自动更新models[].reasoning:可选手动覆盖推理能力判断(优先于supportsReasoning,刷新保留)lastModel:该站上次使用的模型,切换时优先恢复
从 models.json 迁移
首次运行(relays.json 不存在或为空)且 models.json 里有 providers 时,自动迁移:
- 每个 provider 转成一个 relay(按
api字段判断类型) settings.json的defaultModel匹配到则记为lastModel- 迁移完成后清空
models.json的 providers,避免重复注册
安全注意事项
⚠️ API Key 以明文存储在
~/.pi/agent/relays.json(新文件按0600权限创建)。切勿提交该文件——本仓库的.gitignore已默认忽略。
⚠️ pi 扩展拥有完整系统权限、可执行任意代码。 只安装你信任来源的包,安装第三方扩展前请审阅源码。
注意事项 / FAQ
- 改代码要重启 pi:扩展是运行时加载的
- 启动自动恢复:插件在加载阶段(早于会话开始)就注册当前中转站,配合
settings.json的defaultProvider/defaultModel自动恢复上次的模型,不会出现No models available警告(若注册提前到工厂阶段之前还没生效,说明扩展缓存未刷新,重启一次即可) - reserved 关键字冲突:若中转站 id 恰好叫
add/remove等子命令关键字,优先走管理子命令(id 由域名生成,实际几乎不会撞上) - 检测超时:默认 8s,超时按「不可达」处理(可 esc 取消)
- API Key 失效:检测到 401/403 标记为「API Key 无效」,不中断其他站
- 模型列表为空:更换时若拉不到模型,会用
lastModel或第一个模型;都没有则提示稍后重新/switch更换
