diff --git a/AGENTS.md b/AGENTS.md index 0db2d7ad79..93957e861a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,7 @@ If another agent-specific file exists, it should import or defer to this file fo ## Project Map -Egg is maintained as a pnpm monorepo. +Egg is maintained as a Utoo monorepo. - `packages/` contains core framework packages and shared internals. - `plugins/` contains optional Egg integrations. @@ -18,12 +18,12 @@ Egg is maintained as a pnpm monorepo. ## Core Commands -- `pnpm install` hydrates the workspace. -- `pnpm run build` builds all packages. -- `pnpm run test` runs the main test suite. -- `pnpm run lint` runs linting. -- `pnpm run typecheck` runs TypeScript checking. -- use filtered commands for focused work, for example `pnpm --filter=egg run test` or `pnpm --filter=site run dev`. +- `utoo install` hydrates the workspace. +- `utoo run build` builds all packages. +- `utoo run test` runs the main test suite. +- `utoo run lint` runs linting. +- `utoo run typecheck` runs TypeScript checking. +- use workspace-filtered commands for focused work, for example `utoo run --workspace egg test` or `utoo run --workspace site dev`. ## Coding Conventions @@ -51,7 +51,7 @@ Egg is maintained as a pnpm monorepo. - review `SECURITY.md` before handling vulnerability-related work - do not commit secrets, credentials, or local-only URLs -- keep local Node.js and pnpm versions aligned with the repository configuration +- keep local Node.js and Utoo versions aligned with the repository configuration ## Shared Knowledge Workflow @@ -85,7 +85,7 @@ The wiki lives under `wiki/` and stores durable synthesized knowledge. Shared workflow rules live here in `AGENTS.md`. -Agent-specific files should stay thin and point back to this file instead of duplicating the schema. +Agent-specific files such as `CLAUDE.md` should stay thin and point back to the nearest `AGENTS.md` instead of duplicating the schema. ## Wiki Layout diff --git a/CLAUDE.md b/CLAUDE.md index d4ba9b7025..f6aa6c0262 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,9 +1,3 @@ # CLAUDE.md @AGENTS.md - -## Claude-Specific Notes - -- Keep shared repository guidance in `AGENTS.md`. -- Keep this file thin and use it only for Claude Code specific imports or overrides. -- For global type definitions, follow the TypeScript Global Types section in `AGENTS.md`. diff --git a/packages/skills/AGENTS.md b/packages/skills/AGENTS.md new file mode 100644 index 0000000000..2144ee916b --- /dev/null +++ b/packages/skills/AGENTS.md @@ -0,0 +1,214 @@ +# AGENTS.md + +Follow the repository root `AGENTS.md` first. This file adds guidance for work under `packages/skills/`. + +## Skills 编写与评测规范 + +`packages/skills/` 目录包含 AI agent skills — 纯 markdown 文档,指导 AI 助手使用 Egg 框架。以 `@eggjs/skills` npm 包发布,仅含 `.md` 文件。 + +> **Skill 编写基础知识**:SKILL.md 格式、frontmatter 规范、目录结构、progressive disclosure、写作风格等通用知识请使用 `/skill-creator` skill 获取指导。以下仅记录 Egg 项目特有的约定。 + +## Egg Skills 架构 + +Skills 采用分层路由模式: + +- **入口 skill** (`egg/`) — 分析用户意图,通过关键词匹配和决策逻辑路由到专业 skill +- **专业 skills** — 提供特定领域的深度指导: + - `egg-core/` — 核心概念:模块、依赖注入、生命周期、AccessLevel、后台任务 + - `egg-controller/` — 实现指导:HTTPController、MCPController、Schedule、Ajv 校验 + +## Egg Skill Frontmatter 约定 + +- **`name`**:入口 skill 使用 `egg`,专业 skill 以 `egg-` 为前缀(如 `egg-controller`、`egg-core`) +- **`allowed-tools`**:统一使用 `Read`(纯文档指导型,不修改文件) +- **`description`**: + - 中文:以"本技能用于..."开头,包含触发关键词 + - 英文:以"Use when..."开头,包含触发关键词 + +## 专业 Skill 编写规范 + +**入口 Skill(如 `egg/`)编写要点:** + +对应 /skill-creator 的 **Workflow-Based** 模式。 + +1. 决策框架包含明确步骤:识别意图 → 检查模糊意图 → 协议/用例特定指示 +2. 为每个专业 skill 列出中英文触发关键词 +3. 冲突解决规则:明确意图模糊时的优先级(如"基础优先"——核心概念优先于控制器实现) +4. 示例分析:多个完整示例,格式为 用户查询 → 分析 → 决策 → 响应策略 +5. 快速参考表:用户意图 → 关键词 → 推荐 skill 映射 +6. 交叉引用话术:回答完主问题后,附"如需了解 X,请参阅 `@eggjs/skills-xxx`" + +**专业 Skill 两种组织模式:** + +| 模式 | /skill-creator 对应 | 适用场景 | SKILL.md 内容 | references/ 用途 | +| ---------------------------------- | ------------------- | ------------------ | ----------------------- | ------------------ | +| **概念型**(如 `egg-core/`) | Reference-Based | 概念解释、架构理解 | 自包含的深度内容 | 更深入的专题文档 | +| **索引型**(如 `egg-controller/`) | Workflow-Based | 多种实现方式的选择 | 精简的决策树 + 快速参考 | 每种实现的详细指南 | + +**概念型 Skill 内容结构:** + +1. 概述(一段话说明覆盖范围) +2. 按概念分块,每个概念包含:定义 → 使用场景 → 装饰器/API 模式 → 代码示例 +3. 重要约束(反模式、限制) +4. 快速决策指南表(场景 → 推荐方式) +5. 最佳实践 +6. 参考资料链接 + +**索引型 Skill 内容结构:** + +1. 决策树(根据需求选择实现方式) +2. 每种类型的快速参考(装饰器、参数、特点) +3. 最佳实践 +4. 参考资料链接 + +## Reference 文档编写要点 + +Reference 文档(`references/*.md`)**不需要 YAML frontmatter**,只有 `SKILL.md` 才需要。 + +**核心原则:Skill 不是文档的重新排版,而是填补"文档到生产代码"之间的缝隙。** + +Skill 的价值 = 文档 + 实践经验 - 重复内容。如果内容和 `site/docs/` 中的文档高度重复,说明 skill 写得不对。 + +| 内容类型 | 该放文档(site/docs/) | 该放 Skill(packages/skills/) | +| ------------------- | ---------------------- | ------------------------------ | +| API 签名、参数说明 | Yes | No(引用文档即可) | +| 易错点 / 常见错误 | 部分 | **Yes(重点)** | +| 完整端到端模式 | No | **Yes** | +| 跨模块集成知识 | 散落各处 | **Yes(聚合)** | +| 文件放置 / 命名约定 | 部分 | **Yes** | +| 场景化决策树 | No | **Yes** | + +**编写 Reference 文档的具体步骤:** + +1. **先读对应的文档**(如 `site/docs/zh-CN/basics/mcpcontroller.md`),理解已有内容 +2. **向维护者提问,收集文档未覆盖的知识**,重点关注: + - 导入路径、命名约定等易错点(AI 最容易犯的错) + - 文件应该放在哪个目录?命名规则是什么? + - 和其他模块(Module、Service、DI)的集成关系 + - 哪些配置参数实际开发中需要关心,哪些用默认值即可 + - 哪些是内部扩展机制不需要暴露给应用开发者 +3. **以常见错误表开头** — 把 AI 最容易写错的地方放在最醒目的位置(如错误的导入路径、错误的 API 用法) +4. **文件约定** — 目录结构、命名规则、配置文件位置,这些文档里通常不会详细说明 +5. **场景化决策树** — 从用户意图出发("让 AI 查数据"),而非从 API 出发("@MCPTool") +6. **端到端完整示例** — 从配置文件到控制器到 Service 到测试,展示所有相关文件和它们的关系 +7. **精简的装饰器对照表放末尾** — 仅作为速查,不展开 API 详解 + +## 添加新 Skill + +1. 在 `packages/skills/` 下创建目录:`packages/skills//` +2. 创建 `SKILL.md`(格式规范参考 `/skill-creator`,frontmatter 遵循上述 Egg 约定) +3. 创建 `references/` 目录(初始为空时放置 `.gitkeep`) +4. 按需在 `references/*.md` 中添加详细参考文档 +5. 更新入口 skill(`egg/SKILL.md`)的路由逻辑以包含新 skill +6. 如果 skill 涉及 controller 类型,同时更新 `egg-controller/SKILL.md` 决策树 + +## 添加新 Reference 文档 + +1. 在 skill 的 `references/` 目录中创建 `.md` 文件 +2. 遵循命名规范(kebab-case,描述性命名:`http-controller.md`、`mcp-controller.md`) +3. 包含完整的代码示例和决策树 +4. 更新父级 `SKILL.md` 引用新文档 +5. 如果 `references/` 中已有文件,移除 `.gitkeep` + +## Skill 评测 + +评测用例存放在 `packages/skills/eval/` 目录下,用于验证 AI 使用 skill 后的回答质量。 + +**评测文件结构:** + +```text +packages/skills/eval/ +├── evals-egg-core.json # egg-core skill 评测用例 +├── evals-egg-controller.json # egg-controller skill 评测用例 +├── evals-routing.json # 入口路由评测用例 +├── .gitignore # 忽略 *-workspace/ 目录 +└── -workspace/ # 评测输出(gitignored),由 /skill-creator 管理 + └── iteration-N/ + ├── REPORT.md # 对比评分报告 + ├── GRADING.md # with-skill 通过率报告 + └── {prefix}-{id}/ # 每个用例一个目录 + ├── eval_metadata.json + ├── with_skill/outputs/ + └── without_skill/outputs/ +``` + +**评测用例 JSON 格式:** + +```json +{ + "skill_name": "egg-controller", + "description": "控制器评测:覆盖 http-controller、mcp-controller、schedule、ajv-validate", + "evals": [ + { + "id": 1, + "prompt": "用户的任务描述", + "expected_output": "期望输出的关键要素描述", + "files": [{ "path": "相对路径", "content": "文件内容(可选,用于提供上下文或有 bug 的代码)" }] + } + ] +} +``` + +**评测流程:** + +使用 `/skill-creator` skill 运行评测和生成结果展示。评测流程概述: + +1. **编写评测用例** — 在对应的 `evals-*.json` 中添加用例 +2. **运行评测** — 通过 `/skill-creator` 为每个用例启动两个并行 subagent(with-skill 和 site-docs),使用下方 prompt 模板 +3. **评分和展示** — `/skill-creator` 负责评分、生成对比报告、启动可视化 viewer 供人工 review +4. **改进 skill** — 根据评分结果和人工 feedback 改进 skill 内容,开启新的 iteration + +**评测对比的两组环境:** + +每个评测用例需要在两种环境下分别运行,对比 skill 是否有效。Prompt 中不应包含任何流程指引(如"先判断使用哪个 skill"),只提供参考资料和访问约束,让 AI 自然行动。 + +| 环境 | system prompt | 可访问范围(prompt 约束) | +| -------------- | ------------------------------------------------------------------------------------- | -------------------------- | +| **with-skill** | `egg/SKILL.md`(入口 skill)的完整内容 | 仅 `packages/skills/` 目录 | +| **site-docs** | 角色声明 + `site/docs/` 的完整文件目录列表(通过 `find site/docs -name '*.md'` 生成) | 仅 `site/docs/` 目录 | + +**Prompt 模板:** + +with-skill 环境: + +```text +你是 EGG 框架开发专家。你只能通过 Read 工具读取 packages/skills/ 目录下的文件,不能访问 site/docs/ 或项目源码。 + +{egg/SKILL.md 的完整内容} + +--- +{eval prompt} +``` + +site-docs 环境: + +```text +你是 EGG 框架开发专家。你只能通过 Read 工具读取 site/docs/ 目录下的文件,不能访问 packages/skills/ 或项目源码。项目文档目录如下: + +{完整的 site/docs/ 文件列表,通过 find site/docs -name '*.md' | sort 生成} + +--- +{eval prompt} +``` + +两组 prompt 的差异仅在于参考资料不同,不包含额外的流程提示。subagent 均具备 Read 工具权限。访问范围通过 prompt 约束(软限制,非技术硬限制)。 + +两组使用相同的 eval prompt,对比输出质量差异。如果 with-skill 没有明显优于 site-docs,说明 skill 内容需要改进——要么缺少文档未覆盖的知识,要么存在与文档的不必要重复。 + +**输出目录:** + +评测结果保存到 `packages/skills/eval/-workspace/iteration-N/` 目录下(已在 `.gitignore` 中通过 `*-workspace/` 忽略),具体目录结构由 `/skill-creator` 管理。 + +**评测用例设计原则:** + +每个 reference 文档至少覆盖 5 个以上评测用例,需覆盖以下场景类型: + +| 场景类型 | 说明 | 示例 | +| -------------------- | --------------------------------------- | -------------------------------------------------------- | +| **泛化需求描述** | 不了解框架术语,用口语化描述需求 | "帮我加个参数校验" | +| **精确需求描述** | 明确指定技术方案和约束 | "用 TypeBox 定义 Schema,email 用 format: email" | +| **使用咨询** | 询问用法、区别、选型 | "Optional 和 Null 有什么区别" | +| **问题排查** | 提供有 bug 的代码(附 files),要求诊断 | "校验跑不起来,帮我看看" | +| **新项目代码生成** | 在全新项目中从零开始生成功能代码 | "帮我写一个创建订单的接口,需要做参数校验" | +| **存量项目代码生成** | 在包含老 egg 代码的项目中生成或迁移代码 | "帮我把这个老的 egg controller 改成 HTTPController 写法" | +| **不常用 API** | 需要查外部文档链接才能回答 | "用 Tuple 定义元组校验" | diff --git a/packages/skills/CLAUDE.md b/packages/skills/CLAUDE.md index 2f972853f8..f6aa6c0262 100644 --- a/packages/skills/CLAUDE.md +++ b/packages/skills/CLAUDE.md @@ -1,210 +1,3 @@ -# Skills 编写与评测规范 +# CLAUDE.md -`packages/skills/` 目录包含 AI agent skills — 纯 markdown 文档,指导 AI 助手使用 Egg 框架。以 `@eggjs/skills` npm 包发布,仅含 `.md` 文件。 - -> **Skill 编写基础知识**:SKILL.md 格式、frontmatter 规范、目录结构、progressive disclosure、写作风格等通用知识请使用 `/skill-creator` skill 获取指导。以下仅记录 Egg 项目特有的约定。 - -## Egg Skills 架构 - -Skills 采用分层路由模式: - -- **入口 skill** (`egg/`) — 分析用户意图,通过关键词匹配和决策逻辑路由到专业 skill -- **专业 skills** — 提供特定领域的深度指导: - - `egg-core/` — 核心概念:模块、依赖注入、生命周期、AccessLevel、后台任务 - - `egg-controller/` — 实现指导:HTTPController、MCPController、Schedule、Ajv 校验 - -## Egg Skill Frontmatter 约定 - -- **`name`**:入口 skill 使用 `egg`,专业 skill 以 `egg-` 为前缀(如 `egg-controller`、`egg-core`) -- **`allowed-tools`**:统一使用 `Read`(纯文档指导型,不修改文件) -- **`description`**: - - 中文:以"本技能用于..."开头,包含触发关键词 - - 英文:以"Use when..."开头,包含触发关键词 - -## 专业 Skill 编写规范 - -**入口 Skill(如 `egg/`)编写要点:** - -对应 /skill-creator 的 **Workflow-Based** 模式。 - -1. 决策框架包含明确步骤:识别意图 → 检查模糊意图 → 协议/用例特定指示 -2. 为每个专业 skill 列出中英文触发关键词 -3. 冲突解决规则:明确意图模糊时的优先级(如"基础优先"——核心概念优先于控制器实现) -4. 示例分析:多个完整示例,格式为 用户查询 → 分析 → 决策 → 响应策略 -5. 快速参考表:用户意图 → 关键词 → 推荐 skill 映射 -6. 交叉引用话术:回答完主问题后,附"如需了解 X,请参阅 `@eggjs/skills-xxx`" - -**专业 Skill 两种组织模式:** - -| 模式 | /skill-creator 对应 | 适用场景 | SKILL.md 内容 | references/ 用途 | -| ---------------------------------- | ------------------- | ------------------ | ----------------------- | ------------------ | -| **概念型**(如 `egg-core/`) | Reference-Based | 概念解释、架构理解 | 自包含的深度内容 | 更深入的专题文档 | -| **索引型**(如 `egg-controller/`) | Workflow-Based | 多种实现方式的选择 | 精简的决策树 + 快速参考 | 每种实现的详细指南 | - -**概念型 Skill 内容结构:** - -1. 概述(一段话说明覆盖范围) -2. 按概念分块,每个概念包含:定义 → 使用场景 → 装饰器/API 模式 → 代码示例 -3. 重要约束(反模式、限制) -4. 快速决策指南表(场景 → 推荐方式) -5. 最佳实践 -6. 参考资料链接 - -**索引型 Skill 内容结构:** - -1. 决策树(根据需求选择实现方式) -2. 每种类型的快速参考(装饰器、参数、特点) -3. 最佳实践 -4. 参考资料链接 - -## Reference 文档编写要点 - -Reference 文档(`references/*.md`)**不需要 YAML frontmatter**,只有 `SKILL.md` 才需要。 - -**核心原则:Skill 不是文档的重新排版,而是填补"文档到生产代码"之间的缝隙。** - -Skill 的价值 = 文档 + 实践经验 - 重复内容。如果内容和 `site/docs/` 中的文档高度重复,说明 skill 写得不对。 - -| 内容类型 | 该放文档(site/docs/) | 该放 Skill(packages/skills/) | -| ------------------- | ---------------------- | ------------------------------ | -| API 签名、参数说明 | Yes | No(引用文档即可) | -| 易错点 / 常见错误 | 部分 | **Yes(重点)** | -| 完整端到端模式 | No | **Yes** | -| 跨模块集成知识 | 散落各处 | **Yes(聚合)** | -| 文件放置 / 命名约定 | 部分 | **Yes** | -| 场景化决策树 | No | **Yes** | - -**编写 Reference 文档的具体步骤:** - -1. **先读对应的文档**(如 `site/docs/zh-CN/basics/mcpcontroller.md`),理解已有内容 -2. **向维护者提问,收集文档未覆盖的知识**,重点关注: - - 导入路径、命名约定等易错点(AI 最容易犯的错) - - 文件应该放在哪个目录?命名规则是什么? - - 和其他模块(Module、Service、DI)的集成关系 - - 哪些配置参数实际开发中需要关心,哪些用默认值即可 - - 哪些是内部扩展机制不需要暴露给应用开发者 -3. **以常见错误表开头** — 把 AI 最容易写错的地方放在最醒目的位置(如错误的导入路径、错误的 API 用法) -4. **文件约定** — 目录结构、命名规则、配置文件位置,这些文档里通常不会详细说明 -5. **场景化决策树** — 从用户意图出发("让 AI 查数据"),而非从 API 出发("@MCPTool") -6. **端到端完整示例** — 从配置文件到控制器到 Service 到测试,展示所有相关文件和它们的关系 -7. **精简的装饰器对照表放末尾** — 仅作为速查,不展开 API 详解 - -## 添加新 Skill - -1. 在 `packages/skills/` 下创建目录:`packages/skills//` -2. 创建 `SKILL.md`(格式规范参考 `/skill-creator`,frontmatter 遵循上述 Egg 约定) -3. 创建 `references/` 目录(初始为空时放置 `.gitkeep`) -4. 按需在 `references/*.md` 中添加详细参考文档 -5. 更新入口 skill(`egg/SKILL.md`)的路由逻辑以包含新 skill -6. 如果 skill 涉及 controller 类型,同时更新 `egg-controller/SKILL.md` 决策树 - -## 添加新 Reference 文档 - -1. 在 skill 的 `references/` 目录中创建 `.md` 文件 -2. 遵循命名规范(kebab-case,描述性命名:`http-controller.md`、`mcp-controller.md`) -3. 包含完整的代码示例和决策树 -4. 更新父级 `SKILL.md` 引用新文档 -5. 如果 `references/` 中已有文件,移除 `.gitkeep` - -## Skill 评测 - -评测用例存放在 `packages/skills/eval/` 目录下,用于验证 AI 使用 skill 后的回答质量。 - -**评测文件结构:** - -```text -packages/skills/eval/ -├── evals-egg-core.json # egg-core skill 评测用例 -├── evals-egg-controller.json # egg-controller skill 评测用例 -├── evals-routing.json # 入口路由评测用例 -├── .gitignore # 忽略 *-workspace/ 目录 -└── -workspace/ # 评测输出(gitignored),由 /skill-creator 管理 - └── iteration-N/ - ├── REPORT.md # 对比评分报告 - ├── GRADING.md # with-skill 通过率报告 - └── {prefix}-{id}/ # 每个用例一个目录 - ├── eval_metadata.json - ├── with_skill/outputs/ - └── without_skill/outputs/ -``` - -**评测用例 JSON 格式:** - -```json -{ - "skill_name": "egg-controller", - "description": "控制器评测:覆盖 http-controller、mcp-controller、schedule、ajv-validate", - "evals": [ - { - "id": 1, - "prompt": "用户的任务描述", - "expected_output": "期望输出的关键要素描述", - "files": [{ "path": "相对路径", "content": "文件内容(可选,用于提供上下文或有 bug 的代码)" }] - } - ] -} -``` - -**评测流程:** - -使用 `/skill-creator` skill 运行评测和生成结果展示。评测流程概述: - -1. **编写评测用例** — 在对应的 `evals-*.json` 中添加用例 -2. **运行评测** — 通过 `/skill-creator` 为每个用例启动两个并行 subagent(with-skill 和 site-docs),使用下方 prompt 模板 -3. **评分和展示** — `/skill-creator` 负责评分、生成对比报告、启动可视化 viewer 供人工 review -4. **改进 skill** — 根据评分结果和人工 feedback 改进 skill 内容,开启新的 iteration - -**评测对比的两组环境:** - -每个评测用例需要在两种环境下分别运行,对比 skill 是否有效。Prompt 中不应包含任何流程指引(如"先判断使用哪个 skill"),只提供参考资料和访问约束,让 AI 自然行动。 - -| 环境 | system prompt | 可访问范围(prompt 约束) | -| -------------- | ------------------------------------------------------------------------------------- | -------------------------- | -| **with-skill** | `egg/SKILL.md`(入口 skill)的完整内容 | 仅 `packages/skills/` 目录 | -| **site-docs** | 角色声明 + `site/docs/` 的完整文件目录列表(通过 `find site/docs -name '*.md'` 生成) | 仅 `site/docs/` 目录 | - -**Prompt 模板:** - -with-skill 环境: - -```text -你是 EGG 框架开发专家。你只能通过 Read 工具读取 packages/skills/ 目录下的文件,不能访问 site/docs/ 或项目源码。 - -{egg/SKILL.md 的完整内容} - ---- -{eval prompt} -``` - -site-docs 环境: - -```text -你是 EGG 框架开发专家。你只能通过 Read 工具读取 site/docs/ 目录下的文件,不能访问 packages/skills/ 或项目源码。项目文档目录如下: - -{完整的 site/docs/ 文件列表,通过 find site/docs -name '*.md' | sort 生成} - ---- -{eval prompt} -``` - -两组 prompt 的差异仅在于参考资料不同,不包含额外的流程提示。subagent 均具备 Read 工具权限。访问范围通过 prompt 约束(软限制,非技术硬限制)。 - -两组使用相同的 eval prompt,对比输出质量差异。如果 with-skill 没有明显优于 site-docs,说明 skill 内容需要改进——要么缺少文档未覆盖的知识,要么存在与文档的不必要重复。 - -**输出目录:** - -评测结果保存到 `packages/skills/eval/-workspace/iteration-N/` 目录下(已在 `.gitignore` 中通过 `*-workspace/` 忽略),具体目录结构由 `/skill-creator` 管理。 - -**评测用例设计原则:** - -每个 reference 文档至少覆盖 5 个以上评测用例,需覆盖以下场景类型: - -| 场景类型 | 说明 | 示例 | -| -------------------- | --------------------------------------- | -------------------------------------------------------- | -| **泛化需求描述** | 不了解框架术语,用口语化描述需求 | "帮我加个参数校验" | -| **精确需求描述** | 明确指定技术方案和约束 | "用 TypeBox 定义 Schema,email 用 format: email" | -| **使用咨询** | 询问用法、区别、选型 | "Optional 和 Null 有什么区别" | -| **问题排查** | 提供有 bug 的代码(附 files),要求诊断 | "校验跑不起来,帮我看看" | -| **新项目代码生成** | 在全新项目中从零开始生成功能代码 | "帮我写一个创建订单的接口,需要做参数校验" | -| **存量项目代码生成** | 在包含老 egg 代码的项目中生成或迁移代码 | "帮我把这个老的 egg controller 改成 HTTPController 写法" | -| **不常用 API** | 需要查外部文档链接才能回答 | "用 Tuple 定义元组校验" | +@AGENTS.md diff --git a/tegg/AGENTS.md b/tegg/AGENTS.md new file mode 100644 index 0000000000..624ecc6ac6 --- /dev/null +++ b/tegg/AGENTS.md @@ -0,0 +1,308 @@ +# AGENTS.md + +Follow the repository root `AGENTS.md` first. This file adds guidance for work under `tegg/`. + +## Overview + +Tegg is a modular IoC (Inversion of Control) framework for Egg.js, providing dependency injection, lifecycle management, and plugin architecture. It's designed for building large-scale, maintainable Node.js applications using TypeScript decorators. + +**Requirements:** + +- Follow the repo-wide Node.js requirement from the root `package.json` `engines.node` field +- ESM only (no CommonJS) +- egg >= 4.1.0 + +## Monorepo Structure + +**IMPORTANT:** Tegg is part of the main [Egg.js monorepo](https://github.com/eggjs/egg). All build, test, and version management commands should be run from the monorepo root. + +The tegg packages are organized as follows within the main monorepo: + +``` +core/ # 24 core packages - decorators, runtime, metadata, loaders +plugin/ # 10 plugin packages - Egg.js plugins that integrate core functionality +standalone/ # 1 standalone package - standalone runtime without Egg.js +``` + +**Dependency Management:** + +- Uses Utoo workspaces with `catalog:` protocol for shared external dependencies +- Uses `workspace:*` protocol for internal monorepo dependencies (both tegg and egg packages) +- All shared dependency versions are centralized in the root workspace configuration (not in tegg/) +- `catalogMode: prefer` set in root `.npmrc` for automatic catalog usage +- Tegg packages are defined in the root workspace configuration as `tegg/core/*`, `tegg/plugin/*`, `tegg/standalone/*` + +### Key Core Packages + +- **core-decorator**: Basic decorators (`@Inject`, `@ContextProto`, `@SingletonProto`) +- **metadata**: Metadata management for prototypes, modules, and dependency graphs +- **runtime**: Runtime container and object lifecycle management +- **loader**: Module discovery and loading system +- **lifecycle**: Lifecycle hooks and management +- **types**: TypeScript type definitions +- **common-util**: Shared utilities + +### Key Plugin Packages + +- **plugin/tegg**: Main Egg.js plugin integrating tegg runtime +- **plugin/config**: Module configuration support +- **plugin/controller**: HTTP controller decorator support +- **plugin/aop**: AOP runtime integration +- **plugin/eventbus**: Event bus system +- **plugin/schedule**: Scheduled task support +- **plugin/dal**: Data access layer +- **plugin/orm**: Leoric ORM integration + +## Development Commands + +**Note:** All commands below should be run from the **repository root**, not from the tegg directory. + +### Build & Clean + +```bash +utoo run build # Build all packages including tegg +utoo run clean-dist # Clean build artifacts across workspaces that define the script +``` + +### Testing + +All tegg packages use **Vitest** for testing and are integrated with the main Egg.js monorepo test suite. + +```bash +utoo run test # Run vitest tests for all packages (from monorepo root) +utoo run test:cov # Run tests with coverage +utoo run ci # Full CI: vitest with coverage and bail on first failure +``` + +**Note:** Tests are configured in the monorepo root `vitest.config.ts` which includes all tegg packages (`tegg/core/*`, `tegg/plugin/*`, `tegg/standalone/*`). + +### Type Checking & Linting + +```bash +utoo run typecheck # Clean and type check all workspaces (including tegg) +utoo run lint # Run oxlint with type-aware checking on all packages +utoo run fmtcheck # Check code formatting with oxfmt +``` + +**Note:** oxlint automatically runs with `--type-aware` flag for enhanced TypeScript checking. + +### Version Management + +**Note:** Run these commands from the repository root. + +```bash +utoo run version:patch # Bump patch version (0.0.X) +utoo run version:minor # Bump minor version (0.X.0) +utoo run version:major # Bump major version (X.0.0) +utoo run version:prepatch # Bump to next prerelease patch version +utoo run version:preminor # Bump to next prerelease minor version +utoo run version:premajor # Bump to next prerelease major version +utoo run version:alpha # Bump prerelease alpha version +utoo run version:beta # Bump prerelease beta version +utoo run version:rc # Bump prerelease rc version +``` + +### Working with Individual Packages + +**Note:** Run from the monorepo root to work with individual tegg packages. + +```bash +# Install dependencies +utoo install # Install all dependencies using catalog versions + +# Type check a specific package +utoo run --workspace @eggjs/tegg-runtime typecheck + +# Build specific packages through the root tsdown script. +# The -- --workspace flags are forwarded to tsdown, not parsed by Utoo. +utoo run build -- --workspace ./tegg/core/metadata +utoo run build -- --workspace ./tegg/core/runtime +``` + +**Note:** Individual tegg packages don't have test scripts in their package.json. Tests are run via the monorepo root vitest configuration. + +## Architecture Concepts + +### Prototype System + +Tegg uses a prototype-based system where classes are decorated to define how they should be instantiated: + +- **ContextProto**: Instance per request context (scoped to HTTP request) +- **SingletonProto**: Single instance for entire application lifecycle +- **MultiInstanceProto**: Multiple instances of same class with different qualifiers + +Each prototype has: + +- **AccessLevel**: `PRIVATE` (module-only) or `PUBLIC` (globally accessible) +- **InitType**: Defines lifecycle scope (`CONTEXT`, `SINGLETON`) +- **Name**: Instance identifier (defaults to camelCase class name) + +### Dependency Injection + +Dependencies are resolved through `@Inject()` decorator: + +- Property injection: `@Inject() logger: Logger` +- Constructor injection: `constructor(@Inject() logger: Logger)` +- Optional injection: `@InjectOptional()` or `@Inject({ optional: true })` + +**Injection Rules:** + +- ContextProto can inject any prototype +- SingletonProto cannot inject ContextProto +- No circular dependencies allowed (between prototypes or modules) +- Cannot inject `ctx`/`app` directly - inject specific services instead + +### Qualifiers + +When multiple implementations exist, use qualifiers to disambiguate: + +- `@InitTypeQualifier(ObjectInitType.CONTEXT)`: Specify init type +- `@ModuleQualifier('moduleName')`: Specify source module +- `@EggQualifier(EggType.CONTEXT)`: Specify egg context vs app +- Custom qualifiers for dynamic injection patterns + +### Module System + +Modules are organizational units discovered by scanning: + +- `app/modules/` directory (auto-discovered) +- `config/module.json` (manual declaration for npm packages) + +Each module contains: + +- Prototype classes with decorators +- Optional `module.json` or `package.json` with tegg metadata +- Module-level dependencies on other modules + +The **GlobalGraph** builds a dependency graph of all modules and validates: + +- No circular module dependencies +- All prototype dependencies are resolvable +- Access level constraints are respected + +### Lifecycle Hooks + +Objects can implement `EggObjectLifecycle` interface or use decorators: + +- `@LifecyclePostConstruct()`: After constructor +- `@LifecyclePreInject()`: Before dependency injection +- `@LifecyclePostInject()`: After dependency injection +- `@LifecycleInit()`: Custom async initialization +- `@LifecyclePreDestroy()`: Before object destruction +- `@LifecycleDestroy()`: Resource cleanup + +### Runtime Object Management + +The runtime manages object instances through: + +- **EggObjectFactory**: Creates and retrieves object instances +- **LoadUnitInstance**: Manages module instances and their objects +- **EggContext**: Request-scoped context holding ContextProto instances +- **ContextObjectGraph**: Dependency graph for a specific context + +## Testing Patterns + +### Testing with MockApplication + +```typescript +import { MockApplication } from '@eggjs/mock'; + +// Create context scope +await app.mockModuleContextScope(async (ctx: Context) => { + // Get object by class + const service = await ctx.getEggObject(HelloService); + + // Get object by name with qualifiers + const logger = await ctx.getEggObjectFromName('logger', { + qualifier: 'bizLogger', + }); +}); +``` + +### Async Tasks in Tests + +Use `BackgroundTaskHelper` instead of `setTimeout`/`setImmediate`: + +```typescript +@ContextProto() +class MyService { + @Inject() + backgroundTaskHelper: BackgroundTaskHelper; + + async doWork() { + this.backgroundTaskHelper.run(async () => { + // Async work here + }); + } +} +``` + +## Important Implementation Details + +### Metadata Registration + +Decorators register metadata on classes that is later used by the loader: + +- Prototype metadata: `PrototypeUtil.setXXX()` stores on class +- Injection metadata: `InjectObjectInfo` stored per property/parameter +- Qualifier metadata: `QualifierUtil.addProperQualifier()` for disambiguation + +### Loading Process + +1. **Loader** scans directories and discovers modules +2. **EggPrototypeFactory** creates `EggPrototype` from decorated classes +3. **GlobalGraph** validates and builds dependency graph +4. **LoadUnitFactory** creates `LoadUnit` for each module +5. **Runtime** instantiates objects on-demand based on graph + +### Dynamic Injection + +For selecting implementations at runtime: + +```typescript +// Define abstract class and enum +abstract class AbstractHello { abstract hello(): string; } +enum HelloType { FOO = 'FOO', BAR = 'BAR' } + +// Create decorator +const Hello = QualifierImplDecoratorUtil.generatorDecorator( + AbstractHello, + 'HELLO_ATTRIBUTE' +); + +// Apply to implementations +@ContextProto() +@Hello(HelloType.FOO) +class FooHello extends AbstractHello { ... } + +// Get instance dynamically +const impl = await eggObjectFactory.getEggObject( + AbstractHello, + HelloType.FOO +); +``` + +## Common Patterns + +### Creating a New Core Package + +1. Add to `tegg/core/` directory within the main monorepo +2. Include `tsconfig.json` extending `@eggjs/tsconfig` +3. Add standard scripts to `package.json`: + - `"typecheck": "tsgo --noEmit"` +4. Export public API through `src/index.ts` +5. Use `workspace:*` for internal dependencies and `catalog:` for external dependencies + +### Creating a New Plugin + +1. Add to `tegg/plugin/` directory within the main monorepo +2. Define `eggPlugin` in `package.json` with dependencies +3. Create `app.ts` for initialization +4. Add tests using Vitest and `@eggjs/mock` +5. Tests will be automatically discovered by the root `vitest.config.ts` + +### Working with TypeScript + +- Use `emitDecoratorMetadata` for type inference in injection +- `design:type` and `design:paramtypes` are used for automatic dependency resolution +- All packages target ESM with `.js` extensions in imports diff --git a/tegg/CLAUDE.md b/tegg/CLAUDE.md index 6ce219b27b..f6aa6c0262 100644 --- a/tegg/CLAUDE.md +++ b/tegg/CLAUDE.md @@ -1,311 +1,3 @@ # CLAUDE.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Overview - -Tegg is a modular IoC (Inversion of Control) framework for Egg.js, providing dependency injection, lifecycle management, and plugin architecture. It's designed for building large-scale, maintainable Node.js applications using TypeScript decorators. - -**Requirements:** - -- Node.js >= 22.18.0 -- ESM only (no CommonJS) -- egg >= 4.1.0 - -## Monorepo Structure - -**IMPORTANT:** Tegg is part of the main [Egg.js monorepo](https://github.com/eggjs/egg). All build, test, and version management commands should be run from the monorepo root. - -The tegg packages are organized as follows within the main monorepo: - -``` -core/ # 24 core packages - decorators, runtime, metadata, loaders -plugin/ # 10 plugin packages - Egg.js plugins that integrate core functionality -standalone/ # 1 standalone package - standalone runtime without Egg.js -``` - -**Dependency Management:** - -- Uses pnpm workspaces with `catalog:` protocol for shared external dependencies -- Uses `workspace:*` protocol for internal monorepo dependencies (both tegg and egg packages) -- All shared dependency versions centralized in the root `pnpm-workspace.yaml` (not in tegg/) -- `catalogMode: prefer` set in root `.npmrc` for automatic catalog usage -- Tegg packages are defined in root pnpm-workspace.yaml as `tegg/core/*`, `tegg/plugin/*`, `tegg/standalone/*` - -### Key Core Packages - -- **core-decorator**: Basic decorators (`@Inject`, `@ContextProto`, `@SingletonProto`) -- **metadata**: Metadata management for prototypes, modules, and dependency graphs -- **runtime**: Runtime container and object lifecycle management -- **loader**: Module discovery and loading system -- **lifecycle**: Lifecycle hooks and management -- **types**: TypeScript type definitions -- **common-util**: Shared utilities - -### Key Plugin Packages - -- **plugin/tegg**: Main Egg.js plugin integrating tegg runtime -- **plugin/config**: Module configuration support -- **plugin/controller**: HTTP controller decorator support -- **plugin/aop**: AOP runtime integration -- **plugin/eventbus**: Event bus system -- **plugin/schedule**: Scheduled task support -- **plugin/dal**: Data access layer -- **plugin/orm**: Leoric ORM integration - -## Development Commands - -**Note:** All commands below should be run from the **monorepo root** (`../egg`), not from the tegg directory. - -### Build & Clean - -```bash -pnpm run build # Build all packages including tegg (runs build in all workspaces) -pnpm run clean # Clean all build artifacts including tegg (removes dist, tsbuildinfo) -``` - -### Testing - -All tegg packages use **Vitest** for testing and are integrated with the main Egg.js monorepo test suite. - -```bash -pnpm test # Run vitest tests for all packages (from monorepo root) -pnpm run test:cov # Run tests with coverage -pnpm run ci # Full CI: vitest with coverage and bail on first failure -``` - -**Note:** Tests are configured in the monorepo root `vitest.config.ts` which includes all tegg packages (`tegg/core/*`, `tegg/plugin/*`, `tegg/standalone/*`). - -### Type Checking & Linting - -```bash -pnpm run typecheck # Clean and type check all workspaces (including tegg) -pnpm run lint # Run oxlint with type-aware checking on all packages -pnpm run fmtcheck # Check code formatting with oxfmt -``` - -**Note:** oxlint automatically runs with `--type-aware` flag for enhanced TypeScript checking. - -### Version Management - -**Note:** Run these commands from the monorepo root (`../egg`). - -```bash -pnpm run version:patch # Bump patch version (0.0.X) -pnpm run version:minor # Bump minor version (0.X.0) -pnpm run version:major # Bump major version (X.0.0) -pnpm run version:prepatch # Bump to next prerelease patch version -pnpm run version:preminor # Bump to next prerelease minor version -pnpm run version:premajor # Bump to next prerelease major version -pnpm run version:alpha # Bump prerelease alpha version -pnpm run version:beta # Bump prerelease beta version -pnpm run version:rc # Bump prerelease rc version -``` - -### Working with Individual Packages - -**Note:** Run from the monorepo root to work with individual tegg packages. - -```bash -# Install dependencies -pnpm install # Install all dependencies using catalog versions - -# Type check specific packages -pnpm -r run typecheck # Type check all packages recursively -pnpm --filter @eggjs/tegg-runtime run typecheck - -# Build specific packages -pnpm --filter @eggjs/metadata run build -pnpm --filter @eggjs/tegg-runtime run build - -# Clean specific package -pnpm --filter @eggjs/tegg-runtime run clean -``` - -**Note:** Individual tegg packages don't have test scripts in their package.json. Tests are run via the monorepo root vitest configuration. - -## Architecture Concepts - -### Prototype System - -Tegg uses a prototype-based system where classes are decorated to define how they should be instantiated: - -- **ContextProto**: Instance per request context (scoped to HTTP request) -- **SingletonProto**: Single instance for entire application lifecycle -- **MultiInstanceProto**: Multiple instances of same class with different qualifiers - -Each prototype has: - -- **AccessLevel**: `PRIVATE` (module-only) or `PUBLIC` (globally accessible) -- **InitType**: Defines lifecycle scope (`CONTEXT`, `SINGLETON`) -- **Name**: Instance identifier (defaults to camelCase class name) - -### Dependency Injection - -Dependencies are resolved through `@Inject()` decorator: - -- Property injection: `@Inject() logger: Logger` -- Constructor injection: `constructor(@Inject() logger: Logger)` -- Optional injection: `@InjectOptional()` or `@Inject({ optional: true })` - -**Injection Rules:** - -- ContextProto can inject any prototype -- SingletonProto cannot inject ContextProto -- No circular dependencies allowed (between prototypes or modules) -- Cannot inject `ctx`/`app` directly - inject specific services instead - -### Qualifiers - -When multiple implementations exist, use qualifiers to disambiguate: - -- `@InitTypeQualifier(ObjectInitType.CONTEXT)`: Specify init type -- `@ModuleQualifier('moduleName')`: Specify source module -- `@EggQualifier(EggType.CONTEXT)`: Specify egg context vs app -- Custom qualifiers for dynamic injection patterns - -### Module System - -Modules are organizational units discovered by scanning: - -- `app/modules/` directory (auto-discovered) -- `config/module.json` (manual declaration for npm packages) - -Each module contains: - -- Prototype classes with decorators -- Optional `module.json` or `package.json` with tegg metadata -- Module-level dependencies on other modules - -The **GlobalGraph** builds a dependency graph of all modules and validates: - -- No circular module dependencies -- All prototype dependencies are resolvable -- Access level constraints are respected - -### Lifecycle Hooks - -Objects can implement `EggObjectLifecycle` interface or use decorators: - -- `@LifecyclePostConstruct()`: After constructor -- `@LifecyclePreInject()`: Before dependency injection -- `@LifecyclePostInject()`: After dependency injection -- `@LifecycleInit()`: Custom async initialization -- `@LifecyclePreDestroy()`: Before object destruction -- `@LifecycleDestroy()`: Resource cleanup - -### Runtime Object Management - -The runtime manages object instances through: - -- **EggObjectFactory**: Creates and retrieves object instances -- **LoadUnitInstance**: Manages module instances and their objects -- **EggContext**: Request-scoped context holding ContextProto instances -- **ContextObjectGraph**: Dependency graph for a specific context - -## Testing Patterns - -### Testing with MockApplication - -```typescript -import { MockApplication } from '@eggjs/mock'; - -// Create context scope -await app.mockModuleContextScope(async (ctx: Context) => { - // Get object by class - const service = await ctx.getEggObject(HelloService); - - // Get object by name with qualifiers - const logger = await ctx.getEggObjectFromName('logger', { - qualifier: 'bizLogger', - }); -}); -``` - -### Async Tasks in Tests - -Use `BackgroundTaskHelper` instead of `setTimeout`/`setImmediate`: - -```typescript -@ContextProto() -class MyService { - @Inject() - backgroundTaskHelper: BackgroundTaskHelper; - - async doWork() { - this.backgroundTaskHelper.run(async () => { - // Async work here - }); - } -} -``` - -## Important Implementation Details - -### Metadata Registration - -Decorators register metadata on classes that is later used by the loader: - -- Prototype metadata: `PrototypeUtil.setXXX()` stores on class -- Injection metadata: `InjectObjectInfo` stored per property/parameter -- Qualifier metadata: `QualifierUtil.addProperQualifier()` for disambiguation - -### Loading Process - -1. **Loader** scans directories and discovers modules -2. **EggPrototypeFactory** creates `EggPrototype` from decorated classes -3. **GlobalGraph** validates and builds dependency graph -4. **LoadUnitFactory** creates `LoadUnit` for each module -5. **Runtime** instantiates objects on-demand based on graph - -### Dynamic Injection - -For selecting implementations at runtime: - -```typescript -// Define abstract class and enum -abstract class AbstractHello { abstract hello(): string; } -enum HelloType { FOO = 'FOO', BAR = 'BAR' } - -// Create decorator -const Hello = QualifierImplDecoratorUtil.generatorDecorator( - AbstractHello, - 'HELLO_ATTRIBUTE' -); - -// Apply to implementations -@ContextProto() -@Hello(HelloType.FOO) -class FooHello extends AbstractHello { ... } - -// Get instance dynamically -const impl = await eggObjectFactory.getEggObject( - AbstractHello, - HelloType.FOO -); -``` - -## Common Patterns - -### Creating a New Core Package - -1. Add to `tegg/core/` directory within the main monorepo -2. Include `tsconfig.json` extending `@eggjs/tsconfig` -3. Add standard scripts to `package.json`: - - `"typecheck": "tsgo --noEmit"` -4. Export public API through `src/index.ts` -5. Use `workspace:*` for internal dependencies and `catalog:` for external dependencies - -### Creating a New Plugin - -1. Add to `tegg/plugin/` directory within the main monorepo -2. Define `eggPlugin` in `package.json` with dependencies -3. Create `app.ts` for initialization -4. Add tests using Vitest and `@eggjs/mock` -5. Tests will be automatically discovered by the root `vitest.config.ts` - -### Working with TypeScript - -- Use `emitDecoratorMetadata` for type inference in injection -- `design:type` and `design:paramtypes` are used for automatic dependency resolution -- All packages target ESM with `.js` extensions in imports +@AGENTS.md