yq-frontend-skills 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -0
- package/bin/yq-skills.js +55 -0
- package/package.json +31 -0
- package/skills/domains/api/RULES.md +7 -0
- package/skills/domains/component/RULES.md +7 -0
- package/skills/domains/i18n/RULES.md +6 -0
- package/skills/workflows/design-schema/SKILL.md +45 -0
- package/skills/workflows/design-schema/checklist.json +29 -0
- package/skills/workflows/refactor/SKILL.md +34 -0
- package/src/config.js +26 -0
- package/src/register.js +148 -0
- package/src/templates/index.js +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# yq-frontend-skills
|
|
2
|
+
|
|
3
|
+
`yq-frontend-skills` 是一套面向前端开发团队的**全局跨智能体开发技能(Skills)与工作流(Workflows)规范管理框架**。
|
|
4
|
+
|
|
5
|
+
它旨在解决团队在使用各大智能体开发工具(Cursor、Claude Code 等)时出现“盲目写代码 (Vibe Coding)”的问题,强制要求在开发前进行头脑风暴与方案设计评审。通过**全局用户级分发**机制,做到前端项目目录 **零文件污染**、**零 Git 提交**,且**一处更新,所有开发环境同步生效**。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🌟 核心特性
|
|
10
|
+
|
|
11
|
+
* 🚀 **全局原生免污染**:技能文件物理分发到开发者的系统 Home 用户目录下,无需在前端业务项目中物理拷贝文件或建立软链,保障 Git 代码仓库 100% 纯净。
|
|
12
|
+
* 🔄 **跨智能体对齐**:统一适配 Cursor、Claude Code、Codex 的全局 `SKILL.md` 标准,以及 Gemini/Antigravity 的全局 `Workflow` 标准与 OpenCode 的全局 `AGENTS.md` 规范。
|
|
13
|
+
* 🛑 **门控状态机流控制 (Checkpoints)**:内置 `yq-design-schema`(前端方案制定)和 `yq-refactor`(安全重构)核心任务流,用阶段门控(如未通过方案评审严禁调用编码工具)纠正 AI 编码习惯。
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 🛠️ 支持的智能体工具及全局路径
|
|
18
|
+
|
|
19
|
+
| 智能体工具 | 全局加载路径 | 装载类型 |
|
|
20
|
+
| :--- | :--- | :--- |
|
|
21
|
+
| **Claude Code** | `~/.claude/skills/` | 原生全局 `SKILL.md` 个人技能 |
|
|
22
|
+
| **Cursor** | `~/.cursor/skills/` | 原生全局 `SKILL.md` 个人技能 |
|
|
23
|
+
| **Codex CLI / App** | `~/.codex/skills/` | 原生全局 `SKILL.md` 个人技能 |
|
|
24
|
+
| **Gemini / Antigravity** | `~/.gemini/config/global_workflows/` | 全局 Markdown 任务工作流 |
|
|
25
|
+
| **OpenCode** | `~/.config/opencode/` | 全局 `AGENTS.md` 前端宪法 |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 💾 安装与使用
|
|
30
|
+
|
|
31
|
+
### 1. 全局安装
|
|
32
|
+
|
|
33
|
+
通过 NPM 全局安装该工具包:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install -g yq-frontend-skills
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. 全局智能体技能注册
|
|
40
|
+
|
|
41
|
+
安装完成后,在终端的任何路径下执行以下命令。工具会自动识别您系统当前已配置的智能体,并将核心技能与工作流编译分发至对应的全局路径下:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
yq-skills register
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 3. 一键同步与覆盖更新
|
|
48
|
+
|
|
49
|
+
当 `yq-frontend-skills` 发布新版本更新了前端开发规范时,开发人员只需运行包更新,并执行一键同步覆盖,本地所有关联智能体的技能就会同步升级:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm update -g yq-frontend-skills
|
|
53
|
+
yq-skills sync
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 🚀 内置核心工作流
|
|
59
|
+
|
|
60
|
+
### 1. `/yq-design-schema` (前端方案制定)
|
|
61
|
+
强制约束智能体在接到需求后,必须按以下步骤推进,不得擅自修改代码:
|
|
62
|
+
1. **Phase 1: Brainstorming (头脑风暴)**:探索当前项目依赖与副作用,识别并提出未明确的疑问。
|
|
63
|
+
2. **Phase 2: Planning (方案设计)**:编写并向用户汇报包含接口契约、组件拆分 (Mermaid 图) 及 TODO 任务列表的技术设计方案。
|
|
64
|
+
3. **Phase 3: Review (方案评审 - 门控点)**:**强制禁止**调用任何代码修改工具,等待用户阅读并回复“批准”。
|
|
65
|
+
4. **Phase 4: Implementation (执行实施)**:获得批准后,小步快跑地实施方案。
|
|
66
|
+
5. **Phase 5: Verification (方案校验)**:执行构建、类型检查与单元测试,输出修改日志链接。
|
|
67
|
+
|
|
68
|
+
### 2. `/yq-refactor` (安全重构)
|
|
69
|
+
引导智能体安全、高内聚地优化现有代码:
|
|
70
|
+
1. **Step 1: Bad Smell Identification**:定位长方法、超大组件等坏味道,梳理依赖。
|
|
71
|
+
2. **Step 2: Extract & Abstract**:抽离逻辑 hooks 或是子 UI 原子组件,保证职责单一。
|
|
72
|
+
3. **Step 3: Replace & Verify**:对原位置进行平滑替换,回归测试保证不改变原有外部功能行为。
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## ❓ 常见问题 (FAQ)
|
|
77
|
+
|
|
78
|
+
### Q: 运行了 `yq-skills register` 后,为什么智能体无法调出 `/yq-design-schema`?
|
|
79
|
+
**A**: 智能体工具(包括 Antigravity IDE、Claude Code、Cursor 等)的全局技能和工作流是在**会话(Session)冷启动时一次性载入内存的**。已启动的终端或 IDE 会话无法实时刷新,请**关闭当前会话/终端窗口并重新打开一个新的会话**,即可成功加载并唤起新技能。
|
|
80
|
+
|
|
81
|
+
### Q: 如果我想修改团队的方案评估清单(Checklist)该怎么办?
|
|
82
|
+
**A**: 全局技能包内置了 `skills/workflows/design-schema/checklist.json` 规范清单,团队 Leader 可以将该项目 fork 后进行定制,然后发布到私有 NPM 源上供团队更新使用。
|
package/bin/yq-skills.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { registerSkills } from '../src/register.js';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
|
|
11
|
+
// 读取版本号
|
|
12
|
+
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
13
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
14
|
+
|
|
15
|
+
const args = process.argv.slice(2);
|
|
16
|
+
const command = args[0];
|
|
17
|
+
|
|
18
|
+
function printHelp() {
|
|
19
|
+
console.log(`
|
|
20
|
+
yq-frontend-skills v${pkg.version}
|
|
21
|
+
前端智能体全局开发技能管理工具
|
|
22
|
+
|
|
23
|
+
用法:
|
|
24
|
+
yq-skills <command>
|
|
25
|
+
|
|
26
|
+
可用命令:
|
|
27
|
+
register 向系统已安装的智能体(Cursor, Claude, Codex, Gemini 等)注册全局前端方案技能
|
|
28
|
+
sync 同 register,重新读取核心规范并强制更新覆盖全局配置
|
|
29
|
+
--version, -v 打印版本号
|
|
30
|
+
--help, -h 打印此帮助信息
|
|
31
|
+
`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
switch (command) {
|
|
35
|
+
case 'register':
|
|
36
|
+
case 'sync':
|
|
37
|
+
registerSkills();
|
|
38
|
+
break;
|
|
39
|
+
|
|
40
|
+
case '--version':
|
|
41
|
+
case '-v':
|
|
42
|
+
console.log(`v${pkg.version}`);
|
|
43
|
+
break;
|
|
44
|
+
|
|
45
|
+
case '--help':
|
|
46
|
+
case '-h':
|
|
47
|
+
case undefined:
|
|
48
|
+
printHelp();
|
|
49
|
+
break;
|
|
50
|
+
|
|
51
|
+
default:
|
|
52
|
+
console.error(`未知命令: ${command}`);
|
|
53
|
+
printHelp();
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "yq-frontend-skills",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A cross-agent global workflows and skills framework for frontend design schema.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"yq-skills": "bin/yq-skills.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"src",
|
|
13
|
+
"skills",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "echo \"Error: no test specified\" && exit 0"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"cursor",
|
|
21
|
+
"claude",
|
|
22
|
+
"codex",
|
|
23
|
+
"gemini",
|
|
24
|
+
"opencode",
|
|
25
|
+
"skills",
|
|
26
|
+
"workflows",
|
|
27
|
+
"frontend"
|
|
28
|
+
],
|
|
29
|
+
"author": "",
|
|
30
|
+
"license": "MIT"
|
|
31
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: yq-design-schema
|
|
3
|
+
description: 协助前端团队在开发新功能、修改 API 或重构组件前,制定规范、清晰的技术方案,确保架构合理与协作通畅。
|
|
4
|
+
globs:
|
|
5
|
+
- "**/*.js"
|
|
6
|
+
- "**/*.ts"
|
|
7
|
+
- "**/*.vue"
|
|
8
|
+
- "**/*.tsx"
|
|
9
|
+
- "**/*.jsx"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# 前端方案制定工作流 (yq-design-schema)
|
|
13
|
+
|
|
14
|
+
本工作流旨在规范智能体(AI)的编码流程,防止未经理性设计而直接进入代码实现。在进行任何代码修改前,智能体**必须**遵循以下五个阶段:
|
|
15
|
+
|
|
16
|
+
## 阶段流程与门控 (Gates & Checkpoints)
|
|
17
|
+
|
|
18
|
+
### Phase 1: Brainstorming (需求探索与头脑风暴)
|
|
19
|
+
当接收到用户的需求或 bug 修复任务时,不要立即进入代码修改。你应当:
|
|
20
|
+
1. **分析现状**:理清当前涉及到的文件路径、已有逻辑以及技术依赖关系。
|
|
21
|
+
2. **评估副作用**:评估此次修改是否会影响现有的组件、状态管理或公共 API。
|
|
22
|
+
3. **识别疑问**:若需求描述不清或技术边界模糊,应当整理出疑问向用户确认。
|
|
23
|
+
4. **验证门控**:完成此阶段后,方可启动 Phase 2。
|
|
24
|
+
|
|
25
|
+
### Phase 2: Planning (技术方案设计)
|
|
26
|
+
本阶段需要制定详细的实现方案,输出清晰的架构文档。方案必须包括:
|
|
27
|
+
1. **数据模型与状态流**:新设计的数据结构和组件状态流向。
|
|
28
|
+
2. **API 接口契约**:如涉及新旧接口对接,需写明入参、出参和 Mock 契约。
|
|
29
|
+
3. **组件设计**:组件的拓扑结构与职责划分(建议使用 Mermaid 图表达)。
|
|
30
|
+
4. **重构/修改步骤**:列出清晰的 TODO 计划列表。
|
|
31
|
+
5. **门控说明**:方案制定后,**必须**输出一份清晰的技术方案文档并呈现给用户。
|
|
32
|
+
|
|
33
|
+
### Phase 3: Review (方案评审)
|
|
34
|
+
* **强制约束**:在此阶段,智能体**被禁止**调用任何代码编写或文件修改工具。
|
|
35
|
+
* **门控条件**:必须等待用户阅读你的 Planning 方案。当且仅当用户回复“批准”或“确认”后,方可进入 Phase 4 实施阶段。
|
|
36
|
+
|
|
37
|
+
### Phase 4: Implementation (执行实施)
|
|
38
|
+
根据已经过评审的方案计划,开始编写代码。在这个过程中:
|
|
39
|
+
1. 保持小步快跑,每个逻辑单元修改后应及时自我 review。
|
|
40
|
+
2. 遇到未预料到的阻碍时,应立即停止,更新 Planning 方案并重新报审,不得擅自修改评审范围外的代码。
|
|
41
|
+
|
|
42
|
+
### Phase 5: Verification (方案校验)
|
|
43
|
+
开发完成后,必须进行质量校验:
|
|
44
|
+
1. 运行项目内置的编译、类型检查或单元测试命令。
|
|
45
|
+
2. 提供明确的修改日志(Walkthrough)并指出修改的核心文件链接,供用户做最终审查。
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "frontend-design-checklist",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"categories": [
|
|
5
|
+
{
|
|
6
|
+
"name": "Architecture & Clean Code",
|
|
7
|
+
"items": [
|
|
8
|
+
"是否遵循单一职责原则拆分组件?",
|
|
9
|
+
"是否对现有业务逻辑引入了副作用(Side-effects)?",
|
|
10
|
+
"组件或函数是否有不必要的耦合?"
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "API & Data flow",
|
|
15
|
+
"items": [
|
|
16
|
+
"API 契约是否已与后端对齐,是否存在入参/出参模糊字段?",
|
|
17
|
+
"对于暂未上线的 API,是否定义了本地 Mock 数据?",
|
|
18
|
+
"状态管理流向是否单一,是否存在冗余数据源?"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": "I18n & Assets",
|
|
23
|
+
"items": [
|
|
24
|
+
"所有新增和修改的文案,是否全部抽离到了多语言词条中?",
|
|
25
|
+
"是否使用了项目中已有的公共图标和静态资源?"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: yq-refactor
|
|
3
|
+
description: 协助前端团队进行模块重构、组件抽取、废弃代码清理,确保重构过程的安全与高内聚。
|
|
4
|
+
globs:
|
|
5
|
+
- "**/*.js"
|
|
6
|
+
- "**/*.ts"
|
|
7
|
+
- "**/*.vue"
|
|
8
|
+
- "**/*.tsx"
|
|
9
|
+
- "**/*.jsx"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# 前端安全重构工作流 (yq-refactor)
|
|
13
|
+
|
|
14
|
+
重构的目的是在**不改变软件外部行为**的前提下,提高代码的可读性、可维护性和复用性。本工作流定义了重构时的规范步骤:
|
|
15
|
+
|
|
16
|
+
## 重构基本守则 (Refactoring Principles)
|
|
17
|
+
|
|
18
|
+
1. **小步修改**:单次重构范围应控制在最小业务单元内,切忌把“重构”演变成“重写”。
|
|
19
|
+
2. **测试守护**:在开始重构前,如果可能,请确保重构目标模块已覆盖了足够的单元测试或手工验证流程,重构后必须确保原有功能行为 100% 保持一致。
|
|
20
|
+
3. **DRY 准则**:在抽离公共函数或组件时,遵循 Don't Repeat Yourself,优先复用,并进行合理的抽象。
|
|
21
|
+
|
|
22
|
+
## 重构实施步骤 (Steps)
|
|
23
|
+
|
|
24
|
+
### Step 1: Bad Smell Identification (识别重构目标)
|
|
25
|
+
1. 找出长函数、上帝类、超大组件、重复文案或杂乱的状态流转。
|
|
26
|
+
2. 梳理它的依赖链,做好备忘。
|
|
27
|
+
|
|
28
|
+
### Step 2: Extract & Abstract (抽取与解耦)
|
|
29
|
+
1. 将复杂的业务逻辑抽取为高内聚的 hooks 或纯函数。
|
|
30
|
+
2. 将超大视图组件拆分为可复用的原子组件,通过 props 进行清晰的控制。
|
|
31
|
+
|
|
32
|
+
### Step 3: Replace & Verify (替换与回归测试)
|
|
33
|
+
1. 使用新抽离的组件/函数,在原位置做平滑替换。
|
|
34
|
+
2. 运行构建脚本与类型检查,验证代码在浏览器中的表现,确保没有任何渲染或控制报错。
|
package/src/config.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 获取各大智能体在本地系统上的全局配置绝对路径
|
|
6
|
+
*/
|
|
7
|
+
export function getAgentPaths() {
|
|
8
|
+
const home = os.homedir();
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
// Claude Code 全局技能目录
|
|
12
|
+
claude: path.join(home, '.claude', 'skills'),
|
|
13
|
+
|
|
14
|
+
// Cursor 全局技能目录
|
|
15
|
+
cursor: path.join(home, '.cursor', 'skills'),
|
|
16
|
+
|
|
17
|
+
// Codex 全局技能目录
|
|
18
|
+
codex: path.join(home, '.codex', 'skills'),
|
|
19
|
+
|
|
20
|
+
// Gemini / Antigravity 全局 workflow 目录
|
|
21
|
+
gemini: path.join(home, '.gemini', 'config', 'global_workflows'),
|
|
22
|
+
|
|
23
|
+
// OpenCode 全局规则目录
|
|
24
|
+
opencode: path.join(home, '.config', 'opencode')
|
|
25
|
+
};
|
|
26
|
+
}
|
package/src/register.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { getAgentPaths } from './config.js';
|
|
5
|
+
import { formatSkill } from './templates/index.js';
|
|
6
|
+
|
|
7
|
+
// 获取当前文件及项目的根目录(适用于 ES Module)
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
const projectRoot = path.join(__dirname, '..');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 极简的 YAML Frontmatter 解析器,避免引入外部依赖
|
|
14
|
+
* @param {string} content 原始 Markdown 文本
|
|
15
|
+
*/
|
|
16
|
+
function parseFrontmatter(content) {
|
|
17
|
+
const fmRegex = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;
|
|
18
|
+
const match = content.match(fmRegex);
|
|
19
|
+
|
|
20
|
+
if (!match) {
|
|
21
|
+
return { frontmatter: {}, markdown: content };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const yamlStr = match[1];
|
|
25
|
+
const markdown = match[2];
|
|
26
|
+
const frontmatter = {};
|
|
27
|
+
|
|
28
|
+
const lines = yamlStr.split(/\r?\n/);
|
|
29
|
+
let currentKey = null;
|
|
30
|
+
|
|
31
|
+
for (const line of lines) {
|
|
32
|
+
const trimmed = line.trim();
|
|
33
|
+
if (!trimmed) continue;
|
|
34
|
+
|
|
35
|
+
if (trimmed.startsWith('-')) {
|
|
36
|
+
if (currentKey && Array.isArray(frontmatter[currentKey])) {
|
|
37
|
+
const val = trimmed.substring(1).trim().replace(/^["']|["']$/g, '');
|
|
38
|
+
frontmatter[currentKey].push(val);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
const idx = trimmed.indexOf(':');
|
|
42
|
+
if (idx !== -1) {
|
|
43
|
+
const key = trimmed.substring(0, idx).trim();
|
|
44
|
+
const value = trimmed.substring(idx + 1).trim().replace(/^["']|["']$/g, '');
|
|
45
|
+
if (value === '') {
|
|
46
|
+
frontmatter[key] = [];
|
|
47
|
+
currentKey = key;
|
|
48
|
+
} else {
|
|
49
|
+
frontmatter[key] = value;
|
|
50
|
+
currentKey = null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { frontmatter, markdown };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 执行全局技能的注册与同步物理分发
|
|
61
|
+
*/
|
|
62
|
+
export function registerSkills() {
|
|
63
|
+
const agentPaths = getAgentPaths();
|
|
64
|
+
const skillsDir = path.join(projectRoot, 'skills', 'workflows');
|
|
65
|
+
|
|
66
|
+
console.log('\x1b[36m%s\x1b[0m', '>> 开始全局分发 yq-frontend-skills 前端方案制定技能...');
|
|
67
|
+
|
|
68
|
+
// 1. 读取并解析核心 Workflows 下的所有技能
|
|
69
|
+
if (!fs.existsSync(skillsDir)) {
|
|
70
|
+
console.error(`[Error] 找不到技能目录: ${skillsDir}`);
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const skillDirs = fs.readdirSync(skillsDir).filter(name => {
|
|
75
|
+
return fs.statSync(path.join(skillsDir, name)).isDirectory();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const parsedSkills = [];
|
|
79
|
+
|
|
80
|
+
for (const skillName of skillDirs) {
|
|
81
|
+
const skillPath = path.join(skillsDir, skillName, 'SKILL.md');
|
|
82
|
+
if (!fs.existsSync(skillPath)) continue;
|
|
83
|
+
|
|
84
|
+
const rawContent = fs.readFileSync(skillPath, 'utf-8');
|
|
85
|
+
const { frontmatter, markdown } = parseFrontmatter(rawContent);
|
|
86
|
+
|
|
87
|
+
parsedSkills.push({
|
|
88
|
+
dirName: skillName,
|
|
89
|
+
frontmatter,
|
|
90
|
+
markdown
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 2. 分发至各智能体的全局目录
|
|
95
|
+
// 适配 Cursor, Claude Code, Codex (它们使用统一的子目录 + SKILL.md 格式)
|
|
96
|
+
const fileBasedAgents = ['cursor', 'claude', 'codex'];
|
|
97
|
+
for (const agent of fileBasedAgents) {
|
|
98
|
+
const destDir = agentPaths[agent];
|
|
99
|
+
try {
|
|
100
|
+
for (const skill of parsedSkills) {
|
|
101
|
+
const targetSkillDir = path.join(destDir, skill.dirName);
|
|
102
|
+
fs.mkdirSync(targetSkillDir, { recursive: true });
|
|
103
|
+
|
|
104
|
+
const formattedContent = formatSkill(agent, skill.frontmatter, skill.markdown);
|
|
105
|
+
fs.writeFileSync(path.join(targetSkillDir, 'SKILL.md'), formattedContent, 'utf-8');
|
|
106
|
+
|
|
107
|
+
console.log(`[${agent.toUpperCase()}] 技能已成功注册 => ${path.join(targetSkillDir, 'SKILL.md')}`);
|
|
108
|
+
}
|
|
109
|
+
} catch (err) {
|
|
110
|
+
console.warn(`\x1b[33m[警告] 无法为 ${agent} 注册技能,路径可能不可写: ${destDir} (错误: ${err.message})\x1b[0m`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 适配 Gemini / Antigravity (使用单一 markdown 文件放在 global_workflows 下)
|
|
115
|
+
try {
|
|
116
|
+
const destDir = agentPaths.gemini;
|
|
117
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
118
|
+
for (const skill of parsedSkills) {
|
|
119
|
+
const formattedContent = formatSkill('gemini', skill.frontmatter, skill.markdown);
|
|
120
|
+
const targetFilePath = path.join(destDir, `${skill.frontmatter.name || skill.dirName}.md`);
|
|
121
|
+
fs.writeFileSync(targetFilePath, formattedContent, 'utf-8');
|
|
122
|
+
console.log(`[GEMINI] 工作流已成功注册 => ${targetFilePath}`);
|
|
123
|
+
}
|
|
124
|
+
} catch (err) {
|
|
125
|
+
console.warn(`\x1b[33m[警告] 无法为 Gemini 注册工作流,路径可能不可写: ${agentPaths.gemini} (错误: ${err.message})\x1b[0m`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 适配 OpenCode (使用统一的 AGENTS.md 存放在 opencode 全局配置目录下)
|
|
129
|
+
try {
|
|
130
|
+
const destDir = agentPaths.opencode;
|
|
131
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
132
|
+
|
|
133
|
+
// 合并所有的技能生成一份全局 AGENTS.md
|
|
134
|
+
let combinedAgentsMd = '# OpenCode 前端规范宪法 (AGENTS.md)\n\n';
|
|
135
|
+
for (const skill of parsedSkills) {
|
|
136
|
+
combinedAgentsMd += formatSkill('opencode', skill.frontmatter, skill.markdown) + '\n\n---\n\n';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const targetFilePath = path.join(destDir, 'AGENTS.md');
|
|
140
|
+
fs.writeFileSync(targetFilePath, combinedAgentsMd, 'utf-8');
|
|
141
|
+
console.log(`[OPENCODE] 全局 AGENTS.md 已成功注册 => ${targetFilePath}`);
|
|
142
|
+
} catch (err) {
|
|
143
|
+
console.warn(`\x1b[33m[警告] 无法为 OpenCode 注册规则,路径可能不可写: ${agentPaths.opencode} (错误: ${err.message})\x1b[0m`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log('\x1b[32m%s\x1b[0m', '>> 全局技能注册与同步成功!所有关联智能体已装载最新前端制定方案规范。');
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 针对各智能体格式,将原始 Frontmatter 和 Markdown 内容转换并包裹为符合其要求的技能文件
|
|
3
|
+
* @param {string} agentType 智能体类型 ('claude' | 'cursor' | 'codex' | 'gemini' | 'opencode')
|
|
4
|
+
* @param {object} frontmatter 包含 name, description, globs 等字段的元数据
|
|
5
|
+
* @param {string} markdown 核心的 markdown 指导说明
|
|
6
|
+
* @returns {string} 包装适配后的文件字符串
|
|
7
|
+
*/
|
|
8
|
+
export function formatSkill(agentType, frontmatter, markdown) {
|
|
9
|
+
// Cursor, Claude Code, Codex 对全局 SKILL.md 使用一致的 YAML Frontmatter 标准
|
|
10
|
+
if (['cursor', 'claude', 'codex'].includes(agentType)) {
|
|
11
|
+
const yamlHeader = [
|
|
12
|
+
'---',
|
|
13
|
+
`name: ${frontmatter.name || ''}`,
|
|
14
|
+
`description: ${frontmatter.description || ''}`,
|
|
15
|
+
'globs:',
|
|
16
|
+
...(frontmatter.globs || []).map(glob => ` - "${glob}"`),
|
|
17
|
+
'---',
|
|
18
|
+
''
|
|
19
|
+
].join('\n');
|
|
20
|
+
|
|
21
|
+
return `${yamlHeader}${markdown}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Gemini / Antigravity 适用于带 description frontmatter 的 markdown 格式
|
|
25
|
+
if (agentType === 'gemini') {
|
|
26
|
+
const yamlHeader = [
|
|
27
|
+
'---',
|
|
28
|
+
`description: ${frontmatter.description || ''}`,
|
|
29
|
+
'---',
|
|
30
|
+
''
|
|
31
|
+
].join('\n');
|
|
32
|
+
return `${yamlHeader}${markdown}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// OpenCode 等全局规则格式
|
|
36
|
+
if (agentType === 'opencode') {
|
|
37
|
+
return `# Global Rules: ${frontmatter.name || ''}\n\n${markdown}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 默认直接返回内容
|
|
41
|
+
return markdown;
|
|
42
|
+
}
|