Skip to content

版本策略

本库遵循语义化版本

下游是多个独立发版的桌面应用 —— 改一个 pub 字段就可能 break 它们全部。 所以每次改动前先对照本表定版本位。

版本位判定

改动版本位说明
改模型 id / 加 provider / 改 base_urlpatch纯数据更新,不动 API 形状
Kind 枚举值minor#[non_exhaustive] 保证下游 match 不 break
给 struct 加字段minor同上
加公开函数 / 方法minor
改 / 删 struct 已有字段major破坏性
改函数签名major
preset.keymajor🔴 见下
ai.profile规范字段名major见下
reqwest 大版本升级major🔴 见下

三个特别危险的改动

1. preset.key 是存量配置的锚

用户已保存的配置靠 key 找回对应的预置模板(infer_preset_key 的返回值就是它)。

改名会让所有老配置掉进「自定义端点」—— 用户看到的是 "我配好的服务商突然不认识了",而且数据看起来还在,只是不被识别了。

要改名时:保留旧 key 作为别名,而不是直接替换。

别把 key 当展示文本

它不是给人看的,展示用 label。改 label 是 patch,改 key 是 major。

2. ai.profile 的字段名只增不改

协议是跨应用契约,且别人的工具也可能在生成它

改动版本位
解析端加别名(宽进)patch
加可选字段minor
生成端改规范拼写major —— 且应当有极强的理由
删字段 / 改字段语义major

版本号 v 的兼容规则:只拒绝更高版本。低版本能被高版本实现读懂 (字段只增不改),拒绝低版本会把老软件分享的配置挡在外面。

3. reqwest 的大版本在公开 API 里

Verifier::from_builderreqwest::ClientBuilderlib.rs 重导出了 reqwest。 后果是:

改动版本位
reqwest 0.12.x0.12.ypatch
reqwest 0.120.13major 🔴

这是刻意付的代价。不重导出的话,下游用自己依赖树里的 reqwest 建 builder, 版本一旦不同就编译失败,报错还是 expected ClientBuilder, found ClientBuilder 这种看不懂的形式。

宁可把耦合写进版本号,也不要让下游撞上那种错误。

为什么不做一个 ProxyConfig 中间层

考虑过,否决了:代理配置各家差异极大 —— sigil 用的是 reqwest::Proxy::custom(闭包) 按 URL 动态路由,任何简化的中间层都覆盖不了, 最后还是要开一个 builder 级的逃生口。既然逃生口必然存在,不如直接让它是主路径。

#[non_exhaustive] 的用法

所有公开 struct / enum 一律加 —— 这是把「加字段」从 major 降到 minor 的唯一办法。 第一版就要加,事后补本身就是破坏性变更。

🔴 但入参类型必须同时提供 builder

#[non_exhaustive] 让外部 crate 不能用字面量构造该类型(E0639)。

类型定位例子做法
出参(下游只读)ProviderPresetVendorVerifyOknon_exhaustive 就行
入参(下游要构造)ServiceConfig必须配完整的链式 builder

否则加了 non_exhaustive 等于让它无法被使用。

这条是实测踩出来的:ServiceConfig 最初只有 new() 没有 with_*(), xtask 作为外部 crate 编译直接报 E0639。

单元测试抓不到这类问题

它们在 crate 内部,不受 non_exhaustive 限制 —— 写得再多也照样全绿。 tests/ 下的集成测试是唯一防线,仓库里有两条专门守这个。

发版前检查

bash
cargo test -p ai-profile                                    # 默认 feature
cargo test -p ai-profile --no-default-features --features chat
cargo test -p ai-profile --features client
cargo test --workspace --all-features
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo fmt --all --check
cargo xtask gen-docs                                        # 确认 providers.md 无变化

cargo test --workspace 不能代替前三条

xtask 依赖 client feature,workspace 级命令会触发 feature unification, 让 ai-profile 永远带上 client —— 「不带 client 能否编译」那条就永远测不到。

这也是实测踩出来的:开不开 --features client 跑出来都是同样的测试数, 看起来一切正常,实际上有一整个形态从没被验证过。

cargo xtask probe(探活各家端点)是人工触发的季度体检, 不进发版流程,更不能进 CI —— 每次 PR 都打人家的接口既是滥用, 也会让 CI 随网络波动随机红。

当前状态

尚未发布到 crates.io。crates.io 的版本永久不可撤回0.1.0 一旦发出就占住了这个名字 —— 在第一个真实接入方跑通之前, API 形状还可能调整,现在发布只会制造需要长期背负的兼容包袱。

接入方式见安装与 feature

MIT 协议开源 · 文档同样欢迎 PR