Genkit 中的 TypeScript 编码规范技能:解读 agents/skills/typescript/SKILL.md 的设计与实战

发布时间:2026/9/17 12:43:45
Genkit 中的 TypeScript 编码规范技能:解读 agents/skills/typescript/SKILL.md 的设计与实战 Genkit 中的 TypeScript 编码规范技能解读 agents/skills/typescript/SKILL.md 的设计与实战【免费下载链接】genkitOpen-source framework for building agentic apps in JavaScript, Go, Dart, and Python, built and used in production by Google项目地址: https://gitcode.com/GitHub_Trending/ge/genkit本篇文章以 Genkit 仓库中的技能文件 js/testapps/agents/skills/typescript/SKILL.md 为对象完整拆解其作为「TypeScript 编码规范技能」的内容结构并深入讲解 Genkit 的 skills 中间件如何自动扫描、解析并注入该技能让 AI Agent 在写代码时按需加载编码规范。读完本文你既能掌握一份可直接复用的 TypeScript 编码规范清单也能理解在 Genkit 中编写和挂载自定义 SKILL.md 的完整机制。一、技能文件的解剖frontmatter 与正文该技能文件位于js/testapps/agents/skills/typescript/SKILL.md属于js/testapps/agents测试应用的 skills 目录。它由两大部分组成1. YAML frontmatter元数据头文件开头的---包裹区定义了两个关键元数据字段--- name: typescript description: TypeScript coding conventions, best practices, and patterns for writing clean, maintainable code. ---name技能的唯一标识。在 Genkit 中它同时是use_skill工具的参数值skillName用于按名加载。description技能的一句话摘要。它会被注入到模型的系统提示词中作为模型判断何时该调用该技能的依据。从 skills 中间件实现 的parseFrontmatter函数L54-L68可以看到源码通过正则^name:\s*(.)/m与^description:\s*(.)/m分别提取这两个字段若缺少description中间件会回退为No description provided.占位文案。2. Markdown 正文frontmatter 之后是真正的技能指令正文也就是模型调用use_skill后拿到并注入上下文的完整内容。它覆盖了 TypeScript 工程从编码风格到测试的 8 个维度下文逐一详解。二、通用原则General Principles技能开篇给出 5 条贯穿全文的顶层约定开启 TypeScript strict modetsconfig.json中设置strict: true。严格模式会启用包括noImplicitAny、strictNullChecks、strictFunctionTypes在内的一整套类型检查约束把大量运行时错误提前到编译期暴露。优先const拒绝var用const声明不会重新赋值的绑定用let声明确实需要变化的变量彻底摒弃存在函数级提升、易产生作用域泄漏的var。导出函数必须显式标注返回类型对外 API 的返回类型不依赖类型推断既是契约文档也防止重构时返回值类型悄悄漂移。对象形状优先用interface而非 type aliasinterface支持声明合并declaration merging与更友好的编辑器报错与继承适合描述对象结构。尽量用unknown而非anyany会关闭类型检查逃逸所有约束unknown强制先收窄narrow再使用保证类型安全的同时保留灵活性。三、命名规范Naming Conventions技能用一张清单规定了各实体的命名形态实体命名规范示例变量与函数camelCasegetUserById、totalCount类与接口PascalCaseUserRepository、HttpClient常量真常量用UPPER_SNAKE_CASE派生值用camelCaseMAX_RETRIESvsretryLimit文件kebab-case.tsuser-service.ts类型参数单个大写字母T、K、V或语义化描述TResultfunction mapT, TResult(...)「真常量 vs 派生值」的区分要点在于硬编码的魔法数字、固定配置用全大写蛇形由程序计算出来、仅在模块内不变的值用驼峰避免过度标记。四、目录结构File Structure技能推荐的工程目录模板src/ index.ts # Entry point, exports types.ts # Shared type definitions utils/ # Utility functions services/ # Business logic middleware/ # Express/framework middleware这种分层思路的核心是按职责划分而非按类型堆叠入口与公共导出收敛在index.ts共享类型独立成types.ts避免循环依赖纯函数放入utils/业务编排放入services/框架相关的横切逻辑如 Express 中间件单独归入middleware/。五、错误处理Error Handling技能要求三条硬性规则使用类型化错误自定义错误类继承Error携带结构化字段始终处理 Promise 拒绝不放过任何未捕获的 rejectiontry/catch优先捕获具体错误类型避免笼统的catch (e)。文档给出了一个可直接落地的AppError基类class AppError extends Error { constructor( message: string, public readonly code: string, public readonly statusCode: number 500 ) { super(message); this.name AppError; } }该模式的关键设计点readonly修饰的code机器可读的错误码与statusCodeHTTP 状态码默认 500作为构造参数注入使上层可以依据err.code或err.statusCode做分支处理而不是解析错误消息字符串。同时显式设置this.name AppError以修正Error原型链上的 name 属性保证错误序列化与日志输出可读。六、异步模式Async Patterns统一使用async/await不用裸 Promise 链与回调相互独立的并发操作用Promise.all()并行执行缩短总耗时禁止在同一代码路径中混用回调与 Promise保持异步心智模型单一。// 推荐并发拉取相互独立的数据 const [users, posts] await Promise.all([ fetchUsers(), fetchPosts(), ]);七、导入规范Imports使用命名导入import { thing } from ./module分组排序先外部依赖包再内部模块ESM 兼容下导入路径必须带.js扩展名。这一点在现代 Node.js 的 ESM 解析规则下是硬性要求——TypeScript 编译产物仍会保留源码中的相对导入路径而 Node ESM 不会自动补全扩展名因此在 Genkit 这类以type: module发布的包中必须写全.js后缀。例如仓库中的源码import { skills } from ../src/skills.js见 skills 测试文件 L23就是这一约定的实际体现。八、代码风格Code Style单行最大长度 100 字符字符串插值一律使用模板字符串template literals数据变换优先用Array.map/filter/reduce少用命令式for循环善用可选链?.与空值合并??访问多个属性时解构对象与数组。这些风格项共同指向「声明式、防错、少样板」的现代 TS 写法// 结合可选链与空值合并的安全访问 const displayName user?.profile?.nickname ?? anonymous;九、测试规范Testing测试文件与被测文件同目录就近放置thing.ts→thing.test.ts测试命名描述行为而非实现it(should return empty array when no items match)必测边界条件空输入、null 值、错误路径。该「co-locate就近放置」策略在 Genkit 仓库中同样被广泛采用例如js/plugins/middleware/tests/skills_test.ts与src/skills.ts的目录对应关系。十、Genkit 如何加载这份技能skills 中间件源码解析SKILL.md不是孤立文本它由genkit-ai/middleware的skills中间件消费。整个加载链路在 skills.ts 中实现可分为三步1. 目录扫描与缓存L72-L143中间件按配置的skillPaths逐目录readdir对每个非隐藏子目录尝试读取其SKILL.md解析 frontmatter 后将目录名 → { path, description }存入skillCache。扫描结果通过 logger 输出Loaded N skills from disk (...)便于排查。目录缺失ENOENT会被静默跳过其余读取异常仅告警不中断。2. 系统提示注入L171-L254generate钩子把可用技能清单组装成一段带skills标记的系统提示文本追加到 system 消息skills You have access to a library of skills that serve as specialized instructions/personas. Strongly prefer to use them when working on anything related to them. Only use them once to load the context. Here are the available skills: - typescript - TypeScript coding conventions, best practices, and patterns for writing clean, maintainable code. /skills注意清单中的每一条正是- name - description直接来自 SKILL.md 的 frontmatter——这正是为什么本文这份技能文件的description写得如此具体它决定了模型能否在恰当的任务场景下主动选择该技能。此外注入的逻辑是幂等的通过metadata[skills-instructions]标记已注入的消息片段多轮对话中只替换不重复测试用例 skills_test.ts L131-L174 专门验证了系统提示不会随多轮调用累积重复。3.use_skill按需加载L145-L167中间件同时注册一个use_skill工具输入skillName命中缓存后返回该 SKILL.md 的完整原文作为工具输出未知技能则抛出Skill xxx not found.。这就实现了「系统提示只给索引、正文按需拉取」的轻量上下文策略避免所有技能的全文常驻在上下文中。测试 L100-L116 验证了加载python技能能取回其正文内容。十一、在 Coding Agent 中的实战集成这份 TypeScript 技能的实际使用场景是 js/testapps/agents/src/coding-agent.ts 中定义的codingAgent。它通过中间件组合把技能挂载到智能体上const SKILLS_DIR path.resolve(__dirname, .., skills); export const codingAgent ai.defineAgent({ name: codingAgent, system: ..., tools: [runShell, askUser], use: [ toolApproval({ approved: [list_files, read_file, use_skill, run_shell, ask_user], }), filesystem({ rootDirectory: WORKSPACE_DIR, allowWriteAccess: true }), skills({ skillPaths: [SKILLS_DIR] }), // 挂载技能库 retry(), ], store, maxTurns: 30, });这里有几个值得注意的集成细节skillPaths指向js/testapps/agents/skills目录因此该目录下的typescript/子目录即本文所分析的技能会被自动扫描为typescript技能toolApproval的approved列表显式包含use_skill使技能加载操作默认免审批智能体的系统提示明确要求「If a skill matches the task (e.g. typescript for TS work), load it first」与 skills 中间件注入的提示互相配合驱动模型在接到写 TypeScript 代码的任务时先调用use_skill拉取本文这份规范再动手。更精简的示例见 middleware/examples/coding_agent.ts L93-L99它在一次ai.generate调用中同样以use: [toolApproval(...), skills({ skillPaths: [skillsRoot] }), filesystem(...)]的顺序组合使用。此外该能力在 Go 侧也有对应实现 go/plugins/middleware/skills.go跨语言行为一致。十二、编写属于自己的 SKILL.md结合本文分析一份可被 Genkit 正确消费的技能文件需要满足以下条件目录即技能名将 SKILL.md 放在形如skills/skill-name/SKILL.md的目录中目录名就是技能的标识本文即skills/typescript/SKILL.mdfrontmatter 必填name与descriptiondescription直接影响模型是否选择该技能建议写清适用场景与职责边界正文是给模型看的指令建议像本文这份技能一样采用「原则 → 命名 → 结构 → 错误处理 → 异步 → 导入 → 风格 → 测试」的分节结构以列表、代码示例和参数表为主便于模型快速消化通过skills({ skillPaths })挂载指向技能库根目录即可多语言、多规范可以各建一个子目录并存验证加载效果可参照 skills_test.ts 的测试模式——用 mock 模型捕获注入后的系统提示断言skills清单与use_skill的返回内容是否符合预期。综上js/testapps/agents/skills/typescript/SKILL.md既是一份可独立参考的 TypeScript 编码规范模板也是理解 Genkit「SKILL.md skills 中间件 use_skill 工具」这一技能加载链路的最佳入口规范的质量决定 Agent 产出代码的水准而元数据与目录组织决定规范能否被 Agent 在正确时机精准取用。【免费下载链接】genkitOpen-source framework for building agentic apps in JavaScript, Go, Dart, and Python, built and used in production by Google项目地址: https://gitcode.com/GitHub_Trending/ge/genkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考