一个 registry.json 如何支撑插件分发:CLIProxyAPI 插件商店的发布与校验实践
插件商店首先要解决交付问题
一个插件在开发机里能够加载,与用户从商店里能够稳定安装,是两件不同的事。后者涉及版本发现、平台匹配、下载完整性、解压路径和更新说明。CLIProxyAPI-Plugins-Store 选择用一份轻量注册表组织这些信息,把插件发行包保留在作者各自的仓库中。
本文根据公开 README 的注册表与发行规范,讨论这种组织方式适合什么场景、插件作者应怎样发布,以及用户安装失败时如何逐步定位。个人分支地址为 daodeqing/CLIProxyAPI-Plugins-Store,上游为 router-for-me/CLIProxyAPI-Plugins-Store。下文介绍的是上游生态规范与个人分支中的公开说明,不将整个商店或宿主设计归为个人原创成果。
一、注册表只负责发现,发行仓库负责交付
README 明确说明,这个仓库主要维护 registry.json;插件二进制、校验和与发行说明应放在插件作者自己的 GitHub 仓库。商店因此不需要随着每个插件升级而堆积大量二进制文件,也不必把所有插件的构建流水线集中维护。
可以把链路理解为:注册表告诉宿主“插件是谁、发行仓库在哪里”;宿主查询发行仓库的最新 Release,取得版本和当前平台安装包;安装器再按规范校验、解压和加载。本文是交付流程解释,具体宿主行为仍应以当前版本实现为准。
这种拆分也带来依赖:注册表正常不代表作者仓库的 Release 完整,GitHub API 查询失败也不一定是插件损坏。排障必须沿着发现、版本查询、资产匹配、下载校验、安装加载分别检查。
二、registry.json 中哪些字段真正重要
根对象需要 schema_version 为 1,并包含 plugins 数组。每个插件的必填字段包括 id、name、description、author、repository。logo、homepage、license、tags 属于可选信息。version 字段是遗留显示回退:最新发行版本查询失败时可以辅助展示,但不能把修改这个字段当作已经发布更新。
下面为说明字段关系的虚构示例,不代表实际登记的插件,也不是可直接下载的现有项目:
{
"schema_version": 1,
"plugins": [
{
"id": "sample-provider",
"name": "示例连接插件",
"description": "展示注册表字段关系",
"author": "example-author",
"repository": "https://github.com/example-author/sample-provider",
"license": "MIT",
"tags": ["provider"]
}
]
}
id 要符合宿主插件标识规则:以 ASCII 字母或数字开头,后续仅使用 ASCII 字母、数字、点、下划线或连字符,总长最多 128 个字符,而且不能重复。repository 必须是严格的 GitHub 仓库地址形式,不能写成文件链接、Release 详情页或随意的镜像下载地址。
这些约束看似繁琐,却能让版本查询、资产匹配与本地目录命名具有稳定依据。尤其是 id,注册表、安装包文件名和压缩包里的动态库需要围绕同一个标识保持一致。
三、版本号要在三个位置对上
公开规范要求,插件仓库最新 Release 使用 v 开头的点分数字标签,例如 v0.1.0;资产文件名中的版本则去掉前导 v。这里容易把仓库名、插件 id、Release 标签和资产名称混用,产生“页面看起来有版本,客户端却找不到包”的问题。
以虚构插件 sample-provider 的版本 0.1.0 为例:
Release 标签:v0.1.0 Windows x64 包:sample-provider_0.1.0_windows_amd64.zip Linux x64 包:sample-provider_0.1.0_linux_amd64.zip macOS ARM 包:sample-provider_0.1.0_darwin_arm64.zip 校验文件:checksums.txt
平台包必须覆盖实际声明支持的目标。Windows ARM64 与 AMD64、macOS Intel 与 ARM 都不是同一种目标,不能只把文件名改一改就声称完成适配。若某个平台没有构建产物,文档应清楚说明,避免用户安装后才发现架构不匹配。
日常升级通常只需要作者发布新的合规 Release,不需要每次去注册表改版本。这让维护者专注登记信息,作者专注各自的构建与发行。与此同时,“最新版本”具体指向什么发行对象也应保持可预期,预发布版本、草稿 Release 或缺失资产均需要单独核对。
四、ZIP 根目录规范为何值得坚持
每个平台压缩包的根目录应直接包含目标动态库:Windows 为 sample-provider.dll,Linux 为 sample-provider.so,Darwin 为 sample-provider.dylib。README 说明安装器会拒绝嵌套动态库、绝对路径、zip-slip 路径、名称不匹配和多个动态库等情况。
常见错误是把整个构建输出文件夹压进去,形成 package/bin/sample-provider.dll。人能在解压后找到文件,安装器却没有义务猜测哪个子目录才是入口。直接使用明确根目录结构,可以减少平台差异和错误恢复分支。
路径检查也涉及安全。例如包含 ../ 的压缩包条目可能试图写出目标安装目录,绝对路径则可能绕开预期的解压位置。本文只是说明规范的保护目的;校验规则存在,不等于已经对所有压缩工具、编码方式和平台边界完成安全审计。
五、SHA-256 能解决什么,不能解决什么
每个 Release 需要 checksums.txt,采用 sha256sum 格式,将完整 SHA-256 与准确的 ZIP 文件名对应:
此处为格式示意,哈希应由实际最终 ZIP 计算: <64位SHA-256> sample-provider_0.1.0_windows_amd64.zip
顺序应当是构建、生成最终 ZIP、计算哈希、上传资产,再验证下载后的结果。压缩包重新打包后,即使动态库内容没变,ZIP 字节也可能变化,旧校验值就不再适用。因此不要在计算校验和后又追加文件或重新压缩,却忘记更新 checksums.txt。
SHA-256 主要检查下载文件是否与发布者给出的字节一致,不独立证明发布者可信。若攻击者同时控制发行包和校验文件,两者仍可能匹配。供应链的进一步保障可以包括签名、构建来源证明、最小权限与人工审核,但这些属于进一步设计,不能写成此注册表已经提供的全部能力。
同样,源码许可证与二进制运行安全是两条不同的判断线。许可证说明使用与分发条件,不能替代运行前的来源确认、宿主兼容性检查与必要的隔离。
六、插件作者的一套发布顺序
- 确定稳定的插件 id、仓库地址与许可证,先检查是否与既有条目冲突。
- 按真实支持的操作系统和架构构建动态库,核对入口名称与宿主 ABI 兼容性。
- 分别生成平台 ZIP,检查根目录动态库名称与目录结构。
- 对最终 ZIP 计算 SHA-256,生成与资产名称完全一致的 checksums.txt。
- 发布符合规范的 Release 标签,上传包与校验文件,补充变更说明。
- 从实际发行页重新下载,核对校验和与安装结果,避免只检查流水线本地输出。
- 提交注册表 PR,附仓库、版本、资产与校验文件存在的证据,以及新增能力说明。
README 建议新增插件 PR 原则上只更新 registry.json,除非文档本身也确需澄清。这样评审者可以集中检查登记信息,不必在一个注册 PR 中同时审查大量无关业务改动。
需要区分 Actions artifact 和 GitHub Release asset。构建流水线产生可下载 artifact,不能自动替代符合商店发现规则的 Release 安装包;用户是否能通过商店取到正确资产,应在发行完成后单独验证。
七、用户安装失败时怎么查
第一步看插件是否被发现。若完全没有条目,检查注册表格式、重复 id 和当前客户端使用的注册来源;不要先去重装所有插件。
第二步看版本查询。条目存在但没有发行版本时,检查 repository 地址、Release 标签与网络/API 状态。version 回退只可能改善显示,不能凭空补出缺失的发行包。
第三步看平台匹配。版本可见却提示缺包时,逐项对照 id、版本、goos、goarch 和 ZIP 后缀。第四步看完整性与结构:校验不一致先停止安装,结构拒绝则核对根目录与库名。第五步才是运行时:安装成功后加载失败,需要查看宿主版本、依赖库、架构与插件日志。
这套顺序的价值在于缩小问题范围。下载失败、ZIP 校验失败和动态库初始化失败处在不同阶段,反复删除配置或替换密钥通常无助于解决前两类问题,反而可能丢失原本有效的设置。
八、轻量商店的维护成本在哪里
仓库小并不代表维护成本为零。作者仓库迁移、发行资产误删、标签格式改变、许可证遗漏,以及宿主 ABI 更新,都可能让旧登记失效。较稳妥的协作方式是保持标识稳定、发行说明明确,并让用户能找到问题反馈入口。
升级前是否备份插件数据、失败后怎样回退,也应由具体插件与宿主能力共同决定。注册表 README 没有承诺所有插件都具有自动回滚或沙箱隔离,因此介绍时不能把“插件化”直接等同于“彼此完全安全隔离”。动态库加载到宿主后,通常需要更谨慎地对待可信来源与生命周期管理。
对一个社区生态而言,最实用的改进往往是减少含糊:哪个版本、哪个平台、哪个资产、哪个校验值、哪个错误阶段。把这些信息形成稳定约定,能够让作者、维护者与用户在同一条可检查的交付链路上协作。
参考资料与来源说明
本文依据 2026 年 10 月 23 日可见的公开 README 整理,未在本次操作中构建或安装示例插件。示例名称、仓库与哈希占位均用于解释格式,不构成实际发行证明。
- 点赞
- 收藏
- 关注作者
评论(0)