npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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.

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-switch

git 安装

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。

插件做的事:

  1. 标记推理模型:优先读取 /models 响应里的 supports_reasoning 字段(权威);中继不提供该字段时,按模型 id 启发式兜底(deepseek / kimi-k2 / glm-4.5+ / qwen3 / minimax-m2 / gemini-2.5+ / claude-4+ / o1-o4 / reasoner·thinking 等)

  2. 打通发送:推理模型(OpenAI 兼容类型)自动附加:

    compat: { supportsReasoningEffort: true },
    thinkingLevelMap: {
      minimal: "minimal", low: "low", medium: "medium", high: "high",
      xhigh: "high",   // 收敛到 high,避免中继拒绝
      max: "high",
    }

    —— 没有这层配置,pi 的 OpenAI 兼容适配器不会把 reasoning_effort 发给中转站。

  3. 可视化:模型选择列表里带能力标记——🧠 = 支持推理档位(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 更换

License

MIT