ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

AI SDK Codemod 编写指南:借助 AI 模型为破坏性变更自动化升级代码

2026/9/10 22:56:53 拓冰建站 浏览量
AI SDK Codemod 编写指南:借助 AI 模型为破坏性变更自动化升级代码 AI SDK Codemod 编写指南借助 AI 模型为破坏性变更自动化升级代码【免费下载链接】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 SDKai-sdk/codemod的贡献者讲解如何借助 AI 模型高效编写 codemod代码自动转换脚本将streamText()、useChat()等 API 在版本迭代中的破坏性变更自动应用到用户代码库。读完本文你将掌握一套可直接复用的 AI 提示词工作流、createTransformer的底层约定以及从编写、测试到手动验证的完整交付流程。Codemod 是什么为什么 AI SDK 需要它AI SDK 的 API 在版本演进中会经历弃用、移除或重命名例如 v4 → v5 → v6 → v7 的多次迁移。如果让用户逐个文件手工修改成本极高且易出错。因此 AI SDK 提供了ai-sdk/codemod包这些代码转换codemod在用户代码库上以编程方式运行自动检测并改写所有符合旧 API 模式的代码。包内核心入口见 packages/codemod/src/lib/upgrade.ts其中维护了一份按版本划分的 codemod 清单bundleupgrade命令会依序全部执行。注意本指南聚焦的是为仓库贡献新的 codemod与在 packages/codemod/README.md 中介绍的「作为用户运行npx ai-sdk/codemod upgrade」是两回事。前者是开发者向 AI SDK 提交升级脚本后者是用户消费这些脚本。核心工作流让 AI 模型来写 codemod仓库的官方建议非常明确强烈推荐使用 AI 模型来为你的变更生成 codemod。因为 codemod 本质上是把「破坏性变更的描述」翻译成「AST 转换规则」而这正是大语言模型擅长的模式匹配任务。推荐的工作流如下收集破坏性变更的精确描述包括旧 API 的形态、新 API 的形态、迁移前后的代码示例。提供上下文给 AI将下方「指令清单」原样粘贴给 AI 模型例如 Cursor 配合claude-4-sonnet让模型遵循仓库既有的编码约定生成 codemod。让 AI 从 PR diff 学习对于较复杂的变更可以指示 AI 直接审查一个 pull request 的 diff例如https://github.com/vercel/ai/pull/5750.diff从中提取变更模式。如果效果不佳改用文字描述当从 diff 推导不理想时用「破坏性变更 Before/After 代码」的结构化描述替代见下文示例。测试与手动验证运行测试、手动运行 codemod 确认转换结果正确。给 AI 模型的指令清单逐条解读原文档给出了一份可直接粘贴给 AI 模型的指令清单。这里逐条说明其背后的仓库约定- Start all input/output fixtures files with // ts-nocheck. Make sure the comment remains in place in the output fixture file. - Update packages/codemod/src/lib/upgrade.ts - Use import { createTransformer } from ./lib/create-transformer; for codemods. Do not import anything from jscodeshift directly. - No need to cover imports that use require() - The codemod should not return anything. It should set context.hasChanges to true instead. - See files in packages/codemod/src/codemods for conventions - Multiple input/output files can be used in case of import conflicts. - Run tests to verify the change - Run the codemod manually to verify that its working - If you need to create temporary files for testing, create them in packages/codemod/, and remove them when done.// ts-nocheck首行注释测试夹具fixture文件不需要通过类型检查且输出夹具必须保留该注释保证 diff 干净、测试稳定。夹具存放在 packages/codemod/src/test/testfixtures/ 下每个 codemod 对应xxx.input.ts/xxx.output.ts一组文件。同步更新packages/codemod/src/lib/upgrade.ts新增的 codemod 必须登记进 bundle 数组见 upgrade.ts否则upgrade/v4/v5等批处理命令不会执行它。从源码可以看到bundle 会按v4/、v5/、v6/、v7/前缀过滤出各版本子集upgrade.ts。统一使用createTransformer所有 codemod 必须从./lib/create-transformer即 packages/codemod/src/codemods/lib/create-transformer.ts导入工厂函数禁止直接 import jscodeshift 的任何内容。这样将 jscodeshift 的 API 细节收敛到一处便于统一维护上下文与返回约定。不处理require()导入AI SDK 面向现代 ESM/TypeScript 生态codemod 只覆盖import语句无需处理 CommonJS 的require()形式。不返回值而是设置context.hasChanges这是最重要的约定之一。createTransformer创建了TransformContext其中hasChanges标志表示「本次是否对 AST 做了修改」create-transformer.ts。只有当hasChanges true时工厂才会调用root.toSource({ quote: single })返回新源码否则返回null表示无改动create-transformer.ts。messages数组则用于向用户报告信息最终通过api.report(message)输出。参考既有约定packages/codemod/src/codemods目录下已有数十个 v4/v5/v6/v7 的 codemod 实现新代码的风格、过滤条件、替换逻辑都应与之保持一致。导入冲突时使用多组输入/输出文件当同一个文件里出现多种需要替换的模式、或替换后产生命名冲突时可以用多组 fixture 覆盖不同场景。运行测试 手动运行验证两者缺一不可详见下文「测试与验证」。临时文件放packages/codemod/内并及时清理避免污染仓库其他目录。完整示例从破坏性变更描述到 codemod原文档提供了一个典型的「破坏性变更描述」模板用它来驱动 AI 生成 codemod。这个例子在仓库中有真实对应物v5/flatten-streamtext-file-properties。破坏性变更描述模板# Breaking change ## streamtext(): result.file.{mediaType,data} properties is now result.{mediaType,data} Before: ts import { streamText } from ai; const result await streamText({ model: someModel, prompt: Generate an image, }); for await (const delta of result.stream) { switch (delta.type) { case file: { console.log(Media type:, delta.file.mediaType); console.log(File data:, delta.file.data); break; } } }After:import { streamText } from ai; const result await streamText({ model: someModel, prompt: Generate an image, }); for await (const delta of result.stream) { switch (delta.type) { case file: { console.log(Media type:, delta.mediaType); console.log(File data:, delta.data); break; } } }### 仓库中的对应实现 仓库中该转换的真实实现见 [packages/codemod/src/codemods/v5/flatten-streamtext-file-properties.ts](https://link.gitcode.com/i/7d5e5a676a10e1358b905ab9991f88dc)其逻辑可以作为 AI 生成结果的「参考答案」 1. 遍历 AST 中所有的 MemberExpression成员表达式节点 2. 用过滤器精确匹配嵌套结构 delta.file.mediaType 与 delta.file.data即最外层对象为 delta、中间属性为 file、最终属性为 mediaType 或 data 3. 命中后用 j.memberExpression(outerObject.object, j.identifier(propertyName)) 构造新的表达式将 delta.file.mediaType 改写为 delta.mediaType 4. 每次替换后设置 context.hasChanges true。 ts import { createTransformer } from ../lib/create-transformer; export default createTransformer((fileInfo, api, options, context) { const { j, root } context; root .find(j.MemberExpression) .filter(path { const node path.node; // 必须是嵌套成员表达式something.file.property if (!j.MemberExpression.check(node.object)) return false; const outerObject node.object; if (!j.Identifier.check(outerObject.property) || outerObject.property.name ! file) return false; if (!j.Identifier.check(outerObject.object) || outerObject.object.name ! delta) return false; if (!j.Identifier.check(node.property)) return false; const propertyName node.property.name; return propertyName mediaType || propertyName data; }) .forEach(path { const node path.node; const outerObject node.object; const propertyName node.property.name; // delta.file.mediaType - delta.mediaType path.replace(j.memberExpression(outerObject.object, j.identifier(propertyName))); context.hasChanges true; }); });这个例子展示了「描述 → 代码」的完整映射描述中的每个 Before/After 差异点都会转化为过滤器中的一个判定条件和一次节点替换。底层机制createTransformer与TransformContext理解createTransformer的实现有助于写出与仓库完全一致的 codemod。工厂函数位于 packages/codemod/src/codemods/lib/create-transformer.ts它返回一个符合 jscodeshift 签名(fileInfo, api, options)的 transformerjjscodeshift API 对象api.jscodeshift用于j.MemberExpression、j.identifier等节点构造与判定。root以j(fileInfo.source)构建的整个 AST 根集合所有root.find(...)查询都基于它。hasChanges布尔标志codemod 改动 AST 时必须置为true。messages字符串数组通过api.report()上报给用户。转换函数执行完毕后工厂根据hasChanges决定返回root.toSource({ quote: single })注意输出使用单引号还是null。这套封装让单个 codemod 文件极其精简——只关心「匹配什么、替换成什么」。测试与验证交付前的两道关卡编写测试每个 codemod 都配有 vitest 测试例如 packages/codemod/src/test/flatten-streamtext-file-properties.test.tsimport { describe, it } from vitest; import transformer from ../codemods/v5/flatten-streamtext-file-properties; import { testTransform } from ./test-utils; describe(flatten-streamtext-file-properties, () { it(transforms correctly, () { testTransform(transformer, flatten-streamtext-file-properties); }); });测试通过testTransform工具见 packages/codemod/src/test/test-utils.ts自动加载__testfixtures__/flatten-streamtext-file-properties.input.ts与.output.ts断言转换结果与期望输出完全一致。因此编写测试 编写一组 input/output 夹具它们都必须以// ts-nocheck开头。运行测试在 codemod 包目录下执行cd packages/codemod # 运行全部测试 pnpm test # 只跑某个 codemod 的测试 pnpm test codemod-name # 开发时监听模式 pnpm test:watch手动验证自动化测试之外务必手动运行一次真实转换确认在真实项目形态下的表现例如用--print查看转换后的代码、用--dry预览改动命令用法见 packages/codemod/README.md# 预览不实际写入 npx ai-sdk/codemod --dry v5/flatten-streamtext-file-properties src/ # 打印转换结果到 stdout npx ai-sdk/codemod --print v5/flatten-streamtext-file-properties src/example.ts用户视角ai-sdk/codemod的使用方式为了让新写的 codemod 有清晰的消费场景了解 CLI 的对外接口很有帮助详见 packages/codemod/README.md# 一键应用全部 codemodv4 v5 v6 npx ai-sdk/codemod upgrade # 按版本应用 npx ai-sdk/codemod v4 npx ai-sdk/codemod v5 npx ai-sdk/codemod v6 # 单独应用某个 codemod 到文件/目录 npx ai-sdk/codemod codemod-name path常用全局选项--dry预览改动而不写入文件--print把转换后的代码打印到 stdout--verbose输出详细的转换日志。从 packages/codemod/src/lib/transform.ts 可以看到实际执行是通过在子进程中调用 jscodeshift 完成的转换命令默认忽略node_modules、隐藏目录如.next/、dist、build以及压缩后的.min.js/.bundle.js文件transform.ts避免误改依赖与构建产物。编写与交付清单综合原文档与仓库约定提交一个新 codemod 的完整流程是明确变更梳理破坏性变更的 Before/After复杂场景可直接让 AI 阅读 PR diff。生成实现把指令清单 变更描述喂给 AI 模型产出packages/codemod/src/codemods/version/name.ts。登记 bundle将新 codemod 加入 packages/codemod/src/lib/upgrade.ts 的 bundle 数组并确认其版本前缀正确v4/v5/v6/v7。添加夹具与测试在 packages/codemod/src/test/testfixtures/ 写 input/output 文件首行// ts-nocheck在 packages/codemod/src/test/ 写测试用例导入冲突时拆分多组夹具。跑测试pnpm test全绿。手动验证对真实代码运行 codemod确认无遗漏、无误伤并清理packages/codemod/下的临时文件。这套「AI 生成 人工校验」的流程把最容易出错的 AST 遍历与节点替换交给模型同时用统一的createTransformer约定、fixture 测试和 bundle 登记机制守住质量底线让 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),仅供参考