ai-workflow-init 1.3.0 → 1.3.1
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 +27 -7
- package/cli.js +162 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,24 +7,44 @@ Initialize standardized AI workflow docs and command templates into ANY reposito
|
|
|
7
7
|
> Requires: [Node.js](https://nodejs.org/) (>= 14)
|
|
8
8
|
|
|
9
9
|
Run in the root of your target project:
|
|
10
|
+
|
|
10
11
|
```bash
|
|
11
12
|
npx ai-workflow-init
|
|
12
13
|
```
|
|
13
|
-
|
|
14
|
+
|
|
15
|
+
The installer will prompt you to select which AI tool(s) to configure:
|
|
16
|
+
|
|
17
|
+
- **1. Cursor** → installs `.cursor/commands` and `.cursor/prompts`
|
|
18
|
+
- **2. GitHub Copilot** → installs `.github/prompts`
|
|
19
|
+
- **3. Both** → installs both command sets and prompts
|
|
20
|
+
|
|
21
|
+
All installations include:
|
|
22
|
+
|
|
14
23
|
- `docs/ai` (planning, implementation, testing, project standards)
|
|
15
|
-
-
|
|
16
|
-
|
|
24
|
+
- `AGENTS.md` with rules and workflow overview
|
|
25
|
+
|
|
26
|
+
## Smart Installation Features
|
|
27
|
+
|
|
28
|
+
- **Protected Files**: Core documentation files (`CODE_CONVENTIONS.md`, `PROJECT_STRUCTURE.md`) are never overwritten if they already exist
|
|
29
|
+
- **Selective Updates**: Only `template-feature.md` and `README.md` files are updated in each documentation subfolder
|
|
30
|
+
- **Safe Cloning**: Uses temporary directories to ensure no data loss
|
|
17
31
|
|
|
18
32
|
## Notes
|
|
33
|
+
|
|
19
34
|
- Works on Windows (PowerShell/CMD/Git Bash), macOS, and Linux.
|
|
20
|
-
- If the destination folders already exist, the installer will overwrite files as needed.
|
|
21
35
|
- After installation, commit the new files to your repository so your team can use them.
|
|
22
36
|
|
|
23
37
|
## What gets installed
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
38
|
+
|
|
39
|
+
- **Always installed**:
|
|
40
|
+
- Documentation templates and guides under `docs/ai/`
|
|
41
|
+
- `AGENTS.md` with rules and workflow overview
|
|
42
|
+
- **Based on your choice**:
|
|
43
|
+
- `.cursor/commands/` and `.cursor/prompts/` (if Cursor is selected)
|
|
44
|
+
- `.github/prompts/` (if GitHub Copilot is selected)
|
|
27
45
|
|
|
28
46
|
## Troubleshooting
|
|
47
|
+
|
|
29
48
|
- Ensure Node.js is installed and accessible in your PATH.
|
|
30
49
|
- If your network blocks npm registry calls, try again on a different network or with a VPN.
|
|
50
|
+
- Ensure you have write permissions in your project directory.
|
package/cli.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { execSync } = require("child_process");
|
|
4
|
-
const { existsSync, mkdirSync } = require("fs");
|
|
4
|
+
const { existsSync, mkdirSync, rmSync, cpSync, readdirSync } = require("fs");
|
|
5
5
|
const readline = require("readline");
|
|
6
|
+
const path = require("path");
|
|
6
7
|
|
|
7
8
|
// Repo workflow gốc của bạn
|
|
8
9
|
const REPO = "phananhtuan09/ai-agent-workflow";
|
|
@@ -23,13 +24,149 @@ function run(cmd) {
|
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
// Clone folder luôn ghi đè
|
|
28
|
+
function cloneFolderForce(source, dest) {
|
|
29
|
+
mkdirSync(path.dirname(dest), { recursive: true });
|
|
30
|
+
const tempDir = path.join(dest, ".temp-clone");
|
|
31
|
+
|
|
32
|
+
// Xóa temp folder nếu tồn tại
|
|
33
|
+
if (existsSync(tempDir)) {
|
|
34
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
run(`npx degit ${source} ${tempDir} --force`);
|
|
38
|
+
|
|
39
|
+
// Tạo dest folder nếu chưa có
|
|
40
|
+
if (!existsSync(dest)) {
|
|
41
|
+
mkdirSync(dest, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Copy tất cả files từ temp vào dest (ghi đè toàn bộ)
|
|
45
|
+
const filesToCopy = execSync(`find ${tempDir} -type f`, { encoding: "utf8" })
|
|
46
|
+
.trim()
|
|
47
|
+
.split("\n")
|
|
48
|
+
.filter(Boolean);
|
|
49
|
+
|
|
50
|
+
for (const file of filesToCopy) {
|
|
51
|
+
const relativePath = path.relative(tempDir, file);
|
|
52
|
+
const destFile = path.join(dest, relativePath);
|
|
53
|
+
|
|
54
|
+
// Tạo folder nếu cần
|
|
55
|
+
mkdirSync(path.dirname(destFile), { recursive: true });
|
|
56
|
+
|
|
57
|
+
// Copy file với ghi đè
|
|
58
|
+
cpSync(file, destFile, { force: true });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Xóa temp folder
|
|
62
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Clone folder docs/ai một cách an toàn
|
|
66
|
+
function cloneDocsAI(source, dest) {
|
|
67
|
+
mkdirSync(dest, { recursive: true });
|
|
68
|
+
const tempDir = path.join(dest, ".temp-clone");
|
|
69
|
+
|
|
70
|
+
// Xóa temp folder nếu tồn tại
|
|
71
|
+
if (existsSync(tempDir)) {
|
|
72
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
run(`npx degit ${source} ${tempDir} --force`);
|
|
76
|
+
|
|
77
|
+
// Xử lý từng subfolder
|
|
78
|
+
const subfolders = ["implementation", "planning", "testing"];
|
|
79
|
+
|
|
80
|
+
// Xử lý folders: implementation, planning, testing
|
|
81
|
+
for (const subfolder of subfolders) {
|
|
82
|
+
const tempSubfolder = path.join(tempDir, subfolder);
|
|
83
|
+
const destSubfolder = path.join(dest, subfolder);
|
|
84
|
+
|
|
85
|
+
if (existsSync(tempSubfolder)) {
|
|
86
|
+
mkdirSync(destSubfolder, { recursive: true });
|
|
87
|
+
|
|
88
|
+
// Chỉ copy file template và README.md
|
|
89
|
+
const filesToCopy = ["README.md", "feature-template.md"];
|
|
31
90
|
|
|
91
|
+
for (const file of filesToCopy) {
|
|
92
|
+
const srcFile = path.join(tempSubfolder, file);
|
|
93
|
+
const destFile = path.join(destSubfolder, file);
|
|
94
|
+
|
|
95
|
+
if (existsSync(srcFile)) {
|
|
96
|
+
cpSync(srcFile, destFile, { force: true });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Xử lý folder: project
|
|
103
|
+
const tempProject = path.join(tempDir, "project");
|
|
104
|
+
const destProject = path.join(dest, "project");
|
|
105
|
+
|
|
106
|
+
if (existsSync(tempProject)) {
|
|
107
|
+
mkdirSync(destProject, { recursive: true });
|
|
108
|
+
|
|
109
|
+
// 1. Chỉ tạo CODE_CONVENTIONS.md và PROJECT_STRUCTURE.md nếu chưa có
|
|
110
|
+
const protectedFiles = [
|
|
111
|
+
"CODE_CONVENTIONS.md",
|
|
112
|
+
"PROJECT_STRUCTURE.md",
|
|
113
|
+
"README.md",
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
for (const file of protectedFiles) {
|
|
117
|
+
const srcFile = path.join(tempProject, file);
|
|
118
|
+
const destFile = path.join(destProject, file);
|
|
119
|
+
|
|
120
|
+
if (existsSync(srcFile)) {
|
|
121
|
+
// Nếu là CODE_CONVENTIONS.md hoặc PROJECT_STRUCTURE.md, chỉ tạo nếu chưa có
|
|
122
|
+
if (
|
|
123
|
+
(file === "CODE_CONVENTIONS.md" || file === "PROJECT_STRUCTURE.md") &&
|
|
124
|
+
existsSync(destFile)
|
|
125
|
+
) {
|
|
126
|
+
console.log(`⏭️ Skipping (already exists): docs/ai/project/${file}`);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Các file khác luôn ghi đè
|
|
131
|
+
cpSync(srcFile, destFile, { force: true });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 2. Ghi đè folder template-convention
|
|
136
|
+
const tempTemplateConvention = path.join(
|
|
137
|
+
tempProject,
|
|
138
|
+
"template-convention"
|
|
139
|
+
);
|
|
140
|
+
const destTemplateConvention = path.join(
|
|
141
|
+
destProject,
|
|
142
|
+
"template-convention"
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (existsSync(tempTemplateConvention)) {
|
|
146
|
+
// Xóa folder cũ nếu tồn tại
|
|
147
|
+
if (existsSync(destTemplateConvention)) {
|
|
148
|
+
rmSync(destTemplateConvention, { recursive: true, force: true });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Copy folder mới
|
|
152
|
+
cpSync(tempTemplateConvention, destTemplateConvention, {
|
|
153
|
+
recursive: true,
|
|
154
|
+
force: true,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Xóa temp folder
|
|
160
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Hỏi user chọn IDE
|
|
32
164
|
function askIDE() {
|
|
165
|
+
const rl = readline.createInterface({
|
|
166
|
+
input: process.stdin,
|
|
167
|
+
output: process.stdout,
|
|
168
|
+
});
|
|
169
|
+
|
|
33
170
|
return new Promise((resolve) => {
|
|
34
171
|
console.log("\n🤖 Which AI tool(s) do you want to setup?");
|
|
35
172
|
console.log("1. Cursor");
|
|
@@ -53,15 +190,11 @@ async function main() {
|
|
|
53
190
|
process.exit(1);
|
|
54
191
|
}
|
|
55
192
|
|
|
56
|
-
//
|
|
57
|
-
if (!existsSync("docs/ai")) {
|
|
58
|
-
mkdirSync("docs/ai", { recursive: true });
|
|
59
|
-
}
|
|
60
|
-
|
|
193
|
+
// Clone docs/ai một cách an toàn, bảo vệ các file quan trọng
|
|
61
194
|
step("🚚 Downloading workflow template (docs/ai)...");
|
|
62
|
-
|
|
195
|
+
cloneDocsAI(`${REPO}/docs/ai`, "docs/ai");
|
|
63
196
|
|
|
64
|
-
// Clone Cursor commands
|
|
197
|
+
// Clone Cursor commands (luôn ghi đè)
|
|
65
198
|
if (installCursor) {
|
|
66
199
|
if (!existsSync(".cursor/commands")) {
|
|
67
200
|
mkdirSync(".cursor/commands", { recursive: true });
|
|
@@ -70,16 +203,26 @@ async function main() {
|
|
|
70
203
|
run(`npx degit ${REPO}/.cursor/commands .cursor/commands --force`);
|
|
71
204
|
}
|
|
72
205
|
|
|
73
|
-
// Clone GitHub Copilot
|
|
206
|
+
// Clone GitHub Copilot prompts (luôn ghi đè)
|
|
74
207
|
if (installCopilot) {
|
|
75
|
-
if (!existsSync(".
|
|
76
|
-
mkdirSync(".
|
|
208
|
+
if (!existsSync(".github/prompts")) {
|
|
209
|
+
mkdirSync(".github/prompts", { recursive: true });
|
|
210
|
+
}
|
|
211
|
+
step("🚚 Downloading GitHub Copilot prompts (.github/prompts)...");
|
|
212
|
+
run(`npx degit ${REPO}/.github/prompts .github/prompts --force`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Clone Cursor prompts (luôn ghi đè)
|
|
216
|
+
if (installCursor) {
|
|
217
|
+
if (!existsSync(".cursor/prompts")) {
|
|
218
|
+
mkdirSync(".cursor/prompts", { recursive: true });
|
|
77
219
|
}
|
|
78
|
-
step("🚚 Downloading
|
|
79
|
-
run(`npx degit ${REPO}/.
|
|
220
|
+
step("🚚 Downloading Cursor prompts (.cursor/prompts)...");
|
|
221
|
+
run(`npx degit ${REPO}/.cursor/prompts .cursor/prompts --force`);
|
|
80
222
|
}
|
|
81
223
|
|
|
82
|
-
|
|
224
|
+
// Download AGENTS.md (luôn ghi đè)
|
|
225
|
+
step("🚚 Downloading AGENTS.md...");
|
|
83
226
|
try {
|
|
84
227
|
run(`curl -fsSL ${RAW_BASE}/AGENTS.md -o AGENTS.md`);
|
|
85
228
|
} catch (_) {
|