AI SDK 预发布周期(Pre-Release Cycle)完整指南:从创建维护分支到发布下一个大版本
2026/9/11 0:06:46 网站建设 项目流程

AI SDK 预发布周期(Pre-Release Cycle)完整指南:从创建维护分支到发布下一个大版本

【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai

导读

本指南基于 contributing/pre-release-cycle.md 展开,完整讲解 AI SDK(The AI Toolkit for TypeScript)如何围绕"大版本升级(Major Release)"组织一次预发布(beta)周期:从创建维护分支、进入 changeset 预发布模式、为新版 Provider 规范播种 v4 规格目录,到适配器与 mock 测试工具、文档站版本化部署,再到周期内的日常开发约定与收尾发布。读完本文,你将掌握在main分支上并行开发下一个大版本、同时为当前稳定版持续回传补丁的完整工程流程,并能对照仓库源码理解每个步骤背后的真实实现。


一、为什么需要预发布周期

AI SDK 的每一个大版本发布都会引入一个新的Provider 规范版本(provider specification version),例如 V3 到 V4。演进规范正是大版本发布存在的理由:它允许对 Provider 接口做出破坏性变更,同时为 Provider 作者提供清晰的迁移目标。

在仓库的 packages/provider/src/ 中,这一点体现得极为直观:以语言模型为例,packages/provider/src/language-model/ 下并排存在着v2v3v4三个版本目录,每个目录内的类型都通过specificationVersion字面量标明版本,例如 embedding-model-v3.ts 中readonly specificationVersion: 'v3',而 embedding-model-v4.ts 中则是'v4'

预发布周期解决的核心问题是双轨并行

  • main分支发布 beta 版本(例如ai@7.0.0-beta.1);
  • 一个维护分支(例如release-v6.0)接收回传(backport)的补丁并发布稳定版本。

这样既能让破坏性变更在main上持续推进,又不阻塞当前稳定版用户的紧急修复。


二、启动一个预发布周期

1. 创建维护分支

从当前mainHEAD 创建一个分支,让当前稳定版本可以继续接收补丁:

git checkout main git pull origin main git checkout -b release-v<current-major>.0 # e.g. release-v6.0 git push origin release-v<current-major>.0

仓库中的发布工作流 已经配置在release-v*分支上运行(branches: [main, release-v*]),因此无需修改任何工作流文件,维护分支上的合并会自动触发稳定版发布。

2. 在维护分支上设置 npm dist-tag

在新建的维护分支上,更新根目录package.json中的ci:release脚本,使其以版本专属的 npm dist-tag 发布。这一步防止维护版本抢占 npm 上的latest标签:

- "ci:release": "turbo clean && turbo build && changeset publish", + "ci:release": "turbo clean && turbo build && changeset publish --tag ai-v<current-major>",

例如,对于release-v6.0分支使用--tag ai-v6。直接将该改动提交并推送到维护分支。

仓库现状佐证:当前根 package.json 中的脚本为"ci:release": "turbo clean && npm run build:packages && changeset publish",并没有--tag后缀——这正是"维护分支上追加版本专属 tag"需要改动的行;同时ci:version脚本(changeset version && node .github/scripts/cleanup-examples-changesets.mjs && pnpm install --no-frozen-lockfile)会在版本 PR 合并时统一执行版本号提升与依赖重装。

3. 在main上进入预发布模式

切回main,进入 changeset 的预发布模式:

git checkout main pnpm changeset pre enter beta

该命令会修改.changeset/pre.json。其中initialVersions字段应当只包含来自packages/*/package.json的包;需要移除其他任何条目(例如@example/*tools/*或嵌套的测试包)。提交并推送该改动(或开一个 PR)。

4. 创建一个大版本 changeset

创建一个将每个已发布包提升到下一个大版本的 changeset:

pnpm changeset

选择packages/*/package.json中的所有包(跳过@example/*tools/*以及任何不在packages/下的条目——它们是私有的、不会被发布),并为每个包选择major。写一个类似这样的摘要:

Start v7 pre-release

提交生成的.changeset/*.md文件。

5. 播种新的规范版本(spec version)

每个大版本都会引入一个新的 Provider 规范版本(例如 V3 → V4)。必须为packages/provider/src/每一个包含版本化子目录的规范目录创建新版本目录。可以用下面的命令找到它们:

ls -d packages/provider/src/*/v3

截至本文写作时,这些目录为:embedding-modelembedding-model-middlewareimage-modelimage-model-middlewarelanguage-modellanguage-model-middlewareproviderreranking-modelsharedspeech-modeltranscription-modelvideo-model

仓库现状佐证:在当前仓库执行上述命令,实际返回了 12 个v3目录,与文档列出的清单完全一致(packages/provider/src/embedding-model/v3packages/provider/src/language-model/v3packages/provider/src/provider/v3packages/provider/src/shared/v3等)。同时language-model目录下已存在v4,印证了 V3→V4 迁移在仓库中已经落地。

对于每个目录:

  1. 将当前规范目录(例如v3/)复制为新的版本目录(例如v4/)。
  2. 将所有文件从旧版本重命名为新版本(例如language-model-v3.tslanguage-model-v4.ts)。
  3. 在每个文件内部,将所有旧版本字样替换为新版本(例如类型名、import 路径中的V3V4v3v4,以及specificationVersion字面量)。
  4. 在父级index.ts中,于 v3 导出之前添加export * from './v4/index';
  5. 更新交叉引用:如果providerv4 规范导入了其他模型类型,确保它从新的 v4 路径导入(而不是 v3)。

通过在packages/provider中运行pnpm build验证——所有新类型都应出现在构建出的.d.ts输出中。

6. 创建 mock 测试工具

packages/ai/src/test/中的每一个 mock 文件创建 V4 对应版本(例如mock-language-model-v3.tsmock-language-model-v4.ts)。更新packages/ai/test/index.ts以导出新的 V4 mocks。

仓库现状佐证:在 packages/ai/src/test/ 中可以看到完整的 V2/V3/V4 mock 矩阵,例如mock-language-model-v2.tsmock-language-model-v3.tsmock-language-model-v4.ts,以及mock-provider-v2.tsmock-provider-v3.tsmock-provider-v4.ts等,说明 V3→V4 迁移中"三版本并存、测试各自覆盖"的模式在仓库中已经真实落地。

7. 更新packages/ai以支持新规范版本

核心的packages/ai包需要适配函数、更新的公共 API 以及测试更新,来在旧版本之外同时支持新的规范版本。

适配函数(Adapter Functions)

packages/ai/src/model/中为每种模型类型创建 V4 适配文件。这些适配器使用Proxy通过覆盖specificationVersion将 V3 模型转换为 V4:

  • as-language-model-v4.ts
  • as-embedding-model-v4.ts
  • as-image-model-v4.ts
  • as-speech-model-v4.ts
  • as-transcription-model-v4.ts
  • as-reranking-model-v4.ts
  • as-video-model-v4.ts
  • as-provider-v4.ts(通过包装所有模型工厂方法,将 V3 Provider 转换为 V4)

每个适配器都会检查specificationVersion:如果已经是 V4 则原样返回模型,否则将其包装在Proxy中。

以 as-language-model-v4.ts 为例,源码清晰地展示了这一模式:

export function asLanguageModelV4( model: LanguageModelV2 | LanguageModelV3 | LanguageModelV4, ): LanguageModelV4 { if (model.specificationVersion === 'v4') { return model; } // first convert v2 to v3, then proxy v3 as v4: const v3Model = model.specificationVersion === 'v2' ? asLanguageModelV3(model) : model; return new Proxy(v3Model, { get(target, prop: keyof LanguageModelV3) { if (prop === 'specificationVersion') return 'v4'; return target[prop]; }, }) as unknown as LanguageModelV4; }

可以看到:V4 直接透传(identity);V2 先经asLanguageModelV3升到 V3,再通过 Proxy 伪装为 V4;Proxy 的get拦截器只在读取specificationVersion时返回'v4',其余属性与方法一律透传,因此模型行为完全保留。

而 as-provider-v4.ts 展示了 Provider 级别的转换:先确保得到 V3 Provider(必要时调用asProviderV3),再返回一个全新的对象,其中specificationVersion: 'v4',并且每个模型工厂方法(languageModelembeddingModelimageModeltranscriptionModelspeechModelrerankingModel)都通过对应的 V4 适配器包装;对于 Provider 未提供的可选模型类型(如transcriptionModelspeechModelrerankingModel),会保留undefined语义。

每个适配器还应有对应的测试文件(例如as-language-model-v4.test.ts),验证以下行为:

  • V4 输入原样返回(用.toBe()做身份校验);
  • V3 输入被代理且specificationVersion变为'v4'
  • V2 输入(如适用)先转为 V3 再转为 V4;
  • 属性和方法在通过 Proxy 后保持完好。
公共 API 更新

更新以下文件,使其公共边界接受V2 | V3 | V4模型,并在内部用适配器转换为 V4:

  • packages/ai/src/middleware/wrap-language-model.ts —— 接受LanguageModelV2 | V3 | V4
  • packages/ai/src/middleware/wrap-image-model.ts—— 接受ImageModelV2 | V3 | V4
  • packages/ai/src/middleware/wrap-embedding-model.ts—— 接受EmbeddingModelV3 | V4(V2 是通用类型、不包含;保留 V3 以向后兼容)
  • packages/ai/src/registry/custom-provider.ts—— 所有模型 map 中接受 V2/V3/V4 模型
  • packages/ai/src/registry/provider-registry.ts—— 接受ProviderV2 | V3 | V4,用asProviderV4转换
  • packages/ai/src/types/language-model-middleware.ts—— 放宽为同时接受 V3 和 V4 中间件

从 wrap-language-model.ts 的源码可以看到这一演进的落地形态:其wrapLanguageModel的入参类型为LanguageModelV2 | LanguageModelV3 | LanguageModelV4,函数体第一行即调用asLanguageModelV4(inputModel)统一转成 V4,随后所有内部逻辑(LanguageModelV4CallOptionsLanguageModelV4GenerateResultLanguageModelV4StreamResult)都基于 V4 类型展开,返回的包装对象也显式声明specificationVersion: 'v4'

测试更新
  • 为每个 V4 适配器创建测试文件(例如as-language-model-v4.test.ts),验证身份透传、V3→V4 转换和 V2→V4 转换。
  • 更新resolve-model.test.ts,用独立的测试块分别测试 V3→V4 转换(使用 V3 mocks)和 V4 透传(使用 V4 mocks)。
  • 更新其他测试文件,在代码现在返回 V4 模型的地方改用 V4 mocks(例如custom-provider.test.tsprovider-registry.test.ts、中间件测试)。任何对返回模型做引用相等性(.toBe())校验的测试都应使用 V4 mocks。

packages/ai中运行pnpm test,并在工作区根目录运行pnpm type-check:full(对应根 package.json 中的tsc --build tsconfig.with-examples.json)来验证。

8. 配置文档站点(ai-sdk.dev)

文档站点托管在ai-studio仓库中,通过一个指向本仓库的 Git submodule 引用本仓库。在预发布周期内,站点需要同时为稳定版和 beta 版文档提供版本化分支与 Vercel 部署。

vercel/ai仓库中:

  1. 更新.github/workflows/update-sdk-submodule-v6.yml,使其跟踪release-v6.0分支而非main
  2. 创建.github/workflows/update-sdk-submodule-v7.yml—— 该工作流拉取main、在ai-studio中检出sdk/v7分支并推送到origin sdk/v7

ai-studio仓库中:

  1. 创建sdk/v7分支(默认分支暂时保持sdk/v6,这样生产站点继续提供稳定版文档)。
  2. 在 Vercel 中创建一个连接到sdk/v7分支的 v7 预览部署(例如v7.ai-sdk.dev)。

9. 合并到main

打开一个包含第 3-7 步全部改动的 PR。合并后,第一个 beta 版本(例如ai@7.0.0-beta.1)将自动发布。


三、预发布周期内的日常开发

日常开发约定

  • 所有功能 PR 继续指向main
  • 每个 PR 仍然需要 changeset(默认使用patch)。
  • Version PackagesPR 被合并时,beta 版本自动发布。

新增一个包

main处于预发布模式时引入新包,将其package.json中的初始version设为纯0.0.0——绝不要设成0.0.0-canary.0(或任何-<tag>.N后缀)。预发布后缀会使版本成为 "premajor",而 semver 会把对 premajor 的major/minor/patch提升视为仅仅去掉后缀,于是包会卡在0.0.0-canary.N而无法前进(例如一个majorchangeset 本应产生1.0.0-canary.0)。详见 add-new-provider.md → When in pre-release mode。

将修复回传到稳定版

要把main上的修复回传到维护分支,给已合并的 PR 添加backport标签即可。这会自动创建一个指向维护分支的新 PR。

仓库现状佐证:这一行为由 .github/workflows/backport.yml 实现。工作流同时监听pull_requestlabeledclosed事件:labeled捕获"合并后补打标签"的场景,closed捕获"合并时已带标签"的场景,两者都以事件载荷中的 PR 号为准,避免竞态。它会自动解析目标维护分支(main的 PR 回传到最新release-v*分支,release-vN的 PR 回传到更早一个),执行git cherry-pick -m 1,并通过 GitHub GraphQLcreateCommitOnBranch创建签名提交与 backport PR。注意两点限制:来自 fork 的 PR 需要用workflow_dispatch手动触发;修改.github/workflows/的 PR 因GITHUB_TOKEN缺少workflows权限无法自动回传。

发布稳定补丁

合并进维护分支的补丁会触发发布工作流并发布稳定补丁版本。


四、结束预发布周期

当新大版本准备好发布稳定版时:

1. 退出预发布模式

git checkout main pnpm changeset pre exit

这会移除.changeset/pre.json。提交并推送(或开一个 PR)。

仓库现状佐证:当前仓库根目录的 .changeset/ 下只有README.mdconfig.json与几个常规 changeset 文件(如gentle-images-shine.md),并无pre.json——说明仓库当前并不处于预发布模式,这正是"进入/退出模式由pre.json存在与否决定"的旁证。

2. 发布稳定版

退出预发布模式的 PR 合并后,下一个Version PackagesPR 将产生稳定版本(例如ai@7.0.0)。合并它即可发布。

3. 切换文档站点

ai-studio仓库中,将默认分支从sdk/v6改为sdk/v7,使生产站点提供新大版本的文档。同步更新 Vercel 生产部署。

4. 归档维护分支

维护分支(例如release-v6.0)可以保留以应对紧急补丁,但不再接收常规回传。


五、小结:一份可复用的预发布检查清单

阶段关键动作验证方式
启动创建release-v<major>.0分支并推送分支上 CI 自动运行
启动维护分支ci:release追加--tag ai-v<major>检查 npm dist-tag 未被覆盖
启动pnpm changeset pre enter beta并清理pre.jsoninitialVersions检查pre.json内容
启动创建全包majorchangeset检查生成的.changeset/*.md
启动为全部 12 个规范目录播种 v4、重命名文件、替换版本字样、更新index.ts导出与交叉引用packages/providerpnpm build通过
启动创建 V4 mock 并导出pnpm test通过
启动创建 8 个 V4 适配器及测试,更新公共 API 边界与相关测试pnpm test+pnpm type-check:full通过
启动文档站点版本化分支与 Vercel 部署预览域名可访问 beta 文档
周期内功能 PR 均指向main,默认patchchangesetVersion Packages PR 自动发布 beta
周期内新包初始版本用纯0.0.0避免 premajor 卡版本
周期内已合并 PR 加backport标签backport PR 自动创建
结束pnpm changeset pre exit删除pre.jsonVersion Packages 产生稳定版本
结束文档站默认分支切换到sdk/v<new-major>生产站点提供新版文档

这套流程的底层设计意图清晰:规范版本化(spec versioning)是 AI SDK 大版本演进的锚点——从packages/provider/src/*/vN的目录结构,到packages/ai/src/model/中以Proxy实现的版本适配器,再到packages/ai/src/test/中 V2/V3/V4 三套并行的 mock 矩阵,整条链路保证了 Provider 作者可以渐进迁移,而核心packages/ai的公共 API 能同时在旧版本与新版本之上稳定运行。理解并复现这个周期,是任何希望在 AI SDK 生态中跟进或贡献大版本演进的关键能力。

【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询