anchi-toolkit 1.2.2 → 1.2.3
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/dist/index.js +2709 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1 +1,2709 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/******/ var __webpack_modules__ = ({
|
|
3
|
+
|
|
4
|
+
/***/ 1:
|
|
5
|
+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
6
|
+
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// anchi-toolkit Clean Command
|
|
9
|
+
// Reset project context and logs
|
|
10
|
+
// =============================================================================
|
|
11
|
+
|
|
12
|
+
const fs = __nccwpck_require__(896);
|
|
13
|
+
const path = __nccwpck_require__(928);
|
|
14
|
+
const readline = __nccwpck_require__(785);
|
|
15
|
+
const { getConfigDir } = __nccwpck_require__(256);
|
|
16
|
+
|
|
17
|
+
const rl = readline.createInterface({
|
|
18
|
+
input: process.stdin,
|
|
19
|
+
output: process.stdout,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
function ask(question) {
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
rl.question(question, (answer) => {
|
|
25
|
+
resolve(answer);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function clean(targetDir = process.cwd(), options = {}) {
|
|
31
|
+
console.log('');
|
|
32
|
+
console.log('🧹 anchi-toolkit Clean');
|
|
33
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
34
|
+
console.log('');
|
|
35
|
+
|
|
36
|
+
const configDir = getConfigDir(targetDir);
|
|
37
|
+
const auditDir = path.join(configDir, '.ai-audit');
|
|
38
|
+
const memoryDir = path.join(configDir, '.ai-memory');
|
|
39
|
+
|
|
40
|
+
const cleanMemory = options.memory || options.all;
|
|
41
|
+
const cleanAudit = options.audit || options.all;
|
|
42
|
+
const isForce = options.force;
|
|
43
|
+
|
|
44
|
+
if (!cleanMemory && !cleanAudit) {
|
|
45
|
+
console.log('Usage:');
|
|
46
|
+
console.log(' npx anchi-toolkit clean --memory Clear AI context');
|
|
47
|
+
console.log(' npx anchi-toolkit clean --audit Clear logs');
|
|
48
|
+
console.log(' npx anchi-toolkit clean --all Clear everything');
|
|
49
|
+
rl.close();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log('Checking targets:');
|
|
54
|
+
if (cleanMemory) console.log(` • Context Memory: ${memoryDir}`);
|
|
55
|
+
if (cleanAudit) console.log(` • Audit Logs: ${auditDir}`);
|
|
56
|
+
console.log('');
|
|
57
|
+
|
|
58
|
+
if (!isForce) {
|
|
59
|
+
const confirm = await ask('⚠️ Are you sure you want to delete these files? (Y/n): ');
|
|
60
|
+
if (confirm.toLowerCase() === 'n') {
|
|
61
|
+
console.log('❌ Cancelled.');
|
|
62
|
+
rl.close();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (cleanMemory) {
|
|
68
|
+
if (fs.existsSync(memoryDir)) {
|
|
69
|
+
// Keep the directory, just empty it or recreate it
|
|
70
|
+
fs.rmSync(memoryDir, { recursive: true, force: true });
|
|
71
|
+
fs.mkdirSync(memoryDir, { recursive: true });
|
|
72
|
+
console.log('✅ Memory cleared.');
|
|
73
|
+
} else {
|
|
74
|
+
console.log('⚪ Memory already clean.');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (cleanAudit) {
|
|
79
|
+
if (fs.existsSync(auditDir)) {
|
|
80
|
+
fs.rmSync(auditDir, { recursive: true, force: true });
|
|
81
|
+
fs.mkdirSync(auditDir, { recursive: true });
|
|
82
|
+
console.log('✅ Audit logs cleared.');
|
|
83
|
+
} else {
|
|
84
|
+
console.log('⚪ Audit logs already clean.');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log('');
|
|
89
|
+
console.log('✨ Clean complete!');
|
|
90
|
+
rl.close();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = { clean };
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
/***/ }),
|
|
97
|
+
|
|
98
|
+
/***/ 181:
|
|
99
|
+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
100
|
+
|
|
101
|
+
// =============================================================================
|
|
102
|
+
// anchi-toolkit Doctor Command
|
|
103
|
+
// Diagnose and check setup health
|
|
104
|
+
// =============================================================================
|
|
105
|
+
|
|
106
|
+
const fs = __nccwpck_require__(896);
|
|
107
|
+
const path = __nccwpck_require__(928);
|
|
108
|
+
|
|
109
|
+
async function doctor(targetDir = process.cwd()) {
|
|
110
|
+
console.log('');
|
|
111
|
+
console.log('🩺 anchi-toolkit Doctor');
|
|
112
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
113
|
+
console.log('');
|
|
114
|
+
|
|
115
|
+
const checks = [];
|
|
116
|
+
|
|
117
|
+
const { getConfigDir, CONFIG_FILENAME } = __nccwpck_require__(256);
|
|
118
|
+
const configDir = getConfigDir(targetDir);
|
|
119
|
+
const configDirName = path.basename(configDir);
|
|
120
|
+
|
|
121
|
+
// Check config folder
|
|
122
|
+
checks.push({
|
|
123
|
+
name: `${configDirName} folder`,
|
|
124
|
+
ok: fs.existsSync(configDir),
|
|
125
|
+
fix: 'Run: npx anchi-toolkit init'
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Check commands
|
|
129
|
+
const commandsDir = path.join(configDir, (configDirName === '.antigravity' ? 'workflows' : 'commands'));
|
|
130
|
+
// Antigravity has workflows, Cursor has commands. Though user might want consistency?
|
|
131
|
+
// Wait, my ANTIGRAVITY.md says .antigravity/workflows.
|
|
132
|
+
// cli.js installs .antigravity/workflows.
|
|
133
|
+
// So if configDir is .antigravity, check workflows.
|
|
134
|
+
// If configDir is .cursor, check commands.
|
|
135
|
+
// Actually, cli.js installs 'workflows' into .antigravity.
|
|
136
|
+
// Let's check logic:
|
|
137
|
+
// If .antigravity install: src: .cursor/commands (*.md) -> target: .antigravity/workflows (*.md)
|
|
138
|
+
// If .cursor install: src: .cursor/commands -> target: .cursor/commands.
|
|
139
|
+
|
|
140
|
+
// I need to detect which folder to check based on configDirName.
|
|
141
|
+
let cmdFolderName = 'commands';
|
|
142
|
+
if (configDirName === '.antigravity') cmdFolderName = 'workflows';
|
|
143
|
+
|
|
144
|
+
const cmdDir = path.join(configDir, cmdFolderName);
|
|
145
|
+
|
|
146
|
+
const commandCount = fs.existsSync(cmdDir)
|
|
147
|
+
? fs.readdirSync(cmdDir, { recursive: true }).filter(f => f.endsWith('.md')).length
|
|
148
|
+
: 0;
|
|
149
|
+
checks.push({
|
|
150
|
+
name: `Commands/Workflows (${cmdFolderName})`,
|
|
151
|
+
ok: commandCount > 0,
|
|
152
|
+
value: `${commandCount} files`,
|
|
153
|
+
fix: 'Run: npx anchi-toolkit install'
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Check agents
|
|
157
|
+
const agentsDir = path.join(configDir, 'agents');
|
|
158
|
+
const agentCount = fs.existsSync(agentsDir)
|
|
159
|
+
? fs.readdirSync(agentsDir).filter(f => f.endsWith('.md')).length
|
|
160
|
+
: 0;
|
|
161
|
+
checks.push({
|
|
162
|
+
name: 'Agents',
|
|
163
|
+
ok: agentCount > 0,
|
|
164
|
+
value: `${agentCount} files`,
|
|
165
|
+
fix: 'Run: npx anchi-toolkit install'
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Check .cursorrules (Only for Cursor?)
|
|
169
|
+
if (configDirName === '.cursor') {
|
|
170
|
+
const rulesFile = path.join(targetDir, '.cursorrules');
|
|
171
|
+
checks.push({
|
|
172
|
+
name: '.cursorrules',
|
|
173
|
+
ok: fs.existsSync(rulesFile),
|
|
174
|
+
fix: 'Run: /use-preset [name]'
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Check config
|
|
179
|
+
const configFile = path.join(configDir, CONFIG_FILENAME);
|
|
180
|
+
let configValid = false;
|
|
181
|
+
if (fs.existsSync(configFile)) {
|
|
182
|
+
try {
|
|
183
|
+
const content = fs.readFileSync(configFile, 'utf-8');
|
|
184
|
+
// Basic YAML validation check
|
|
185
|
+
if (content.trim().length > 0) {
|
|
186
|
+
configValid = true;
|
|
187
|
+
// Try parsing if possible
|
|
188
|
+
try {
|
|
189
|
+
const { parseYaml } = __nccwpck_require__(256);
|
|
190
|
+
parseYaml(content);
|
|
191
|
+
} catch (e) {
|
|
192
|
+
configValid = false;
|
|
193
|
+
console.log(` ❌ Config syntax error: ${e.message}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
} catch (e) {
|
|
197
|
+
configValid = false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
checks.push({
|
|
201
|
+
name: 'Config file syntax',
|
|
202
|
+
ok: configValid,
|
|
203
|
+
fix: 'Run: npx anchi-toolkit init (or fix YAML)'
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Check docs
|
|
207
|
+
const docsDir = path.join(configDir, 'docs');
|
|
208
|
+
checks.push({
|
|
209
|
+
name: 'Docs folder',
|
|
210
|
+
ok: fs.existsSync(docsDir),
|
|
211
|
+
fix: 'Run: npx anchi-toolkit install'
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Check package.json
|
|
215
|
+
const pkgFile = path.join(targetDir, 'package.json');
|
|
216
|
+
checks.push({
|
|
217
|
+
name: 'package.json',
|
|
218
|
+
ok: fs.existsSync(pkgFile),
|
|
219
|
+
fix: 'Run: npm init -y'
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Check Write Permissions (.ai-memory)
|
|
223
|
+
const memoryDir = path.join(configDir, '.ai-memory');
|
|
224
|
+
let memoryWriteable = false;
|
|
225
|
+
if (!fs.existsSync(memoryDir)) {
|
|
226
|
+
// Create checks will fail later if not exists, but we can try to create
|
|
227
|
+
// Actually, install should create it.
|
|
228
|
+
// If missing, check ok=false
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// We check if we can write to configDir (essential for logs/memory)
|
|
232
|
+
try {
|
|
233
|
+
if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, {recursive: true});
|
|
234
|
+
const testFile = path.join(configDir, '.perm-test');
|
|
235
|
+
fs.writeFileSync(testFile, 'test');
|
|
236
|
+
fs.unlinkSync(testFile);
|
|
237
|
+
memoryWriteable = true;
|
|
238
|
+
} catch (e) {
|
|
239
|
+
memoryWriteable = false;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
checks.push({
|
|
243
|
+
name: 'Write Permissions',
|
|
244
|
+
ok: memoryWriteable,
|
|
245
|
+
fix: 'Check folder permissions'
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Display results
|
|
249
|
+
let allOk = true;
|
|
250
|
+
for (const check of checks) {
|
|
251
|
+
const status = check.ok ? '✅' : '❌';
|
|
252
|
+
const value = check.value ? ` (${check.value})` : '';
|
|
253
|
+
console.log(` ${status} ${check.name}${value}`);
|
|
254
|
+
if (!check.ok) {
|
|
255
|
+
console.log(` 💡 Fix: ${check.fix}`);
|
|
256
|
+
allOk = false;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
console.log('');
|
|
261
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
262
|
+
|
|
263
|
+
if (allOk) {
|
|
264
|
+
console.log('✅ All checks passed! anchi-toolkit is healthy.');
|
|
265
|
+
} else {
|
|
266
|
+
console.log('⚠️ Some issues found. See fixes above.');
|
|
267
|
+
}
|
|
268
|
+
console.log('');
|
|
269
|
+
|
|
270
|
+
return allOk;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
module.exports = { doctor };
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
/***/ }),
|
|
277
|
+
|
|
278
|
+
/***/ 816:
|
|
279
|
+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
// =============================================================================
|
|
283
|
+
// anchi-toolkit Enhanced Init Command
|
|
284
|
+
// Usage: npx anchi-toolkit init
|
|
285
|
+
// =============================================================================
|
|
286
|
+
|
|
287
|
+
const fs = __nccwpck_require__(896);
|
|
288
|
+
const path = __nccwpck_require__(928);
|
|
289
|
+
const readline = __nccwpck_require__(785);
|
|
290
|
+
|
|
291
|
+
const { PROFILES, getProfile, getProfileList, getProfileEstimate } = __nccwpck_require__(251);
|
|
292
|
+
const { getSkillPackList, resolveSkillPacks } = __nccwpck_require__(548);
|
|
293
|
+
const { detectTechStack, suggestSkills, formatDetectedStack } = __nccwpck_require__(835);
|
|
294
|
+
const { calculateInstallSize, getComponentPaths, formatSize } = __nccwpck_require__(568);
|
|
295
|
+
|
|
296
|
+
// Colors
|
|
297
|
+
const colors = {
|
|
298
|
+
reset: '\x1b[0m',
|
|
299
|
+
red: '\x1b[31m',
|
|
300
|
+
green: '\x1b[32m',
|
|
301
|
+
yellow: '\x1b[33m',
|
|
302
|
+
cyan: '\x1b[36m',
|
|
303
|
+
gray: '\x1b[90m',
|
|
304
|
+
bold: '\x1b[1m',
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const log = {
|
|
308
|
+
info: (msg) => console.log(`${colors.cyan}${msg}${colors.reset}`),
|
|
309
|
+
success: (msg) => console.log(`${colors.green}${msg}${colors.reset}`),
|
|
310
|
+
warn: (msg) => console.log(`${colors.yellow}${msg}${colors.reset}`),
|
|
311
|
+
error: (msg) => console.log(`${colors.red}${msg}${colors.reset}`),
|
|
312
|
+
gray: (msg) => console.log(`${colors.gray}${msg}${colors.reset}`),
|
|
313
|
+
bold: (msg) => console.log(`${colors.bold}${msg}${colors.reset}`),
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
const rl = readline.createInterface({
|
|
317
|
+
input: process.stdin,
|
|
318
|
+
output: process.stdout,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
function ask(question) {
|
|
322
|
+
return new Promise((resolve) => {
|
|
323
|
+
rl.question(question, (answer) => resolve(answer.trim()));
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
async function askChoice(question, options) {
|
|
328
|
+
console.log('');
|
|
329
|
+
log.bold(question);
|
|
330
|
+
options.forEach((opt, i) => {
|
|
331
|
+
const estimate = opt.estimate ? ` ${colors.gray}(${opt.estimate})${colors.reset}` : '';
|
|
332
|
+
console.log(` ${colors.cyan}${i + 1}${colors.reset}) ${opt.label}${estimate}`);
|
|
333
|
+
if (opt.description) {
|
|
334
|
+
log.gray(` ${opt.description}`);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
console.log('');
|
|
338
|
+
|
|
339
|
+
while (true) {
|
|
340
|
+
const answer = await ask(`${colors.gray}Chọn (1-${options.length}): ${colors.reset}`);
|
|
341
|
+
const num = parseInt(answer);
|
|
342
|
+
if (num >= 1 && num <= options.length) {
|
|
343
|
+
return options[num - 1].value;
|
|
344
|
+
}
|
|
345
|
+
log.warn(' Vui lòng chọn số hợp lệ');
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
async function askMultiSelect(question, options) {
|
|
350
|
+
console.log('');
|
|
351
|
+
log.bold(question);
|
|
352
|
+
log.gray(' (Nhập số cách nhau bởi dấu phẩy, VD: 1,2,3. Enter để chọn mặc định)');
|
|
353
|
+
console.log('');
|
|
354
|
+
options.forEach((opt, i) => {
|
|
355
|
+
const checked = opt.default ? `${colors.green}◉${colors.reset}` : `${colors.gray}○${colors.reset}`;
|
|
356
|
+
console.log(` ${checked} ${colors.cyan}${i + 1}${colors.reset}) ${opt.label}`);
|
|
357
|
+
});
|
|
358
|
+
console.log('');
|
|
359
|
+
|
|
360
|
+
const answer = await ask(`${colors.gray}Chọn: ${colors.reset}`);
|
|
361
|
+
|
|
362
|
+
if (!answer) {
|
|
363
|
+
return options.filter(o => o.default).map(o => o.value);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const nums = answer.split(',').map(s => parseInt(s.trim())).filter(n => n >= 1 && n <= options.length);
|
|
367
|
+
return nums.map(n => options[n - 1].value);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function copyDirRecursive(src, dest) {
|
|
371
|
+
if (!fs.existsSync(dest)) {
|
|
372
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
373
|
+
}
|
|
374
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
375
|
+
for (const entry of entries) {
|
|
376
|
+
const srcPath = path.join(src, entry.name);
|
|
377
|
+
const destPath = path.join(dest, entry.name);
|
|
378
|
+
if (entry.isDirectory()) {
|
|
379
|
+
copyDirRecursive(srcPath, destPath);
|
|
380
|
+
} else {
|
|
381
|
+
fs.copyFileSync(srcPath, destPath);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function copyFile(src, dest) {
|
|
387
|
+
const destDir = path.dirname(dest);
|
|
388
|
+
if (!fs.existsSync(destDir)) {
|
|
389
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
390
|
+
}
|
|
391
|
+
fs.copyFileSync(src, dest);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
async function init() {
|
|
395
|
+
console.log('');
|
|
396
|
+
log.info('╔═══════════════════════════════════════════════════════════╗');
|
|
397
|
+
log.info('║ 🚀 anchi-toolkit Smart Install ║');
|
|
398
|
+
log.info('╚═══════════════════════════════════════════════════════════╝');
|
|
399
|
+
console.log('');
|
|
400
|
+
|
|
401
|
+
const targetPath = process.cwd();
|
|
402
|
+
const kitPath = path.resolve(__dirname, '../..');
|
|
403
|
+
|
|
404
|
+
log.gray(`📂 Target: ${targetPath}`);
|
|
405
|
+
|
|
406
|
+
// Step 1: Detect tech stack
|
|
407
|
+
console.log('');
|
|
408
|
+
log.warn('🔍 Detecting tech stack...');
|
|
409
|
+
const detected = detectTechStack(targetPath);
|
|
410
|
+
const detectedStr = formatDetectedStack(detected);
|
|
411
|
+
log.info(` ${detectedStr}`);
|
|
412
|
+
|
|
413
|
+
const suggestedSkills = suggestSkills(detected);
|
|
414
|
+
if (suggestedSkills.length > 0) {
|
|
415
|
+
log.success(` 💡 Suggested skills: ${suggestedSkills.join(', ')}`);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Step 2: Choose profile
|
|
419
|
+
const profiles = getProfileList();
|
|
420
|
+
const profileOptions = profiles.map(p => ({
|
|
421
|
+
label: `${p.name}`,
|
|
422
|
+
description: p.description,
|
|
423
|
+
estimate: getProfileEstimate(p.key).formatted || '',
|
|
424
|
+
value: p.key,
|
|
425
|
+
}));
|
|
426
|
+
|
|
427
|
+
const selectedProfile = await askChoice('Chọn profile:', profileOptions);
|
|
428
|
+
const profile = getProfile(selectedProfile);
|
|
429
|
+
|
|
430
|
+
// Step 3: Customize (if not minimal or fullstack)
|
|
431
|
+
let finalConfig = { ...profile };
|
|
432
|
+
|
|
433
|
+
if (selectedProfile !== 'minimal' && selectedProfile !== 'fullstack') {
|
|
434
|
+
const customize = await ask(`\n${colors.yellow}Customize thêm? (y/N): ${colors.reset}`);
|
|
435
|
+
|
|
436
|
+
if (customize.toLowerCase() === 'y') {
|
|
437
|
+
// Skill packs
|
|
438
|
+
const packs = getSkillPackList();
|
|
439
|
+
const packOptions = packs.map(p => ({
|
|
440
|
+
label: `${p.name} (${p.skillCount} skills)`,
|
|
441
|
+
value: p.key,
|
|
442
|
+
default: false,
|
|
443
|
+
}));
|
|
444
|
+
|
|
445
|
+
const selectedPacks = await askMultiSelect('Thêm skill packs:', packOptions);
|
|
446
|
+
if (selectedPacks.length > 0) {
|
|
447
|
+
const extraSkills = resolveSkillPacks(selectedPacks);
|
|
448
|
+
finalConfig.skills = [...new Set([...finalConfig.skills, ...extraSkills])];
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Include presets?
|
|
452
|
+
if (!finalConfig.includePresets) {
|
|
453
|
+
const includePresets = await ask(`\n${colors.yellow}Include presets folder? (y/N): ${colors.reset}`);
|
|
454
|
+
finalConfig.includePresets = includePresets.toLowerCase() === 'y';
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Include docs?
|
|
458
|
+
if (!finalConfig.includeDocs) {
|
|
459
|
+
const includeDocs = await ask(`${colors.yellow}Include docs folder? (y/N): ${colors.reset}`);
|
|
460
|
+
finalConfig.includeDocs = includeDocs.toLowerCase() === 'y';
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Step 4: Size preview
|
|
466
|
+
console.log('');
|
|
467
|
+
log.warn('📊 Install Preview:');
|
|
468
|
+
const components = getComponentPaths(finalConfig, kitPath);
|
|
469
|
+
const sizeInfo = calculateInstallSize(kitPath, components);
|
|
470
|
+
|
|
471
|
+
console.log(` Files: ~${sizeInfo.files}`);
|
|
472
|
+
console.log(` Size: ~${sizeInfo.formatted}`);
|
|
473
|
+
console.log('');
|
|
474
|
+
log.info(' Components:');
|
|
475
|
+
|
|
476
|
+
if (finalConfig.commands === 'all') {
|
|
477
|
+
log.success(' ✓ All commands');
|
|
478
|
+
} else {
|
|
479
|
+
log.success(` ✓ Commands: ${finalConfig.commands.join(', ')}`);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (finalConfig.agents === 'all' || (Array.isArray(finalConfig.agents) && finalConfig.agents.length > 0)) {
|
|
483
|
+
log.success(` ✓ Agents: ${finalConfig.agents === 'all' ? 'All' : finalConfig.agents.length + ' agents'}`);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (finalConfig.skills === 'all' || (Array.isArray(finalConfig.skills) && finalConfig.skills.length > 0)) {
|
|
487
|
+
log.success(` ✓ Skills: ${finalConfig.skills === 'all' ? 'All' : finalConfig.skills.length + ' skills'}`);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
if (finalConfig.includePresets) log.success(' ✓ Presets');
|
|
491
|
+
if (finalConfig.includeDocs) log.success(' ✓ Docs');
|
|
492
|
+
|
|
493
|
+
// Step 5: Confirm
|
|
494
|
+
console.log('');
|
|
495
|
+
const confirm = await ask(`${colors.yellow}Proceed with installation? (Y/n): ${colors.reset}`);
|
|
496
|
+
|
|
497
|
+
if (confirm.toLowerCase() === 'n') {
|
|
498
|
+
log.error('❌ Cancelled.');
|
|
499
|
+
rl.close();
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Step 6: Install
|
|
504
|
+
console.log('');
|
|
505
|
+
log.warn('📦 Installing...');
|
|
506
|
+
console.log('');
|
|
507
|
+
|
|
508
|
+
let installedFiles = 0;
|
|
509
|
+
|
|
510
|
+
// Install commands
|
|
511
|
+
const commandsPath = __nccwpck_require__.ab + "commands";
|
|
512
|
+
const destCommandsPath = __nccwpck_require__.ab + "commands";
|
|
513
|
+
|
|
514
|
+
if (finalConfig.commands === 'all') {
|
|
515
|
+
copyDirRecursive(__nccwpck_require__.ab + "commands", destCommandsPath);
|
|
516
|
+
installedFiles += fs.readdirSync(__nccwpck_require__.ab + "commands").length;
|
|
517
|
+
log.success(' ✅ Commands (all)');
|
|
518
|
+
} else {
|
|
519
|
+
for (const cmd of finalConfig.commands) {
|
|
520
|
+
const srcFile = __nccwpck_require__.ab + "commands/" + cmd + '.md';
|
|
521
|
+
if (fs.existsSync(srcFile)) {
|
|
522
|
+
copyFile(srcFile, __nccwpck_require__.ab + "commands/" + cmd + '.md');
|
|
523
|
+
installedFiles++;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
log.success(` ✅ Commands (${finalConfig.commands.length})`);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Install agents
|
|
530
|
+
const agentsPath = __nccwpck_require__.ab + "agents";
|
|
531
|
+
const destAgentsPath = __nccwpck_require__.ab + "agents";
|
|
532
|
+
|
|
533
|
+
if (finalConfig.agents === 'all') {
|
|
534
|
+
copyDirRecursive(__nccwpck_require__.ab + "agents", destAgentsPath);
|
|
535
|
+
log.success(' ✅ Agents (all)');
|
|
536
|
+
} else if (Array.isArray(finalConfig.agents) && finalConfig.agents.length > 0) {
|
|
537
|
+
for (const agent of finalConfig.agents) {
|
|
538
|
+
const srcFile = __nccwpck_require__.ab + "agents/" + agent + '.md';
|
|
539
|
+
if (fs.existsSync(srcFile)) {
|
|
540
|
+
copyFile(srcFile, __nccwpck_require__.ab + "agents/" + agent + '.md');
|
|
541
|
+
installedFiles++;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
log.success(` ✅ Agents (${finalConfig.agents.length})`);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Install skills
|
|
548
|
+
const skillsPath = __nccwpck_require__.ab + "skills";
|
|
549
|
+
const destSkillsPath = __nccwpck_require__.ab + "skills";
|
|
550
|
+
|
|
551
|
+
if (finalConfig.skills === 'all') {
|
|
552
|
+
copyDirRecursive(__nccwpck_require__.ab + "skills", destSkillsPath);
|
|
553
|
+
log.success(' ✅ Skills (all)');
|
|
554
|
+
} else if (Array.isArray(finalConfig.skills) && finalConfig.skills.length > 0) {
|
|
555
|
+
for (const skill of finalConfig.skills) {
|
|
556
|
+
const srcDir = __nccwpck_require__.ab + "skills/" + skill;
|
|
557
|
+
if (fs.existsSync(srcDir)) {
|
|
558
|
+
copyDirRecursive(srcDir, __nccwpck_require__.ab + "skills/" + skill);
|
|
559
|
+
installedFiles++;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
log.success(` ✅ Skills (${finalConfig.skills.length})`);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Install extras
|
|
566
|
+
if (finalConfig.includePresets) {
|
|
567
|
+
const presetsPath = __nccwpck_require__.ab + "presets";
|
|
568
|
+
if (fs.existsSync(__nccwpck_require__.ab + "presets")) {
|
|
569
|
+
copyDirRecursive(presetsPath, path.join(targetPath, '.cursor/presets'));
|
|
570
|
+
log.success(' ✅ Presets');
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
if (finalConfig.includeDocs) {
|
|
575
|
+
const docsPath = __nccwpck_require__.ab + "docs";
|
|
576
|
+
if (fs.existsSync(__nccwpck_require__.ab + "docs")) {
|
|
577
|
+
copyDirRecursive(docsPath, path.join(targetPath, '.cursor/docs'));
|
|
578
|
+
log.success(' ✅ Docs');
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Install AI folders (Implicit)
|
|
583
|
+
const auditPath = path.join(kitPath, '.ai-audit');
|
|
584
|
+
if (fs.existsSync(auditPath)) {
|
|
585
|
+
copyDirRecursive(auditPath, path.join(targetPath, '.cursor/.ai-audit'));
|
|
586
|
+
log.success(' ✅ .ai-audit');
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
const memoryPath = __nccwpck_require__.ab + ".ai-memory";
|
|
590
|
+
if (fs.existsSync(__nccwpck_require__.ab + ".ai-memory")) {
|
|
591
|
+
copyDirRecursive(memoryPath, path.join(targetPath, '.cursor/.ai-memory'));
|
|
592
|
+
log.success(' ✅ .ai-memory');
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Install scripts
|
|
596
|
+
const scriptsPath = __nccwpck_require__.ab + "scripts";
|
|
597
|
+
if (fs.existsSync(__nccwpck_require__.ab + "scripts")) {
|
|
598
|
+
copyDirRecursive(scriptsPath, path.join(targetPath, '.cursor/scripts'));
|
|
599
|
+
log.success(' ✅ scripts');
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Always include
|
|
603
|
+
const cursorRulesPath = __nccwpck_require__.ab + ".cursorrules";
|
|
604
|
+
if (fs.existsSync(__nccwpck_require__.ab + ".cursorrules")) {
|
|
605
|
+
fs.copyFileSync(cursorRulesPath, path.join(targetPath, '.cursorrules'));
|
|
606
|
+
log.success(' ✅ .cursorrules');
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
const cursorMdPath = __nccwpck_require__.ab + "CURSOR.md";
|
|
610
|
+
if (fs.existsSync(__nccwpck_require__.ab + "CURSOR.md")) {
|
|
611
|
+
fs.copyFileSync(cursorMdPath, path.join(targetPath, 'CURSOR.md'));
|
|
612
|
+
log.success(' ✅ CURSOR.md');
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// Copy MODEL_COSTS.md
|
|
616
|
+
const modelCostsPath = __nccwpck_require__.ab + "MODEL_COSTS.md";
|
|
617
|
+
if (fs.existsSync(__nccwpck_require__.ab + "MODEL_COSTS.md")) {
|
|
618
|
+
copyFile(modelCostsPath, path.join(targetPath, '.cursor/MODEL_COSTS.md'));
|
|
619
|
+
log.success(' ✅ MODEL_COSTS.md');
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// Done
|
|
623
|
+
console.log('');
|
|
624
|
+
log.info('═══════════════════════════════════════════════════════════════');
|
|
625
|
+
log.success(' ✅ anchi-toolkit installed successfully!');
|
|
626
|
+
log.info('═══════════════════════════════════════════════════════════════');
|
|
627
|
+
console.log('');
|
|
628
|
+
log.warn('📌 Next steps:');
|
|
629
|
+
console.log('');
|
|
630
|
+
console.log(' 1. Open Cursor and run:');
|
|
631
|
+
log.success(' /start');
|
|
632
|
+
console.log('');
|
|
633
|
+
console.log(' 2. Start coding:');
|
|
634
|
+
log.success(' /plan "Feature description"');
|
|
635
|
+
console.log('');
|
|
636
|
+
|
|
637
|
+
rl.close();
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
module.exports = { init };
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
/***/ }),
|
|
644
|
+
|
|
645
|
+
/***/ 697:
|
|
646
|
+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
647
|
+
|
|
648
|
+
// =============================================================================
|
|
649
|
+
// anchi-toolkit Memory CLI Command
|
|
650
|
+
// =============================================================================
|
|
651
|
+
|
|
652
|
+
const { loadMemory, saveMemory, clearMemory, getMemorySummary, addNote, addDecision } = __nccwpck_require__(355);
|
|
653
|
+
|
|
654
|
+
async function memory(action = 'show', arg = null) {
|
|
655
|
+
const targetDir = process.cwd();
|
|
656
|
+
|
|
657
|
+
console.log('');
|
|
658
|
+
console.log('🧠 anchi-toolkit Memory');
|
|
659
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
660
|
+
console.log('');
|
|
661
|
+
|
|
662
|
+
switch (action) {
|
|
663
|
+
case 'show':
|
|
664
|
+
case undefined:
|
|
665
|
+
showMemory(targetDir);
|
|
666
|
+
break;
|
|
667
|
+
|
|
668
|
+
case 'save':
|
|
669
|
+
saveProjectMemory(targetDir, arg);
|
|
670
|
+
break;
|
|
671
|
+
|
|
672
|
+
case 'load':
|
|
673
|
+
loadProjectMemory(targetDir);
|
|
674
|
+
break;
|
|
675
|
+
|
|
676
|
+
case 'clear':
|
|
677
|
+
clearProjectMemory(targetDir);
|
|
678
|
+
break;
|
|
679
|
+
|
|
680
|
+
case 'add':
|
|
681
|
+
addToMemory(targetDir, arg);
|
|
682
|
+
break;
|
|
683
|
+
|
|
684
|
+
default:
|
|
685
|
+
console.log('Usage:');
|
|
686
|
+
console.log(' npx anchi-toolkit memory show Show current memory');
|
|
687
|
+
console.log(' npx anchi-toolkit memory save Save context');
|
|
688
|
+
console.log(' npx anchi-toolkit memory load Load context');
|
|
689
|
+
console.log(' npx anchi-toolkit memory clear Clear memory');
|
|
690
|
+
console.log(' npx anchi-toolkit memory add "note" Add a note');
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
console.log('');
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
function showMemory(targetDir) {
|
|
698
|
+
const memory = loadMemory(targetDir);
|
|
699
|
+
|
|
700
|
+
console.log('📂 Project:');
|
|
701
|
+
if (memory.project.name) {
|
|
702
|
+
console.log(` Name: ${memory.project.name}`);
|
|
703
|
+
if (memory.project.description) {
|
|
704
|
+
console.log(` Description: ${memory.project.description}`);
|
|
705
|
+
}
|
|
706
|
+
if (memory.project.tech_stack.length > 0) {
|
|
707
|
+
console.log(` Tech: ${memory.project.tech_stack.join(', ')}`);
|
|
708
|
+
}
|
|
709
|
+
if (memory.project.architecture) {
|
|
710
|
+
console.log(` Architecture: ${memory.project.architecture}`);
|
|
711
|
+
}
|
|
712
|
+
} else {
|
|
713
|
+
console.log(' (No project info saved)');
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
console.log('');
|
|
717
|
+
console.log('📌 Last Session:');
|
|
718
|
+
if (memory.session.last_task) {
|
|
719
|
+
console.log(` Task: ${memory.session.last_task}`);
|
|
720
|
+
if (memory.session.current_phase) {
|
|
721
|
+
console.log(` Phase: ${memory.session.current_phase}`);
|
|
722
|
+
}
|
|
723
|
+
console.log(` Last accessed: ${memory.session.last_accessed || 'Never'}`);
|
|
724
|
+
} else {
|
|
725
|
+
console.log(' (No session info)');
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
console.log('');
|
|
729
|
+
console.log('🧠 Decisions:');
|
|
730
|
+
if (memory.decisions.length > 0) {
|
|
731
|
+
const recent = memory.decisions.slice(-5);
|
|
732
|
+
for (const d of recent) {
|
|
733
|
+
console.log(` • ${d.decision}`);
|
|
734
|
+
}
|
|
735
|
+
if (memory.decisions.length > 5) {
|
|
736
|
+
console.log(` ... and ${memory.decisions.length - 5} more`);
|
|
737
|
+
}
|
|
738
|
+
} else {
|
|
739
|
+
console.log(' (No decisions recorded)');
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
console.log('');
|
|
743
|
+
console.log('📝 Notes:');
|
|
744
|
+
if (memory.notes.length > 0) {
|
|
745
|
+
const recent = memory.notes.slice(-5);
|
|
746
|
+
for (const n of recent) {
|
|
747
|
+
console.log(` • ${n.note}`);
|
|
748
|
+
}
|
|
749
|
+
if (memory.notes.length > 5) {
|
|
750
|
+
console.log(` ... and ${memory.notes.length - 5} more`);
|
|
751
|
+
}
|
|
752
|
+
} else {
|
|
753
|
+
console.log(' (No notes)');
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
function saveProjectMemory(targetDir, note) {
|
|
758
|
+
const memory = loadMemory(targetDir);
|
|
759
|
+
if (note) {
|
|
760
|
+
memory.notes.push({
|
|
761
|
+
id: Date.now(),
|
|
762
|
+
note: note,
|
|
763
|
+
category: 'session',
|
|
764
|
+
timestamp: new Date().toISOString(),
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
const path = saveMemory(targetDir, memory);
|
|
768
|
+
console.log('✅ Memory saved!');
|
|
769
|
+
console.log(` Location: ${path}`);
|
|
770
|
+
console.log(` Stats:`);
|
|
771
|
+
console.log(` • Decisions: ${memory.decisions.length}`);
|
|
772
|
+
console.log(` • Notes: ${memory.notes.length}`);
|
|
773
|
+
console.log(` • Entities: ${Object.keys(memory.entities).length}`);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
function loadProjectMemory(targetDir) {
|
|
777
|
+
const summary = getMemorySummary(targetDir);
|
|
778
|
+
console.log(summary);
|
|
779
|
+
console.log('');
|
|
780
|
+
console.log('✅ Context loaded! AI now remembers your project.');
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
function clearProjectMemory(targetDir) {
|
|
784
|
+
clearMemory(targetDir);
|
|
785
|
+
console.log('✅ Memory cleared!');
|
|
786
|
+
console.log(' All project context has been reset.');
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
function addToMemory(targetDir, content) {
|
|
790
|
+
if (!content) {
|
|
791
|
+
console.log('Usage: npx anchi-toolkit memory add "your note"');
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
if (content.startsWith('decision:')) {
|
|
796
|
+
const parts = content.slice(9).split(' - ');
|
|
797
|
+
addDecision(targetDir, parts[0].trim(), parts[1] || '');
|
|
798
|
+
console.log('✅ Decision recorded!');
|
|
799
|
+
} else {
|
|
800
|
+
addNote(targetDir, content);
|
|
801
|
+
console.log('✅ Note added!');
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
module.exports = { memory };
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
/***/ }),
|
|
809
|
+
|
|
810
|
+
/***/ 66:
|
|
811
|
+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
// =============================================================================
|
|
815
|
+
// anchi-toolkit Uninstall Command
|
|
816
|
+
// Usage: npx anchi-toolkit uninstall
|
|
817
|
+
// =============================================================================
|
|
818
|
+
|
|
819
|
+
const fs = __nccwpck_require__(896);
|
|
820
|
+
const path = __nccwpck_require__(928);
|
|
821
|
+
const readline = __nccwpck_require__(785);
|
|
822
|
+
|
|
823
|
+
const colors = {
|
|
824
|
+
reset: '\x1b[0m',
|
|
825
|
+
red: '\x1b[31m',
|
|
826
|
+
green: '\x1b[32m',
|
|
827
|
+
yellow: '\x1b[33m',
|
|
828
|
+
cyan: '\x1b[36m',
|
|
829
|
+
gray: '\x1b[90m',
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
const log = {
|
|
833
|
+
info: (msg) => console.log(`${colors.cyan}${msg}${colors.reset}`),
|
|
834
|
+
success: (msg) => console.log(`${colors.green}${msg}${colors.reset}`),
|
|
835
|
+
warn: (msg) => console.log(`${colors.yellow}${msg}${colors.reset}`),
|
|
836
|
+
error: (msg) => console.log(`${colors.red}${msg}${colors.reset}`),
|
|
837
|
+
gray: (msg) => console.log(`${colors.gray}${msg}${colors.reset}`),
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
const rl = readline.createInterface({
|
|
841
|
+
input: process.stdin,
|
|
842
|
+
output: process.stdout,
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
function ask(question) {
|
|
846
|
+
return new Promise((resolve) => {
|
|
847
|
+
rl.question(question, (answer) => resolve(answer.trim()));
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
function deleteRecursive(dir) {
|
|
852
|
+
if (fs.existsSync(dir)) {
|
|
853
|
+
fs.readdirSync(dir).forEach((file) => {
|
|
854
|
+
const curPath = path.join(dir, file);
|
|
855
|
+
if (fs.lstatSync(curPath).isDirectory()) {
|
|
856
|
+
deleteRecursive(curPath);
|
|
857
|
+
} else {
|
|
858
|
+
fs.unlinkSync(curPath);
|
|
859
|
+
}
|
|
860
|
+
});
|
|
861
|
+
fs.rmdirSync(dir);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
async function uninstall() {
|
|
866
|
+
console.log('');
|
|
867
|
+
log.info('╔═══════════════════════════════════════════════════════════╗');
|
|
868
|
+
log.info('║ 🗑️ anchi-toolkit Uninstall ║');
|
|
869
|
+
log.info('╚═══════════════════════════════════════════════════════════╝');
|
|
870
|
+
console.log('');
|
|
871
|
+
|
|
872
|
+
const targetPath = process.cwd();
|
|
873
|
+
|
|
874
|
+
// Items to remove
|
|
875
|
+
// Items to remove
|
|
876
|
+
const itemsToRemove = [
|
|
877
|
+
// Cursor
|
|
878
|
+
{ path: '.cursor/commands', type: 'dir', desc: 'Commands' },
|
|
879
|
+
{ path: '.cursor/agents', type: 'dir', desc: 'Agents' },
|
|
880
|
+
{ path: '.cursor/skills', type: 'dir', desc: 'Skills' },
|
|
881
|
+
{ path: '.cursor/presets', type: 'dir', desc: 'Presets' },
|
|
882
|
+
{ path: '.cursor/docs', type: 'dir', desc: 'Docs' },
|
|
883
|
+
{ path: '.cursor/.ai-audit', type: 'dir', desc: 'Audit Logs' },
|
|
884
|
+
{ path: '.cursor/.ai-memory', type: 'dir', desc: 'Memory' },
|
|
885
|
+
{ path: '.cursor/MODEL_COSTS.md', type: 'file', desc: 'Model costs guide' },
|
|
886
|
+
|
|
887
|
+
// Antigravity
|
|
888
|
+
{ path: '.antigravity', type: 'dir', desc: 'Antigravity Folder' },
|
|
889
|
+
|
|
890
|
+
// Root files
|
|
891
|
+
{ path: '.cursorrules', type: 'file', desc: 'Cursor rules' },
|
|
892
|
+
{ path: 'CURSOR.md', type: 'file', desc: 'Cursor instructions' },
|
|
893
|
+
{ path: 'GEMINI.md', type: 'file', desc: 'Gemini instructions' },
|
|
894
|
+
{ path: 'ANTIGRAVITY.md', type: 'file', desc: 'Antigravity instructions' },
|
|
895
|
+
|
|
896
|
+
// Legacy (Root) - Cleanup old installs
|
|
897
|
+
{ path: 'presets', type: 'dir', desc: 'Presets (Legacy)' },
|
|
898
|
+
{ path: 'docs', type: 'dir', desc: 'Docs (Legacy)' },
|
|
899
|
+
{ path: '.ai-audit', type: 'dir', desc: 'Audit Logs (Legacy)' },
|
|
900
|
+
{ path: '.ai-memory', type: 'dir', desc: 'Memory (Legacy)' },
|
|
901
|
+
];
|
|
902
|
+
|
|
903
|
+
// Check what exists
|
|
904
|
+
const existingItems = itemsToRemove.filter(item => {
|
|
905
|
+
const fullPath = path.join(targetPath, item.path);
|
|
906
|
+
return fs.existsSync(fullPath);
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
if (existingItems.length === 0) {
|
|
910
|
+
log.warn('⚠️ No anchi-toolkit files found in this directory.');
|
|
911
|
+
rl.close();
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// Show what will be removed
|
|
916
|
+
log.warn('📋 The following will be removed:');
|
|
917
|
+
console.log('');
|
|
918
|
+
|
|
919
|
+
existingItems.forEach(item => {
|
|
920
|
+
if (item.type === 'dir') {
|
|
921
|
+
log.error(` 📁 ${item.path}/`);
|
|
922
|
+
} else {
|
|
923
|
+
log.error(` 📄 ${item.path}`);
|
|
924
|
+
}
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
console.log('');
|
|
928
|
+
log.warn('⚠️ This action cannot be undone!');
|
|
929
|
+
console.log('');
|
|
930
|
+
|
|
931
|
+
const confirm = await ask(`${colors.red}Type 'REMOVE' to confirm: ${colors.reset}`);
|
|
932
|
+
|
|
933
|
+
if (confirm !== 'REMOVE') {
|
|
934
|
+
log.info('❌ Cancelled.');
|
|
935
|
+
rl.close();
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
console.log('');
|
|
940
|
+
log.warn('🗑️ Removing...');
|
|
941
|
+
console.log('');
|
|
942
|
+
|
|
943
|
+
let removed = 0;
|
|
944
|
+
|
|
945
|
+
for (const item of existingItems) {
|
|
946
|
+
const fullPath = path.join(targetPath, item.path);
|
|
947
|
+
try {
|
|
948
|
+
if (item.type === 'dir') {
|
|
949
|
+
deleteRecursive(fullPath);
|
|
950
|
+
} else {
|
|
951
|
+
fs.unlinkSync(fullPath);
|
|
952
|
+
}
|
|
953
|
+
log.success(` ✅ Removed: ${item.path}`);
|
|
954
|
+
removed++;
|
|
955
|
+
} catch (e) {
|
|
956
|
+
log.error(` ❌ Failed: ${item.path} - ${e.message}`);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// Clean up empty .cursor folder
|
|
961
|
+
const cursorDir = __nccwpck_require__.ab + ".cursor";
|
|
962
|
+
if (fs.existsSync(__nccwpck_require__.ab + ".cursor")) {
|
|
963
|
+
const remaining = fs.readdirSync(cursorDir);
|
|
964
|
+
if (remaining.length === 0) {
|
|
965
|
+
fs.rmdirSync(cursorDir);
|
|
966
|
+
log.gray(' 🧹 Removed empty .cursor/');
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
console.log('');
|
|
971
|
+
log.info('═══════════════════════════════════════════════════════════════');
|
|
972
|
+
log.success(` ✅ Removed ${removed} items!`);
|
|
973
|
+
log.info('═══════════════════════════════════════════════════════════════');
|
|
974
|
+
console.log('');
|
|
975
|
+
|
|
976
|
+
rl.close();
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
module.exports = { uninstall };
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
/***/ }),
|
|
983
|
+
|
|
984
|
+
/***/ 779:
|
|
985
|
+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
// =============================================================================
|
|
989
|
+
// anchi-toolkit Update Command
|
|
990
|
+
// Usage: npx anchi-toolkit update
|
|
991
|
+
// =============================================================================
|
|
992
|
+
|
|
993
|
+
const fs = __nccwpck_require__(896);
|
|
994
|
+
const path = __nccwpck_require__(928);
|
|
995
|
+
const https = __nccwpck_require__(692);
|
|
996
|
+
|
|
997
|
+
const colors = {
|
|
998
|
+
reset: '\x1b[0m',
|
|
999
|
+
red: '\x1b[31m',
|
|
1000
|
+
green: '\x1b[32m',
|
|
1001
|
+
yellow: '\x1b[33m',
|
|
1002
|
+
cyan: '\x1b[36m',
|
|
1003
|
+
gray: '\x1b[90m',
|
|
1004
|
+
};
|
|
1005
|
+
|
|
1006
|
+
const log = {
|
|
1007
|
+
info: (msg) => console.log(`${colors.cyan}${msg}${colors.reset}`),
|
|
1008
|
+
success: (msg) => console.log(`${colors.green}${msg}${colors.reset}`),
|
|
1009
|
+
warn: (msg) => console.log(`${colors.yellow}${msg}${colors.reset}`),
|
|
1010
|
+
error: (msg) => console.log(`${colors.red}${msg}${colors.reset}`),
|
|
1011
|
+
gray: (msg) => console.log(`${colors.gray}${msg}${colors.reset}`),
|
|
1012
|
+
};
|
|
1013
|
+
|
|
1014
|
+
// Get current installed version
|
|
1015
|
+
function getCurrentVersion() {
|
|
1016
|
+
try {
|
|
1017
|
+
const kitPath = path.resolve(__dirname, '..');
|
|
1018
|
+
const pkgPath = path.join(kitPath, 'package.json');
|
|
1019
|
+
if (fs.existsSync(pkgPath)) {
|
|
1020
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
1021
|
+
return pkg.version || '0.0.0';
|
|
1022
|
+
}
|
|
1023
|
+
} catch (e) {
|
|
1024
|
+
return '0.0.0';
|
|
1025
|
+
}
|
|
1026
|
+
return '0.0.0';
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
// Check npm registry for latest version
|
|
1030
|
+
function getLatestVersion() {
|
|
1031
|
+
return new Promise((resolve, reject) => {
|
|
1032
|
+
https.get('https://registry.npmjs.org/anchi-toolkit/latest', (res) => {
|
|
1033
|
+
let data = '';
|
|
1034
|
+
res.on('data', chunk => data += chunk);
|
|
1035
|
+
res.on('end', () => {
|
|
1036
|
+
try {
|
|
1037
|
+
const pkg = JSON.parse(data);
|
|
1038
|
+
resolve(pkg.version || '0.0.0');
|
|
1039
|
+
} catch (e) {
|
|
1040
|
+
resolve('0.0.0');
|
|
1041
|
+
}
|
|
1042
|
+
});
|
|
1043
|
+
}).on('error', () => resolve('0.0.0'));
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
// Compare versions (simple semver compare)
|
|
1048
|
+
function isNewer(latest, current) {
|
|
1049
|
+
const l = latest.split('.').map(Number);
|
|
1050
|
+
const c = current.split('.').map(Number);
|
|
1051
|
+
for (let i = 0; i < 3; i++) {
|
|
1052
|
+
if ((l[i] || 0) > (c[i] || 0)) return true;
|
|
1053
|
+
if ((l[i] || 0) < (c[i] || 0)) return false;
|
|
1054
|
+
}
|
|
1055
|
+
return false;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// Backup and update files
|
|
1059
|
+
function updateFiles(targetPath, kitPath) {
|
|
1060
|
+
const timestamp = new Date().toISOString().replace(/[-:]/g, '').slice(0, 15);
|
|
1061
|
+
const updatableComponents = [
|
|
1062
|
+
{ path: '.cursor/commands', desc: 'Commands' },
|
|
1063
|
+
{ path: '.cursor/agents', desc: 'Agents' },
|
|
1064
|
+
{ path: '.cursor/skills', desc: 'Skills' },
|
|
1065
|
+
];
|
|
1066
|
+
|
|
1067
|
+
let updated = 0;
|
|
1068
|
+
|
|
1069
|
+
for (const comp of updatableComponents) {
|
|
1070
|
+
const sourcePath = path.join(kitPath, comp.path);
|
|
1071
|
+
const destPath = path.join(targetPath, comp.path);
|
|
1072
|
+
|
|
1073
|
+
if (fs.existsSync(sourcePath) && fs.existsSync(destPath)) {
|
|
1074
|
+
// Backup existing
|
|
1075
|
+
const backupPath = `${destPath}.backup_${timestamp}`;
|
|
1076
|
+
log.gray(` 📦 Backing up ${comp.desc}...`);
|
|
1077
|
+
|
|
1078
|
+
// Copy source to dest (overwrite)
|
|
1079
|
+
copyDirRecursive(sourcePath, destPath);
|
|
1080
|
+
log.success(` ✅ Updated: ${comp.desc}`);
|
|
1081
|
+
updated++;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
return updated;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
function copyDirRecursive(src, dest) {
|
|
1089
|
+
if (!fs.existsSync(dest)) {
|
|
1090
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
1091
|
+
}
|
|
1092
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
1093
|
+
for (const entry of entries) {
|
|
1094
|
+
const srcPath = path.join(src, entry.name);
|
|
1095
|
+
const destPath = path.join(dest, entry.name);
|
|
1096
|
+
if (entry.isDirectory()) {
|
|
1097
|
+
copyDirRecursive(srcPath, destPath);
|
|
1098
|
+
} else {
|
|
1099
|
+
fs.copyFileSync(srcPath, destPath);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// Main update function
|
|
1105
|
+
async function update() {
|
|
1106
|
+
console.log('');
|
|
1107
|
+
log.info('╔═══════════════════════════════════════════════════════════╗');
|
|
1108
|
+
log.info('║ 🔄 anchi-toolkit Update ║');
|
|
1109
|
+
log.info('╚═══════════════════════════════════════════════════════════╝');
|
|
1110
|
+
console.log('');
|
|
1111
|
+
|
|
1112
|
+
const currentVersion = getCurrentVersion();
|
|
1113
|
+
log.gray(`📦 Current version: ${currentVersion}`);
|
|
1114
|
+
|
|
1115
|
+
log.info('🔍 Checking for updates...');
|
|
1116
|
+
const latestVersion = await getLatestVersion();
|
|
1117
|
+
|
|
1118
|
+
if (latestVersion === '0.0.0') {
|
|
1119
|
+
log.warn('⚠️ Could not check npm registry.');
|
|
1120
|
+
log.gray(' Package may not be published yet.');
|
|
1121
|
+
log.info('');
|
|
1122
|
+
log.info('💡 For now, you can update manually:');
|
|
1123
|
+
log.success(' git pull origin main');
|
|
1124
|
+
return;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
log.gray(`📦 Latest version: ${latestVersion}`);
|
|
1128
|
+
console.log('');
|
|
1129
|
+
|
|
1130
|
+
if (isNewer(latestVersion, currentVersion)) {
|
|
1131
|
+
log.warn(`🆕 New version available: ${currentVersion} → ${latestVersion}`);
|
|
1132
|
+
console.log('');
|
|
1133
|
+
log.info('To update, run:');
|
|
1134
|
+
log.success(' npm update -g anchi-toolkit');
|
|
1135
|
+
log.info('');
|
|
1136
|
+
log.info('Or reinstall:');
|
|
1137
|
+
log.success(' npm install -g anchi-toolkit@latest');
|
|
1138
|
+
} else {
|
|
1139
|
+
log.success('✅ You are using the latest version!');
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
console.log('');
|
|
1143
|
+
log.info('💡 To update project files:');
|
|
1144
|
+
log.success(' npx anchi-toolkit install');
|
|
1145
|
+
log.gray(' (Use Overwrite when prompted)');
|
|
1146
|
+
console.log('');
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
module.exports = { update };
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
/***/ }),
|
|
1153
|
+
|
|
1154
|
+
/***/ 256:
|
|
1155
|
+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
1156
|
+
|
|
1157
|
+
// =============================================================================
|
|
1158
|
+
// anchi-toolkit Config Manager
|
|
1159
|
+
// Handles loading, saving, and merging configuration
|
|
1160
|
+
// =============================================================================
|
|
1161
|
+
|
|
1162
|
+
const fs = __nccwpck_require__(896);
|
|
1163
|
+
const path = __nccwpck_require__(928);
|
|
1164
|
+
|
|
1165
|
+
const CONFIG_FILENAME = 'anchi-toolkit.config.yaml';
|
|
1166
|
+
|
|
1167
|
+
// Default configuration
|
|
1168
|
+
const DEFAULT_CONFIG = {
|
|
1169
|
+
version: '2.1',
|
|
1170
|
+
profile: 'developer',
|
|
1171
|
+
|
|
1172
|
+
model_preference: {
|
|
1173
|
+
default: 'auto',
|
|
1174
|
+
complex: 'opus',
|
|
1175
|
+
economy: 'haiku',
|
|
1176
|
+
},
|
|
1177
|
+
|
|
1178
|
+
features: {
|
|
1179
|
+
auto_commit: false,
|
|
1180
|
+
auto_push: false,
|
|
1181
|
+
progress_indicators: true,
|
|
1182
|
+
summary_cards: true,
|
|
1183
|
+
quick_actions: true,
|
|
1184
|
+
},
|
|
1185
|
+
|
|
1186
|
+
team: {
|
|
1187
|
+
role: null, // frontend, backend, fullstack, lead, etc.
|
|
1188
|
+
slack_webhook: null,
|
|
1189
|
+
notifications: true,
|
|
1190
|
+
},
|
|
1191
|
+
|
|
1192
|
+
hooks: {
|
|
1193
|
+
enabled: false,
|
|
1194
|
+
pre_commit: [],
|
|
1195
|
+
post_merge: [],
|
|
1196
|
+
},
|
|
1197
|
+
};
|
|
1198
|
+
|
|
1199
|
+
/**
|
|
1200
|
+
* Parse simple YAML (subset)
|
|
1201
|
+
*/
|
|
1202
|
+
function parseYaml(content) {
|
|
1203
|
+
const result = {};
|
|
1204
|
+
const lines = content.split('\n');
|
|
1205
|
+
const stack = [{ obj: result, indent: -1 }];
|
|
1206
|
+
|
|
1207
|
+
for (const line of lines) {
|
|
1208
|
+
if (line.trim() === '' || line.trim().startsWith('#')) continue;
|
|
1209
|
+
|
|
1210
|
+
const match = line.match(/^(\s*)([^:]+):\s*(.*)$/);
|
|
1211
|
+
if (!match) continue;
|
|
1212
|
+
|
|
1213
|
+
const indent = match[1].length;
|
|
1214
|
+
const key = match[2].trim();
|
|
1215
|
+
let value = match[3].trim();
|
|
1216
|
+
|
|
1217
|
+
// Pop stack until we find parent
|
|
1218
|
+
while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
|
|
1219
|
+
stack.pop();
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
const parent = stack[stack.length - 1].obj;
|
|
1223
|
+
|
|
1224
|
+
if (value === '' || value === null) {
|
|
1225
|
+
// Nested object
|
|
1226
|
+
parent[key] = {};
|
|
1227
|
+
stack.push({ obj: parent[key], indent: indent });
|
|
1228
|
+
} else {
|
|
1229
|
+
// Parse value
|
|
1230
|
+
if (value === 'true') value = true;
|
|
1231
|
+
else if (value === 'false') value = false;
|
|
1232
|
+
else if (value === 'null') value = null;
|
|
1233
|
+
else if (!isNaN(value)) value = Number(value);
|
|
1234
|
+
else if (value.startsWith('"') && value.endsWith('"')) value = value.slice(1, -1);
|
|
1235
|
+
else if (value.startsWith('[') && value.endsWith(']')) {
|
|
1236
|
+
value = value.slice(1, -1).split(',').map(s => s.trim());
|
|
1237
|
+
}
|
|
1238
|
+
parent[key] = value;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
return result;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* Stringify to YAML
|
|
1247
|
+
*/
|
|
1248
|
+
function stringifyYaml(obj, indent = 0) {
|
|
1249
|
+
let result = '';
|
|
1250
|
+
const prefix = ' '.repeat(indent);
|
|
1251
|
+
|
|
1252
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
1253
|
+
if (value === null) {
|
|
1254
|
+
result += `${prefix}${key}: null\n`;
|
|
1255
|
+
} else if (typeof value === 'object' && !Array.isArray(value)) {
|
|
1256
|
+
result += `${prefix}${key}:\n`;
|
|
1257
|
+
result += stringifyYaml(value, indent + 1);
|
|
1258
|
+
} else if (Array.isArray(value)) {
|
|
1259
|
+
result += `${prefix}${key}: [${value.join(', ')}]\n`;
|
|
1260
|
+
} else if (typeof value === 'string') {
|
|
1261
|
+
result += `${prefix}${key}: "${value}"\n`;
|
|
1262
|
+
} else {
|
|
1263
|
+
result += `${prefix}${key}: ${value}\n`;
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
return result;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* Deep merge objects
|
|
1272
|
+
*/
|
|
1273
|
+
function deepMerge(target, source) {
|
|
1274
|
+
const result = { ...target };
|
|
1275
|
+
|
|
1276
|
+
for (const key of Object.keys(source)) {
|
|
1277
|
+
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
|
1278
|
+
result[key] = deepMerge(target[key] || {}, source[key]);
|
|
1279
|
+
} else {
|
|
1280
|
+
result[key] = source[key];
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
return result;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
/**
|
|
1288
|
+
* Get config directory (.antigravity or .cursor)
|
|
1289
|
+
*/
|
|
1290
|
+
function getConfigDir(targetDir) {
|
|
1291
|
+
// Check for Antigravity first
|
|
1292
|
+
const antigravityDir = path.join(targetDir, '.antigravity');
|
|
1293
|
+
if (fs.existsSync(antigravityDir)) {
|
|
1294
|
+
return antigravityDir;
|
|
1295
|
+
}
|
|
1296
|
+
// Fallback to Cursor
|
|
1297
|
+
return path.join(targetDir, '.cursor');
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
/**
|
|
1301
|
+
* Load config from target directory
|
|
1302
|
+
*/
|
|
1303
|
+
function loadConfig(targetDir) {
|
|
1304
|
+
const configDir = getConfigDir(targetDir);
|
|
1305
|
+
const configPath = path.join(configDir, CONFIG_FILENAME);
|
|
1306
|
+
|
|
1307
|
+
if (!fs.existsSync(configPath)) {
|
|
1308
|
+
return DEFAULT_CONFIG;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
try {
|
|
1312
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
1313
|
+
const userConfig = parseYaml(content);
|
|
1314
|
+
return deepMerge(DEFAULT_CONFIG, userConfig);
|
|
1315
|
+
} catch (e) {
|
|
1316
|
+
console.warn(`Warning: Could not parse config: ${e.message}`);
|
|
1317
|
+
return DEFAULT_CONFIG;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
/**
|
|
1322
|
+
* Save config to target directory
|
|
1323
|
+
*/
|
|
1324
|
+
function saveConfig(targetDir, config) {
|
|
1325
|
+
const configDir = getConfigDir(targetDir);
|
|
1326
|
+
const configPath = path.join(configDir, CONFIG_FILENAME);
|
|
1327
|
+
|
|
1328
|
+
if (!fs.existsSync(configDir)) {
|
|
1329
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
const header = `# anchi-toolkit Configuration
|
|
1333
|
+
# https://github.com/ANCHI-STE/anchi-webkit-dev
|
|
1334
|
+
# ═══════════════════════════════════════════════════════════════
|
|
1335
|
+
|
|
1336
|
+
`;
|
|
1337
|
+
|
|
1338
|
+
fs.writeFileSync(configPath, header + stringifyYaml(config));
|
|
1339
|
+
return configPath;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
/**
|
|
1343
|
+
* Get config value by path (e.g., 'features.auto_commit')
|
|
1344
|
+
*/
|
|
1345
|
+
function getConfigValue(config, keyPath) {
|
|
1346
|
+
return keyPath.split('.').reduce((obj, key) => obj?.[key], config);
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
/**
|
|
1350
|
+
* Set config value by path
|
|
1351
|
+
*/
|
|
1352
|
+
function setConfigValue(config, keyPath, value) {
|
|
1353
|
+
const keys = keyPath.split('.');
|
|
1354
|
+
const lastKey = keys.pop();
|
|
1355
|
+
const target = keys.reduce((obj, key) => obj[key] = obj[key] || {}, config);
|
|
1356
|
+
target[lastKey] = value;
|
|
1357
|
+
return config;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
module.exports = {
|
|
1361
|
+
DEFAULT_CONFIG,
|
|
1362
|
+
CONFIG_FILENAME,
|
|
1363
|
+
loadConfig,
|
|
1364
|
+
saveConfig,
|
|
1365
|
+
parseYaml,
|
|
1366
|
+
stringifyYaml,
|
|
1367
|
+
deepMerge,
|
|
1368
|
+
getConfigValue,
|
|
1369
|
+
setConfigValue,
|
|
1370
|
+
getConfigDir,
|
|
1371
|
+
};
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
/***/ }),
|
|
1375
|
+
|
|
1376
|
+
/***/ 835:
|
|
1377
|
+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
1378
|
+
|
|
1379
|
+
// =============================================================================
|
|
1380
|
+
// Tech Stack Detector
|
|
1381
|
+
// =============================================================================
|
|
1382
|
+
|
|
1383
|
+
const fs = __nccwpck_require__(896);
|
|
1384
|
+
const path = __nccwpck_require__(928);
|
|
1385
|
+
|
|
1386
|
+
function detectTechStack(targetPath) {
|
|
1387
|
+
const detected = {
|
|
1388
|
+
frameworks: [],
|
|
1389
|
+
languages: [],
|
|
1390
|
+
databases: [],
|
|
1391
|
+
styling: [],
|
|
1392
|
+
auth: [],
|
|
1393
|
+
testing: [],
|
|
1394
|
+
};
|
|
1395
|
+
|
|
1396
|
+
// Check package.json
|
|
1397
|
+
const pkgPath = path.join(targetPath, 'package.json');
|
|
1398
|
+
if (fs.existsSync(pkgPath)) {
|
|
1399
|
+
try {
|
|
1400
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
1401
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
1402
|
+
|
|
1403
|
+
// Frameworks
|
|
1404
|
+
if (deps['next']) detected.frameworks.push('next');
|
|
1405
|
+
if (deps['react']) detected.frameworks.push('react');
|
|
1406
|
+
if (deps['vue']) detected.frameworks.push('vue');
|
|
1407
|
+
if (deps['express']) detected.frameworks.push('express');
|
|
1408
|
+
if (deps['fastify']) detected.frameworks.push('fastify');
|
|
1409
|
+
if (deps['@nestjs/core']) detected.frameworks.push('nestjs');
|
|
1410
|
+
|
|
1411
|
+
// Databases
|
|
1412
|
+
if (deps['prisma'] || deps['@prisma/client']) detected.databases.push('prisma');
|
|
1413
|
+
if (deps['mongoose']) detected.databases.push('mongodb');
|
|
1414
|
+
if (deps['pg']) detected.databases.push('postgresql');
|
|
1415
|
+
if (deps['mysql2']) detected.databases.push('mysql');
|
|
1416
|
+
if (deps['better-sqlite3']) detected.databases.push('sqlite');
|
|
1417
|
+
|
|
1418
|
+
// Styling
|
|
1419
|
+
if (deps['tailwindcss']) detected.styling.push('tailwind');
|
|
1420
|
+
if (deps['styled-components']) detected.styling.push('styled-components');
|
|
1421
|
+
if (deps['@emotion/react']) detected.styling.push('emotion');
|
|
1422
|
+
if (deps['sass']) detected.styling.push('sass');
|
|
1423
|
+
|
|
1424
|
+
// Auth
|
|
1425
|
+
if (deps['next-auth']) detected.auth.push('next-auth');
|
|
1426
|
+
if (deps['better-auth']) detected.auth.push('better-auth');
|
|
1427
|
+
if (deps['passport']) detected.auth.push('passport');
|
|
1428
|
+
|
|
1429
|
+
// Testing
|
|
1430
|
+
if (deps['jest']) detected.testing.push('jest');
|
|
1431
|
+
if (deps['vitest']) detected.testing.push('vitest');
|
|
1432
|
+
if (deps['playwright']) detected.testing.push('playwright');
|
|
1433
|
+
|
|
1434
|
+
// Languages
|
|
1435
|
+
if (deps['typescript']) detected.languages.push('typescript');
|
|
1436
|
+
} catch (e) {
|
|
1437
|
+
// Ignore parse errors
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
// Check for config files
|
|
1442
|
+
if (fs.existsSync(path.join(targetPath, 'tailwind.config.js')) ||
|
|
1443
|
+
fs.existsSync(path.join(targetPath, 'tailwind.config.ts'))) {
|
|
1444
|
+
if (!detected.styling.includes('tailwind')) detected.styling.push('tailwind');
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
if (fs.existsSync(path.join(targetPath, 'prisma'))) {
|
|
1448
|
+
if (!detected.databases.includes('prisma')) detected.databases.push('prisma');
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
if (fs.existsSync(path.join(targetPath, 'tsconfig.json'))) {
|
|
1452
|
+
if (!detected.languages.includes('typescript')) detected.languages.push('typescript');
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
return detected;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
function suggestSkills(detected) {
|
|
1459
|
+
const suggestions = new Set();
|
|
1460
|
+
|
|
1461
|
+
// Framework-based suggestions
|
|
1462
|
+
if (detected.frameworks.includes('next') || detected.frameworks.includes('react')) {
|
|
1463
|
+
suggestions.add('frontend-development');
|
|
1464
|
+
suggestions.add('web-frameworks');
|
|
1465
|
+
}
|
|
1466
|
+
if (detected.frameworks.includes('express') || detected.frameworks.includes('fastify')) {
|
|
1467
|
+
suggestions.add('backend-development');
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
// Database suggestions
|
|
1471
|
+
if (detected.databases.length > 0) {
|
|
1472
|
+
suggestions.add('databases');
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
// Styling suggestions
|
|
1476
|
+
if (detected.styling.includes('tailwind')) {
|
|
1477
|
+
suggestions.add('ui-styling');
|
|
1478
|
+
suggestions.add('frontend-design');
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
// Auth suggestions
|
|
1482
|
+
if (detected.auth.includes('better-auth')) {
|
|
1483
|
+
suggestions.add('better-auth');
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
// Default suggestions if nothing detected
|
|
1487
|
+
if (suggestions.size === 0) {
|
|
1488
|
+
suggestions.add('frontend-development');
|
|
1489
|
+
suggestions.add('planning');
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
return Array.from(suggestions);
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
function formatDetectedStack(detected) {
|
|
1496
|
+
const parts = [];
|
|
1497
|
+
|
|
1498
|
+
if (detected.frameworks.length) {
|
|
1499
|
+
parts.push(`Frameworks: ${detected.frameworks.join(', ')}`);
|
|
1500
|
+
}
|
|
1501
|
+
if (detected.databases.length) {
|
|
1502
|
+
parts.push(`Database: ${detected.databases.join(', ')}`);
|
|
1503
|
+
}
|
|
1504
|
+
if (detected.styling.length) {
|
|
1505
|
+
parts.push(`Styling: ${detected.styling.join(', ')}`);
|
|
1506
|
+
}
|
|
1507
|
+
if (detected.auth.length) {
|
|
1508
|
+
parts.push(`Auth: ${detected.auth.join(', ')}`);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
return parts.length > 0 ? parts.join(' | ') : 'No specific tech detected';
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
module.exports = {
|
|
1515
|
+
detectTechStack,
|
|
1516
|
+
suggestSkills,
|
|
1517
|
+
formatDetectedStack,
|
|
1518
|
+
};
|
|
1519
|
+
|
|
1520
|
+
|
|
1521
|
+
/***/ }),
|
|
1522
|
+
|
|
1523
|
+
/***/ 355:
|
|
1524
|
+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
1525
|
+
|
|
1526
|
+
// =============================================================================
|
|
1527
|
+
// anchi-toolkit Memory Manager
|
|
1528
|
+
// Saves and loads project context to avoid AI "forgetting"
|
|
1529
|
+
// =============================================================================
|
|
1530
|
+
|
|
1531
|
+
const fs = __nccwpck_require__(896);
|
|
1532
|
+
const path = __nccwpck_require__(928);
|
|
1533
|
+
const { getConfigDir } = __nccwpck_require__(256);
|
|
1534
|
+
|
|
1535
|
+
const MEMORY_DIR_NAME = '.ai-memory';
|
|
1536
|
+
const MEMORY_FILE = 'context.json'; // Changed from memory.json to context.json based on what I saw in ls
|
|
1537
|
+
|
|
1538
|
+
// Default memory structure
|
|
1539
|
+
const DEFAULT_MEMORY = {
|
|
1540
|
+
version: '1.0',
|
|
1541
|
+
project: {
|
|
1542
|
+
name: null,
|
|
1543
|
+
description: null,
|
|
1544
|
+
tech_stack: [],
|
|
1545
|
+
architecture: null,
|
|
1546
|
+
created_at: null,
|
|
1547
|
+
updated_at: null,
|
|
1548
|
+
},
|
|
1549
|
+
session: {
|
|
1550
|
+
last_task: null,
|
|
1551
|
+
current_phase: null,
|
|
1552
|
+
open_files: [],
|
|
1553
|
+
pending_actions: [],
|
|
1554
|
+
last_accessed: null,
|
|
1555
|
+
},
|
|
1556
|
+
decisions: [],
|
|
1557
|
+
notes: [],
|
|
1558
|
+
entities: {},
|
|
1559
|
+
};
|
|
1560
|
+
|
|
1561
|
+
/**
|
|
1562
|
+
* Get memory file path
|
|
1563
|
+
*/
|
|
1564
|
+
function getMemoryPath(targetDir) {
|
|
1565
|
+
const configDir = getConfigDir(targetDir);
|
|
1566
|
+
return path.join(configDir, MEMORY_DIR_NAME, MEMORY_FILE);
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
/**
|
|
1570
|
+
* Ensure memory directory exists
|
|
1571
|
+
*/
|
|
1572
|
+
function ensureMemoryDir(targetDir) {
|
|
1573
|
+
const configDir = getConfigDir(targetDir);
|
|
1574
|
+
const memoryDir = path.join(configDir, MEMORY_DIR_NAME);
|
|
1575
|
+
if (!fs.existsSync(memoryDir)) {
|
|
1576
|
+
fs.mkdirSync(memoryDir, { recursive: true });
|
|
1577
|
+
}
|
|
1578
|
+
return memoryDir;
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
/**
|
|
1582
|
+
* Load memory from file
|
|
1583
|
+
*/
|
|
1584
|
+
function loadMemory(targetDir = process.cwd()) {
|
|
1585
|
+
const memoryPath = getMemoryPath(targetDir);
|
|
1586
|
+
|
|
1587
|
+
if (!fs.existsSync(memoryPath)) {
|
|
1588
|
+
return { ...DEFAULT_MEMORY };
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
try {
|
|
1592
|
+
const content = fs.readFileSync(memoryPath, 'utf-8');
|
|
1593
|
+
const memory = JSON.parse(content);
|
|
1594
|
+
return { ...DEFAULT_MEMORY, ...memory };
|
|
1595
|
+
} catch (e) {
|
|
1596
|
+
console.warn(`Warning: Could not parse memory: ${e.message}`);
|
|
1597
|
+
return { ...DEFAULT_MEMORY };
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
/**
|
|
1602
|
+
* Save memory to file
|
|
1603
|
+
*/
|
|
1604
|
+
function saveMemory(targetDir, memory) {
|
|
1605
|
+
ensureMemoryDir(targetDir);
|
|
1606
|
+
const memoryPath = getMemoryPath(targetDir);
|
|
1607
|
+
|
|
1608
|
+
memory.session.last_accessed = new Date().toISOString();
|
|
1609
|
+
memory.project.updated_at = new Date().toISOString();
|
|
1610
|
+
|
|
1611
|
+
fs.writeFileSync(memoryPath, JSON.stringify(memory, null, 2));
|
|
1612
|
+
return memoryPath;
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
/**
|
|
1616
|
+
* Update project info
|
|
1617
|
+
*/
|
|
1618
|
+
function updateProject(targetDir, projectInfo) {
|
|
1619
|
+
const memory = loadMemory(targetDir);
|
|
1620
|
+
memory.project = {
|
|
1621
|
+
...memory.project,
|
|
1622
|
+
...projectInfo,
|
|
1623
|
+
updated_at: new Date().toISOString(),
|
|
1624
|
+
};
|
|
1625
|
+
if (!memory.project.created_at) {
|
|
1626
|
+
memory.project.created_at = new Date().toISOString();
|
|
1627
|
+
}
|
|
1628
|
+
saveMemory(targetDir, memory);
|
|
1629
|
+
return memory;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
/**
|
|
1633
|
+
* Update session info
|
|
1634
|
+
*/
|
|
1635
|
+
function updateSession(targetDir, sessionInfo) {
|
|
1636
|
+
const memory = loadMemory(targetDir);
|
|
1637
|
+
memory.session = {
|
|
1638
|
+
...memory.session,
|
|
1639
|
+
...sessionInfo,
|
|
1640
|
+
last_accessed: new Date().toISOString(),
|
|
1641
|
+
};
|
|
1642
|
+
saveMemory(targetDir, memory);
|
|
1643
|
+
return memory;
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
/**
|
|
1647
|
+
* Add a decision
|
|
1648
|
+
*/
|
|
1649
|
+
function addDecision(targetDir, decision, reason, filesAffected = []) {
|
|
1650
|
+
const memory = loadMemory(targetDir);
|
|
1651
|
+
memory.decisions.push({
|
|
1652
|
+
id: Date.now(),
|
|
1653
|
+
decision,
|
|
1654
|
+
reason,
|
|
1655
|
+
files_affected: filesAffected,
|
|
1656
|
+
timestamp: new Date().toISOString(),
|
|
1657
|
+
});
|
|
1658
|
+
saveMemory(targetDir, memory);
|
|
1659
|
+
return memory;
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
/**
|
|
1663
|
+
* Add a note
|
|
1664
|
+
*/
|
|
1665
|
+
function addNote(targetDir, note, category = 'general') {
|
|
1666
|
+
const memory = loadMemory(targetDir);
|
|
1667
|
+
memory.notes.push({
|
|
1668
|
+
id: Date.now(),
|
|
1669
|
+
note,
|
|
1670
|
+
category,
|
|
1671
|
+
timestamp: new Date().toISOString(),
|
|
1672
|
+
});
|
|
1673
|
+
saveMemory(targetDir, memory);
|
|
1674
|
+
return memory;
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
/**
|
|
1678
|
+
* Add/update an entity
|
|
1679
|
+
*/
|
|
1680
|
+
function upsertEntity(targetDir, entityName, entityData) {
|
|
1681
|
+
const memory = loadMemory(targetDir);
|
|
1682
|
+
memory.entities[entityName] = {
|
|
1683
|
+
...memory.entities[entityName],
|
|
1684
|
+
...entityData,
|
|
1685
|
+
updated_at: new Date().toISOString(),
|
|
1686
|
+
};
|
|
1687
|
+
saveMemory(targetDir, memory);
|
|
1688
|
+
return memory;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
/**
|
|
1692
|
+
* Get entity
|
|
1693
|
+
*/
|
|
1694
|
+
function getEntity(targetDir, entityName) {
|
|
1695
|
+
const memory = loadMemory(targetDir);
|
|
1696
|
+
return memory.entities[entityName] || null;
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
/**
|
|
1700
|
+
* Clear memory
|
|
1701
|
+
*/
|
|
1702
|
+
function clearMemory(targetDir) {
|
|
1703
|
+
const memory = { ...DEFAULT_MEMORY };
|
|
1704
|
+
memory.project.created_at = new Date().toISOString();
|
|
1705
|
+
saveMemory(targetDir, memory);
|
|
1706
|
+
return memory;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
/**
|
|
1710
|
+
* Get memory summary (for AI context)
|
|
1711
|
+
*/
|
|
1712
|
+
function getMemorySummary(targetDir) {
|
|
1713
|
+
const memory = loadMemory(targetDir);
|
|
1714
|
+
|
|
1715
|
+
let summary = '';
|
|
1716
|
+
|
|
1717
|
+
// Project info
|
|
1718
|
+
if (memory.project.name) {
|
|
1719
|
+
summary += `## Project: ${memory.project.name}\n`;
|
|
1720
|
+
if (memory.project.description) {
|
|
1721
|
+
summary += `${memory.project.description}\n`;
|
|
1722
|
+
}
|
|
1723
|
+
if (memory.project.tech_stack.length > 0) {
|
|
1724
|
+
summary += `Tech Stack: ${memory.project.tech_stack.join(', ')}\n`;
|
|
1725
|
+
}
|
|
1726
|
+
if (memory.project.architecture) {
|
|
1727
|
+
summary += `Architecture: ${memory.project.architecture}\n`;
|
|
1728
|
+
}
|
|
1729
|
+
summary += '\n';
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
// Session info
|
|
1733
|
+
if (memory.session.last_task) {
|
|
1734
|
+
summary += `## Last Session\n`;
|
|
1735
|
+
summary += `Task: ${memory.session.last_task}\n`;
|
|
1736
|
+
if (memory.session.current_phase) {
|
|
1737
|
+
summary += `Phase: ${memory.session.current_phase}\n`;
|
|
1738
|
+
}
|
|
1739
|
+
summary += '\n';
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
// Recent decisions
|
|
1743
|
+
if (memory.decisions.length > 0) {
|
|
1744
|
+
summary += `## Recent Decisions\n`;
|
|
1745
|
+
const recent = memory.decisions.slice(-5);
|
|
1746
|
+
for (const d of recent) {
|
|
1747
|
+
summary += `- ${d.decision}\n`;
|
|
1748
|
+
}
|
|
1749
|
+
summary += '\n';
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
// Recent notes
|
|
1753
|
+
if (memory.notes.length > 0) {
|
|
1754
|
+
summary += `## Notes\n`;
|
|
1755
|
+
const recent = memory.notes.slice(-5);
|
|
1756
|
+
for (const n of recent) {
|
|
1757
|
+
summary += `- [${n.category}] ${n.note}\n`;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
return summary || 'No memory saved yet.';
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
module.exports = {
|
|
1765
|
+
DEFAULT_MEMORY,
|
|
1766
|
+
loadMemory,
|
|
1767
|
+
saveMemory,
|
|
1768
|
+
updateProject,
|
|
1769
|
+
updateSession,
|
|
1770
|
+
addDecision,
|
|
1771
|
+
addNote,
|
|
1772
|
+
upsertEntity,
|
|
1773
|
+
getEntity,
|
|
1774
|
+
clearMemory,
|
|
1775
|
+
getMemorySummary,
|
|
1776
|
+
getMemoryPath,
|
|
1777
|
+
ensureMemoryDir,
|
|
1778
|
+
};
|
|
1779
|
+
|
|
1780
|
+
|
|
1781
|
+
/***/ }),
|
|
1782
|
+
|
|
1783
|
+
/***/ 251:
|
|
1784
|
+
/***/ ((module) => {
|
|
1785
|
+
|
|
1786
|
+
// =============================================================================
|
|
1787
|
+
// Role-based Profiles
|
|
1788
|
+
// =============================================================================
|
|
1789
|
+
|
|
1790
|
+
const PROFILES = {
|
|
1791
|
+
minimal: {
|
|
1792
|
+
name: 'Minimal',
|
|
1793
|
+
description: 'Core commands only (fastest install)',
|
|
1794
|
+
commands: ['start', 'plan', 'cook', 'fix'],
|
|
1795
|
+
agents: [],
|
|
1796
|
+
skills: [],
|
|
1797
|
+
includePresets: false,
|
|
1798
|
+
includeDocs: false,
|
|
1799
|
+
},
|
|
1800
|
+
|
|
1801
|
+
developer: {
|
|
1802
|
+
name: 'Developer',
|
|
1803
|
+
description: 'Daily coding (commands + basic agents)',
|
|
1804
|
+
commands: ['start', 'plan', 'cook', 'fix', 'scout', 'generate'],
|
|
1805
|
+
agents: ['planner', 'scout', 'fullstack-developer', 'debugger'],
|
|
1806
|
+
skills: ['frontend-development', 'backend-development', 'databases'],
|
|
1807
|
+
includePresets: false,
|
|
1808
|
+
includeDocs: false,
|
|
1809
|
+
},
|
|
1810
|
+
|
|
1811
|
+
ui_ux: {
|
|
1812
|
+
name: 'UI/UX Designer',
|
|
1813
|
+
description: 'Frontend & Design focus',
|
|
1814
|
+
commands: ['start', 'plan', 'cook', 'design-ui', 'generate'],
|
|
1815
|
+
agents: ['ui-ux-designer', 'design-system-architect', 'planner'],
|
|
1816
|
+
skills: ['frontend-development', 'frontend-design', 'ui-styling', 'aesthetic'],
|
|
1817
|
+
includePresets: false,
|
|
1818
|
+
includeDocs: false,
|
|
1819
|
+
},
|
|
1820
|
+
|
|
1821
|
+
architect: {
|
|
1822
|
+
name: 'Architect',
|
|
1823
|
+
description: 'System design & DDD',
|
|
1824
|
+
commands: ['start', 'plan', 'cook', 'fix', 'design-domain', 'review'],
|
|
1825
|
+
agents: ['planner', 'ddd-architect', 'code-reviewer', 'researcher'],
|
|
1826
|
+
skills: ['ddd-modular-monolith', 'planning', 'backend-development', 'databases'],
|
|
1827
|
+
includePresets: true,
|
|
1828
|
+
includeDocs: true,
|
|
1829
|
+
},
|
|
1830
|
+
|
|
1831
|
+
lead: {
|
|
1832
|
+
name: 'Team Lead',
|
|
1833
|
+
description: 'Code review & management',
|
|
1834
|
+
commands: ['start', 'plan', 'cook', 'fix', 'review', 'scout', 'summary'],
|
|
1835
|
+
agents: ['planner', 'code-reviewer', 'project-manager', 'docs-manager', 'git-manager'],
|
|
1836
|
+
skills: ['code-review', 'planning', 'debugging'],
|
|
1837
|
+
includePresets: false,
|
|
1838
|
+
includeDocs: true,
|
|
1839
|
+
},
|
|
1840
|
+
|
|
1841
|
+
fullstack: {
|
|
1842
|
+
name: 'Full Stack',
|
|
1843
|
+
description: 'Everything included',
|
|
1844
|
+
commands: 'all',
|
|
1845
|
+
agents: 'all',
|
|
1846
|
+
skills: 'all',
|
|
1847
|
+
includePresets: true,
|
|
1848
|
+
includeDocs: true,
|
|
1849
|
+
},
|
|
1850
|
+
};
|
|
1851
|
+
|
|
1852
|
+
function getProfile(name) {
|
|
1853
|
+
return PROFILES[name] || null;
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
function getProfileList() {
|
|
1857
|
+
return Object.entries(PROFILES).map(([key, profile]) => ({
|
|
1858
|
+
key,
|
|
1859
|
+
name: profile.name,
|
|
1860
|
+
description: profile.description,
|
|
1861
|
+
}));
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
function getProfileEstimate(profileKey) {
|
|
1865
|
+
const profile = PROFILES[profileKey];
|
|
1866
|
+
if (!profile) return null;
|
|
1867
|
+
|
|
1868
|
+
const estimates = {
|
|
1869
|
+
minimal: { files: 5, size: '~50KB' },
|
|
1870
|
+
developer: { files: 30, size: '~300KB' },
|
|
1871
|
+
ui_ux: { files: 25, size: '~250KB' },
|
|
1872
|
+
architect: { files: 50, size: '~500KB' },
|
|
1873
|
+
lead: { files: 40, size: '~400KB' },
|
|
1874
|
+
fullstack: { files: 400, size: '~5MB' },
|
|
1875
|
+
};
|
|
1876
|
+
|
|
1877
|
+
return estimates[profileKey] || { files: '?', size: '?' };
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
module.exports = {
|
|
1881
|
+
PROFILES,
|
|
1882
|
+
getProfile,
|
|
1883
|
+
getProfileList,
|
|
1884
|
+
getProfileEstimate,
|
|
1885
|
+
};
|
|
1886
|
+
|
|
1887
|
+
|
|
1888
|
+
/***/ }),
|
|
1889
|
+
|
|
1890
|
+
/***/ 568:
|
|
1891
|
+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
1892
|
+
|
|
1893
|
+
// =============================================================================
|
|
1894
|
+
// Size Calculator
|
|
1895
|
+
// =============================================================================
|
|
1896
|
+
|
|
1897
|
+
const fs = __nccwpck_require__(896);
|
|
1898
|
+
const path = __nccwpck_require__(928);
|
|
1899
|
+
|
|
1900
|
+
function countFilesRecursive(dir) {
|
|
1901
|
+
let count = 0;
|
|
1902
|
+
let size = 0;
|
|
1903
|
+
|
|
1904
|
+
if (!fs.existsSync(dir)) return { count: 0, size: 0 };
|
|
1905
|
+
|
|
1906
|
+
try {
|
|
1907
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
1908
|
+
for (const entry of entries) {
|
|
1909
|
+
const fullPath = path.join(dir, entry.name);
|
|
1910
|
+
if (entry.isDirectory()) {
|
|
1911
|
+
const sub = countFilesRecursive(fullPath);
|
|
1912
|
+
count += sub.count;
|
|
1913
|
+
size += sub.size;
|
|
1914
|
+
} else {
|
|
1915
|
+
count++;
|
|
1916
|
+
try {
|
|
1917
|
+
const stats = fs.statSync(fullPath);
|
|
1918
|
+
size += stats.size;
|
|
1919
|
+
} catch (e) {
|
|
1920
|
+
// Ignore
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
} catch (e) {
|
|
1925
|
+
// Ignore
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
return { count, size };
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
function formatSize(bytes) {
|
|
1932
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
1933
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
1934
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
function calculateInstallSize(kitPath, components) {
|
|
1938
|
+
let totalFiles = 0;
|
|
1939
|
+
let totalSize = 0;
|
|
1940
|
+
|
|
1941
|
+
for (const comp of components) {
|
|
1942
|
+
const compPath = path.join(kitPath, comp);
|
|
1943
|
+
if (fs.existsSync(compPath)) {
|
|
1944
|
+
const stats = fs.statSync(compPath);
|
|
1945
|
+
if (stats.isDirectory()) {
|
|
1946
|
+
const { count, size } = countFilesRecursive(compPath);
|
|
1947
|
+
totalFiles += count;
|
|
1948
|
+
totalSize += size;
|
|
1949
|
+
} else {
|
|
1950
|
+
totalFiles++;
|
|
1951
|
+
totalSize += stats.size;
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
return {
|
|
1957
|
+
files: totalFiles,
|
|
1958
|
+
size: totalSize,
|
|
1959
|
+
formatted: formatSize(totalSize),
|
|
1960
|
+
};
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
function getComponentPaths(profile, kitPath) {
|
|
1964
|
+
const components = [];
|
|
1965
|
+
|
|
1966
|
+
// Commands
|
|
1967
|
+
if (profile.commands === 'all') {
|
|
1968
|
+
components.push('.cursor/commands');
|
|
1969
|
+
} else if (Array.isArray(profile.commands)) {
|
|
1970
|
+
profile.commands.forEach(cmd => {
|
|
1971
|
+
components.push(`.cursor/commands/${cmd}.md`);
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
// Agents
|
|
1976
|
+
if (profile.agents === 'all') {
|
|
1977
|
+
components.push('.cursor/agents');
|
|
1978
|
+
} else if (Array.isArray(profile.agents)) {
|
|
1979
|
+
profile.agents.forEach(agent => {
|
|
1980
|
+
components.push(`.cursor/agents/${agent}.md`);
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
// Skills
|
|
1985
|
+
if (profile.skills === 'all') {
|
|
1986
|
+
components.push('.cursor/skills');
|
|
1987
|
+
} else if (Array.isArray(profile.skills)) {
|
|
1988
|
+
profile.skills.forEach(skill => {
|
|
1989
|
+
components.push(`.cursor/skills/${skill}`);
|
|
1990
|
+
});
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
// Extras
|
|
1994
|
+
if (profile.includePresets) {
|
|
1995
|
+
components.push('presets');
|
|
1996
|
+
}
|
|
1997
|
+
if (profile.includeDocs) {
|
|
1998
|
+
components.push('docs');
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
// Always include
|
|
2002
|
+
components.push('.cursorrules');
|
|
2003
|
+
components.push('CURSOR.md');
|
|
2004
|
+
|
|
2005
|
+
return components;
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
module.exports = {
|
|
2009
|
+
countFilesRecursive,
|
|
2010
|
+
formatSize,
|
|
2011
|
+
calculateInstallSize,
|
|
2012
|
+
getComponentPaths,
|
|
2013
|
+
};
|
|
2014
|
+
|
|
2015
|
+
|
|
2016
|
+
/***/ }),
|
|
2017
|
+
|
|
2018
|
+
/***/ 548:
|
|
2019
|
+
/***/ ((module) => {
|
|
2020
|
+
|
|
2021
|
+
// =============================================================================
|
|
2022
|
+
// Skill Packs (Bundled Skills)
|
|
2023
|
+
// =============================================================================
|
|
2024
|
+
|
|
2025
|
+
const SKILL_PACKS = {
|
|
2026
|
+
frontend: {
|
|
2027
|
+
name: 'Frontend Pack',
|
|
2028
|
+
description: 'UI development skills',
|
|
2029
|
+
skills: [
|
|
2030
|
+
'frontend-development',
|
|
2031
|
+
'frontend-design',
|
|
2032
|
+
'ui-styling',
|
|
2033
|
+
'aesthetic',
|
|
2034
|
+
],
|
|
2035
|
+
},
|
|
2036
|
+
|
|
2037
|
+
backend: {
|
|
2038
|
+
name: 'Backend Pack',
|
|
2039
|
+
description: 'Server & database skills',
|
|
2040
|
+
skills: [
|
|
2041
|
+
'backend-development',
|
|
2042
|
+
'databases',
|
|
2043
|
+
'better-auth',
|
|
2044
|
+
],
|
|
2045
|
+
},
|
|
2046
|
+
|
|
2047
|
+
fullstack: {
|
|
2048
|
+
name: 'Fullstack Pack',
|
|
2049
|
+
description: 'Frontend + Backend combined',
|
|
2050
|
+
skills: [
|
|
2051
|
+
'frontend-development',
|
|
2052
|
+
'frontend-design',
|
|
2053
|
+
'ui-styling',
|
|
2054
|
+
'backend-development',
|
|
2055
|
+
'databases',
|
|
2056
|
+
'better-auth',
|
|
2057
|
+
'web-frameworks',
|
|
2058
|
+
],
|
|
2059
|
+
},
|
|
2060
|
+
|
|
2061
|
+
ddd: {
|
|
2062
|
+
name: 'DDD Pack',
|
|
2063
|
+
description: 'Domain-Driven Design skills',
|
|
2064
|
+
skills: [
|
|
2065
|
+
'ddd-modular-monolith',
|
|
2066
|
+
'planning',
|
|
2067
|
+
'debugging',
|
|
2068
|
+
],
|
|
2069
|
+
},
|
|
2070
|
+
|
|
2071
|
+
devops: {
|
|
2072
|
+
name: 'DevOps Pack',
|
|
2073
|
+
description: 'CI/CD & infrastructure',
|
|
2074
|
+
skills: [
|
|
2075
|
+
'devops',
|
|
2076
|
+
'debugging',
|
|
2077
|
+
],
|
|
2078
|
+
},
|
|
2079
|
+
|
|
2080
|
+
ai: {
|
|
2081
|
+
name: 'AI Tools Pack',
|
|
2082
|
+
description: 'AI integration skills',
|
|
2083
|
+
skills: [
|
|
2084
|
+
'ai-multimodal',
|
|
2085
|
+
'mcp-builder',
|
|
2086
|
+
'mcp-management',
|
|
2087
|
+
],
|
|
2088
|
+
},
|
|
2089
|
+
|
|
2090
|
+
mobile: {
|
|
2091
|
+
name: 'Mobile Pack',
|
|
2092
|
+
description: 'Mobile development',
|
|
2093
|
+
skills: [
|
|
2094
|
+
'mobile-development',
|
|
2095
|
+
'frontend-development',
|
|
2096
|
+
],
|
|
2097
|
+
},
|
|
2098
|
+
};
|
|
2099
|
+
|
|
2100
|
+
function getSkillPack(name) {
|
|
2101
|
+
return SKILL_PACKS[name] || null;
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
function getSkillPackList() {
|
|
2105
|
+
return Object.entries(SKILL_PACKS).map(([key, pack]) => ({
|
|
2106
|
+
key,
|
|
2107
|
+
name: pack.name,
|
|
2108
|
+
description: pack.description,
|
|
2109
|
+
skillCount: pack.skills.length,
|
|
2110
|
+
}));
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
function resolveSkillPacks(packKeys) {
|
|
2114
|
+
const skills = new Set();
|
|
2115
|
+
for (const key of packKeys) {
|
|
2116
|
+
const pack = SKILL_PACKS[key];
|
|
2117
|
+
if (pack) {
|
|
2118
|
+
pack.skills.forEach(s => skills.add(s));
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
return Array.from(skills);
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
module.exports = {
|
|
2125
|
+
SKILL_PACKS,
|
|
2126
|
+
getSkillPack,
|
|
2127
|
+
getSkillPackList,
|
|
2128
|
+
resolveSkillPacks,
|
|
2129
|
+
};
|
|
2130
|
+
|
|
2131
|
+
|
|
2132
|
+
/***/ }),
|
|
2133
|
+
|
|
2134
|
+
/***/ 896:
|
|
2135
|
+
/***/ ((module) => {
|
|
2136
|
+
|
|
2137
|
+
"use strict";
|
|
2138
|
+
module.exports = require("fs");
|
|
2139
|
+
|
|
2140
|
+
/***/ }),
|
|
2141
|
+
|
|
2142
|
+
/***/ 692:
|
|
2143
|
+
/***/ ((module) => {
|
|
2144
|
+
|
|
2145
|
+
"use strict";
|
|
2146
|
+
module.exports = require("https");
|
|
2147
|
+
|
|
2148
|
+
/***/ }),
|
|
2149
|
+
|
|
2150
|
+
/***/ 928:
|
|
2151
|
+
/***/ ((module) => {
|
|
2152
|
+
|
|
2153
|
+
"use strict";
|
|
2154
|
+
module.exports = require("path");
|
|
2155
|
+
|
|
2156
|
+
/***/ }),
|
|
2157
|
+
|
|
2158
|
+
/***/ 785:
|
|
2159
|
+
/***/ ((module) => {
|
|
2160
|
+
|
|
2161
|
+
"use strict";
|
|
2162
|
+
module.exports = require("readline");
|
|
2163
|
+
|
|
2164
|
+
/***/ })
|
|
2165
|
+
|
|
2166
|
+
/******/ });
|
|
2167
|
+
/************************************************************************/
|
|
2168
|
+
/******/ // The module cache
|
|
2169
|
+
/******/ var __webpack_module_cache__ = {};
|
|
2170
|
+
/******/
|
|
2171
|
+
/******/ // The require function
|
|
2172
|
+
/******/ function __nccwpck_require__(moduleId) {
|
|
2173
|
+
/******/ // Check if module is in cache
|
|
2174
|
+
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
2175
|
+
/******/ if (cachedModule !== undefined) {
|
|
2176
|
+
/******/ return cachedModule.exports;
|
|
2177
|
+
/******/ }
|
|
2178
|
+
/******/ // Create a new module (and put it into the cache)
|
|
2179
|
+
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
2180
|
+
/******/ // no module.id needed
|
|
2181
|
+
/******/ // no module.loaded needed
|
|
2182
|
+
/******/ exports: {}
|
|
2183
|
+
/******/ };
|
|
2184
|
+
/******/
|
|
2185
|
+
/******/ // Execute the module function
|
|
2186
|
+
/******/ var threw = true;
|
|
2187
|
+
/******/ try {
|
|
2188
|
+
/******/ __webpack_modules__[moduleId](module, module.exports, __nccwpck_require__);
|
|
2189
|
+
/******/ threw = false;
|
|
2190
|
+
/******/ } finally {
|
|
2191
|
+
/******/ if(threw) delete __webpack_module_cache__[moduleId];
|
|
2192
|
+
/******/ }
|
|
2193
|
+
/******/
|
|
2194
|
+
/******/ // Return the exports of the module
|
|
2195
|
+
/******/ return module.exports;
|
|
2196
|
+
/******/ }
|
|
2197
|
+
/******/
|
|
2198
|
+
/************************************************************************/
|
|
2199
|
+
/******/ /* webpack/runtime/compat */
|
|
2200
|
+
/******/
|
|
2201
|
+
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";
|
|
2202
|
+
/******/
|
|
2203
|
+
/************************************************************************/
|
|
2204
|
+
var __webpack_exports__ = {};
|
|
2205
|
+
|
|
2206
|
+
// =============================================================================
|
|
2207
|
+
// anchi-toolkit CLI
|
|
2208
|
+
// Usage: npx anchi-toolkit install
|
|
2209
|
+
// =============================================================================
|
|
2210
|
+
|
|
2211
|
+
const fs = __nccwpck_require__(896);
|
|
2212
|
+
const path = __nccwpck_require__(928);
|
|
2213
|
+
const readline = __nccwpck_require__(785);
|
|
2214
|
+
|
|
2215
|
+
// =============================================================================
|
|
2216
|
+
// COLORS
|
|
2217
|
+
// =============================================================================
|
|
2218
|
+
const colors = {
|
|
2219
|
+
reset: '\x1b[0m',
|
|
2220
|
+
red: '\x1b[31m',
|
|
2221
|
+
green: '\x1b[32m',
|
|
2222
|
+
yellow: '\x1b[33m',
|
|
2223
|
+
cyan: '\x1b[36m',
|
|
2224
|
+
gray: '\x1b[90m',
|
|
2225
|
+
};
|
|
2226
|
+
|
|
2227
|
+
const log = {
|
|
2228
|
+
info: (msg) => console.log(`${colors.cyan}${msg}${colors.reset}`),
|
|
2229
|
+
success: (msg) => console.log(`${colors.green}${msg}${colors.reset}`),
|
|
2230
|
+
warn: (msg) => console.log(`${colors.yellow}${msg}${colors.reset}`),
|
|
2231
|
+
error: (msg) => console.log(`${colors.red}${msg}${colors.reset}`),
|
|
2232
|
+
gray: (msg) => console.log(`${colors.gray}${msg}${colors.reset}`),
|
|
2233
|
+
};
|
|
2234
|
+
|
|
2235
|
+
// =============================================================================
|
|
2236
|
+
// HELPERS
|
|
2237
|
+
// =============================================================================
|
|
2238
|
+
|
|
2239
|
+
const rl = readline.createInterface({
|
|
2240
|
+
input: process.stdin,
|
|
2241
|
+
output: process.stdout,
|
|
2242
|
+
});
|
|
2243
|
+
|
|
2244
|
+
function ask(question) {
|
|
2245
|
+
return new Promise((resolve) => {
|
|
2246
|
+
rl.question(question, (answer) => {
|
|
2247
|
+
resolve(answer);
|
|
2248
|
+
});
|
|
2249
|
+
});
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
function writeBanner() {
|
|
2253
|
+
console.log('');
|
|
2254
|
+
log.info('╔═══════════════════════════════════════════════════════════╗');
|
|
2255
|
+
log.info('║ 🚀 anchi-toolkit for Cursor AI ║');
|
|
2256
|
+
log.info('║ Cài đặt Cursor AI toolkit vào dự án có sẵn ║');
|
|
2257
|
+
log.info('╚═══════════════════════════════════════════════════════════╝');
|
|
2258
|
+
console.log('');
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
async function askConflictResolution(filePath, isForce = false) {
|
|
2262
|
+
// Force mode: auto-overwrite
|
|
2263
|
+
if (isForce) {
|
|
2264
|
+
log.gray(` 🔄 Force mode: auto-overwrite ${filePath}`);
|
|
2265
|
+
return 'O';
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
console.log('');
|
|
2269
|
+
log.warn(`⚠️ File đã tồn tại: ${filePath}`);
|
|
2270
|
+
console.log(' [O] Overwrite - Ghi đè (backup file cũ)');
|
|
2271
|
+
console.log(' [S] Skip - Bỏ qua, giữ file hiện tại');
|
|
2272
|
+
console.log(' [M] Merge - Tạo file .new để merge thủ công');
|
|
2273
|
+
console.log('');
|
|
2274
|
+
|
|
2275
|
+
while (true) {
|
|
2276
|
+
const choice = (await ask(' Chọn (O/S/M): ')).toUpperCase();
|
|
2277
|
+
if (['O', 'S', 'M'].includes(choice)) {
|
|
2278
|
+
return choice;
|
|
2279
|
+
}
|
|
2280
|
+
console.log(' Vui lòng chọn O, S, hoặc M');
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
function backupFile(filePath) {
|
|
2285
|
+
const timestamp = new Date().toISOString().replace(/[-:]/g, '').replace('T', '_').slice(0, 15);
|
|
2286
|
+
const backupPath = `${filePath}.backup_${timestamp}`;
|
|
2287
|
+
fs.copyFileSync(filePath, backupPath);
|
|
2288
|
+
log.gray(` 📦 Backup: ${backupPath}`);
|
|
2289
|
+
return backupPath;
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
function copyDirRecursive(src, dest) {
|
|
2293
|
+
if (!fs.existsSync(dest)) {
|
|
2294
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
2298
|
+
|
|
2299
|
+
for (const entry of entries) {
|
|
2300
|
+
const srcPath = path.join(src, entry.name);
|
|
2301
|
+
const destPath = path.join(dest, entry.name);
|
|
2302
|
+
|
|
2303
|
+
if (entry.isDirectory()) {
|
|
2304
|
+
copyDirRecursive(srcPath, destPath);
|
|
2305
|
+
} else {
|
|
2306
|
+
fs.copyFileSync(srcPath, destPath);
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
async function copyWithConflictHandling(source, destination, isDirectory, isForce = false) {
|
|
2312
|
+
if (isDirectory) {
|
|
2313
|
+
if (fs.existsSync(destination)) {
|
|
2314
|
+
// Directory exists - copy contents with per-file handling
|
|
2315
|
+
const files = getAllFiles(source);
|
|
2316
|
+
for (const srcFile of files) {
|
|
2317
|
+
const relativePath = path.relative(source, srcFile);
|
|
2318
|
+
const destFile = path.join(destination, relativePath);
|
|
2319
|
+
const destDir = path.dirname(destFile);
|
|
2320
|
+
|
|
2321
|
+
if (!fs.existsSync(destDir)) {
|
|
2322
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
if (fs.existsSync(destFile)) {
|
|
2326
|
+
const choice = await askConflictResolution(relativePath, isForce);
|
|
2327
|
+
switch (choice) {
|
|
2328
|
+
case 'O':
|
|
2329
|
+
backupFile(destFile);
|
|
2330
|
+
fs.copyFileSync(srcFile, destFile);
|
|
2331
|
+
log.success(` ✅ Overwrote: ${relativePath}`);
|
|
2332
|
+
break;
|
|
2333
|
+
case 'S':
|
|
2334
|
+
log.gray(` ⏭️ Skipped: ${relativePath}`);
|
|
2335
|
+
break;
|
|
2336
|
+
case 'M':
|
|
2337
|
+
fs.copyFileSync(srcFile, `${destFile}.new`);
|
|
2338
|
+
log.warn(` 📝 Merge manually: ${relativePath} vs ${relativePath}.new`);
|
|
2339
|
+
break;
|
|
2340
|
+
}
|
|
2341
|
+
} else {
|
|
2342
|
+
fs.copyFileSync(srcFile, destFile);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
} else {
|
|
2346
|
+
copyDirRecursive(source, destination);
|
|
2347
|
+
log.success(` ✅ Copied: ${path.basename(source)}/`);
|
|
2348
|
+
}
|
|
2349
|
+
} else {
|
|
2350
|
+
if (fs.existsSync(destination)) {
|
|
2351
|
+
const choice = await askConflictResolution(path.basename(destination), isForce);
|
|
2352
|
+
switch (choice) {
|
|
2353
|
+
case 'O':
|
|
2354
|
+
backupFile(destination);
|
|
2355
|
+
fs.copyFileSync(source, destination);
|
|
2356
|
+
log.success(` ✅ Overwrote: ${path.basename(destination)}`);
|
|
2357
|
+
break;
|
|
2358
|
+
case 'S':
|
|
2359
|
+
log.gray(` ⏭️ Skipped: ${path.basename(destination)}`);
|
|
2360
|
+
break;
|
|
2361
|
+
case 'M':
|
|
2362
|
+
fs.copyFileSync(source, `${destination}.new`);
|
|
2363
|
+
log.warn(` 📝 Merge manually: ${path.basename(destination)} vs ${path.basename(destination)}.new`);
|
|
2364
|
+
break;
|
|
2365
|
+
}
|
|
2366
|
+
} else {
|
|
2367
|
+
fs.copyFileSync(source, destination);
|
|
2368
|
+
log.success(` ✅ Copied: ${path.basename(destination)}`);
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
function getAllFiles(dir, files = []) {
|
|
2374
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
2375
|
+
for (const entry of entries) {
|
|
2376
|
+
const fullPath = path.join(dir, entry.name);
|
|
2377
|
+
if (entry.isDirectory()) {
|
|
2378
|
+
getAllFiles(fullPath, files);
|
|
2379
|
+
} else {
|
|
2380
|
+
files.push(fullPath);
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
return files;
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
// =============================================================================
|
|
2387
|
+
// ANTIGRAVITY INSTALL
|
|
2388
|
+
// =============================================================================
|
|
2389
|
+
|
|
2390
|
+
async function installAntigravity(isForce = false) {
|
|
2391
|
+
console.log('');
|
|
2392
|
+
log.info('╔═══════════════════════════════════════════════════════════╗');
|
|
2393
|
+
log.info('║ 🌌 anchi-toolkit for Antigravity (Gemini) ║');
|
|
2394
|
+
log.info('║ All-in-One Installation ║');
|
|
2395
|
+
log.info('╚═══════════════════════════════════════════════════════════╝');
|
|
2396
|
+
console.log('');
|
|
2397
|
+
|
|
2398
|
+
const targetPath = process.cwd();
|
|
2399
|
+
const kitPath = path.resolve(__dirname, '..');
|
|
2400
|
+
|
|
2401
|
+
log.gray(`📁 Kit source: ${kitPath}`);
|
|
2402
|
+
log.gray(`📂 Target: ${targetPath}`);
|
|
2403
|
+
console.log('');
|
|
2404
|
+
|
|
2405
|
+
// Show what will be installed - ALL into .antigravity/
|
|
2406
|
+
log.warn('📦 Installing:');
|
|
2407
|
+
console.log(' ├── .antigravity/ 19 commands, 19 agents, 35 skills');
|
|
2408
|
+
console.log(' ├── .ai-audit/ Decision logging');
|
|
2409
|
+
console.log(' ├── .ai-memory/ Context storage');
|
|
2410
|
+
console.log(' └── presets/docs Architecture & docs');
|
|
2411
|
+
console.log('');
|
|
2412
|
+
|
|
2413
|
+
if (!isForce) {
|
|
2414
|
+
const confirm = await ask('Tiếp tục cài đặt? (Y/n): ');
|
|
2415
|
+
if (confirm.toLowerCase() === 'n') {
|
|
2416
|
+
log.error('❌ Đã hủy.');
|
|
2417
|
+
rl.close();
|
|
2418
|
+
process.exit(0);
|
|
2419
|
+
}
|
|
2420
|
+
} else {
|
|
2421
|
+
log.info('🚀 Force mode: skipping confirmation...');
|
|
2422
|
+
}
|
|
2423
|
+
|
|
2424
|
+
console.log('');
|
|
2425
|
+
log.warn('📋 Installing anchi-toolkit for Antigravity...');
|
|
2426
|
+
console.log('');
|
|
2427
|
+
|
|
2428
|
+
const antigravityDest = __nccwpck_require__.ab + ".antigravity";
|
|
2429
|
+
|
|
2430
|
+
// Ensure .antigravity folder exists
|
|
2431
|
+
if (!fs.existsSync(__nccwpck_require__.ab + ".antigravity")) {
|
|
2432
|
+
fs.mkdirSync(__nccwpck_require__.ab + ".antigravity", { recursive: true });
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
// 1. Copy .antigravity folder (workflows, agents, skills)
|
|
2436
|
+
const agentSource = __nccwpck_require__.ab + ".antigravity";
|
|
2437
|
+
if (fs.existsSync(__nccwpck_require__.ab + ".antigravity")) {
|
|
2438
|
+
await copyWithConflictHandling(agentSource, antigravityDest, true, isForce);
|
|
2439
|
+
log.success(' ✅ workflows/ - 18 commands');
|
|
2440
|
+
log.success(' ✅ agents/ - 19 agents');
|
|
2441
|
+
log.success(' ✅ skills/ - 35 skills');
|
|
2442
|
+
} else {
|
|
2443
|
+
log.error(` ❌ .antigravity folder not found at: ${agentSource}`);
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
// 2. Copy presets INTO .antigravity/presets/
|
|
2447
|
+
const presetsSource = __nccwpck_require__.ab + "presets";
|
|
2448
|
+
const presetsDest = path.join(antigravityDest, 'presets');
|
|
2449
|
+
if (fs.existsSync(__nccwpck_require__.ab + "presets")) {
|
|
2450
|
+
await copyWithConflictHandling(presetsSource, presetsDest, true, isForce);
|
|
2451
|
+
log.success(' ✅ presets/ - 3 architecture presets');
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2454
|
+
// 3. Copy docs INTO .antigravity/docs/
|
|
2455
|
+
const docsSource = __nccwpck_require__.ab + "docs";
|
|
2456
|
+
const docsDest = path.join(antigravityDest, 'docs');
|
|
2457
|
+
if (fs.existsSync(__nccwpck_require__.ab + "docs")) {
|
|
2458
|
+
await copyWithConflictHandling(docsSource, docsDest, true, isForce);
|
|
2459
|
+
log.success(' ✅ docs/ - Documentation');
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
// 4. Copy config files from .cursor to .antigravity
|
|
2463
|
+
const configFiles = [
|
|
2464
|
+
'orchestration.yaml',
|
|
2465
|
+
'failure-modes.yaml',
|
|
2466
|
+
'agent-skill-index.yaml',
|
|
2467
|
+
'team.yaml',
|
|
2468
|
+
'anchi-toolkit.config.yaml'
|
|
2469
|
+
];
|
|
2470
|
+
|
|
2471
|
+
for (const configFile of configFiles) {
|
|
2472
|
+
// First check if exists in .antigravity source
|
|
2473
|
+
let configSource = __nccwpck_require__.ab + ".antigravity/" + configFile;
|
|
2474
|
+
if (!fs.existsSync(configSource)) {
|
|
2475
|
+
// Fallback to .cursor
|
|
2476
|
+
configSource = __nccwpck_require__.ab + ".cursor/" + configFile;
|
|
2477
|
+
}
|
|
2478
|
+
const configDest = __nccwpck_require__.ab + ".antigravity/" + configFile;
|
|
2479
|
+
if (fs.existsSync(configSource) && !fs.existsSync(configDest)) {
|
|
2480
|
+
fs.copyFileSync(configSource, configDest);
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
// 5. Create .ai-audit folder (for logging)
|
|
2484
|
+
const auditSource = path.join(kitPath, '.ai-audit');
|
|
2485
|
+
const auditDest = path.join(antigravityDest, '.ai-audit'); // Inside .antigravity
|
|
2486
|
+
if (fs.existsSync(auditSource)) {
|
|
2487
|
+
await copyWithConflictHandling(auditSource, auditDest, true, isForce);
|
|
2488
|
+
log.success(' ✅ .ai-audit/ - Decision logs');
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
// 6. Create .ai-memory folder (for context)
|
|
2492
|
+
const memorySource = __nccwpck_require__.ab + ".ai-memory";
|
|
2493
|
+
const memoryDest = path.join(antigravityDest, '.ai-memory'); // Inside .antigravity
|
|
2494
|
+
if (fs.existsSync(__nccwpck_require__.ab + ".ai-memory")) {
|
|
2495
|
+
await copyWithConflictHandling(memorySource, memoryDest, true, isForce);
|
|
2496
|
+
log.success(' ✅ .ai-memory/ - Context storage');
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
// 7. Create scripts folder (for setup)
|
|
2500
|
+
const scriptsSource = __nccwpck_require__.ab + "scripts";
|
|
2501
|
+
const scriptsDest = path.join(antigravityDest, 'scripts');
|
|
2502
|
+
if (fs.existsSync(__nccwpck_require__.ab + "scripts")) {
|
|
2503
|
+
await copyWithConflictHandling(scriptsSource, scriptsDest, true, isForce);
|
|
2504
|
+
log.success(' ✅ scripts/ - Setup tools');
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
// 8. Copy ANTIGRAVITY.md to root (entry point doc)
|
|
2508
|
+
const antigravityMdPath = __nccwpck_require__.ab + "ANTIGRAVITY.md";
|
|
2509
|
+
if (fs.existsSync(__nccwpck_require__.ab + "ANTIGRAVITY.md")) {
|
|
2510
|
+
fs.copyFileSync(antigravityMdPath, path.join(targetPath, 'ANTIGRAVITY.md'));
|
|
2511
|
+
log.success(' ✅ ANTIGRAVITY.md (root)');
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2514
|
+
// =====================================================================
|
|
2515
|
+
// SUCCESS MESSAGE - Clear Next Steps
|
|
2516
|
+
// =====================================================================
|
|
2517
|
+
console.log('');
|
|
2518
|
+
console.log('');
|
|
2519
|
+
log.success('╔═══════════════════════════════════════════════════════════╗');
|
|
2520
|
+
log.success('║ ✅ INSTALLATION COMPLETE! ║');
|
|
2521
|
+
log.success('╚═══════════════════════════════════════════════════════════╝');
|
|
2522
|
+
console.log('');
|
|
2523
|
+
log.info('📂 Installed to: .antigravity/');
|
|
2524
|
+
console.log('');
|
|
2525
|
+
console.log('╭───────────────────────────────────────────────────────────╮');
|
|
2526
|
+
console.log('│ │');
|
|
2527
|
+
log.success('│ 🚀 START NOW: Open Antigravity Chat and type: │');
|
|
2528
|
+
console.log('│ │');
|
|
2529
|
+
log.warn('│ /start │');
|
|
2530
|
+
console.log('│ │');
|
|
2531
|
+
console.log('╰───────────────────────────────────────────────────────────╯');
|
|
2532
|
+
console.log('');
|
|
2533
|
+
log.gray('Other commands: /do, /commit, /test, /help');
|
|
2534
|
+
console.log('');
|
|
2535
|
+
|
|
2536
|
+
rl.close();
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
|
|
2540
|
+
// =============================================================================
|
|
2541
|
+
// MAIN
|
|
2542
|
+
// =============================================================================
|
|
2543
|
+
|
|
2544
|
+
async function install(isForce = false) {
|
|
2545
|
+
writeBanner();
|
|
2546
|
+
|
|
2547
|
+
const targetPath = process.cwd();
|
|
2548
|
+
const kitPath = path.resolve(__dirname, '..');
|
|
2549
|
+
|
|
2550
|
+
log.gray(`📁 Kit source: ${kitPath}`);
|
|
2551
|
+
log.gray(`📂 Target: ${targetPath}`);
|
|
2552
|
+
console.log('');
|
|
2553
|
+
|
|
2554
|
+
if (!isForce) {
|
|
2555
|
+
const confirm = await ask('Tiếp tục cài đặt? (Y/n): ');
|
|
2556
|
+
if (confirm.toLowerCase() === 'n') {
|
|
2557
|
+
log.error('❌ Đã hủy.');
|
|
2558
|
+
rl.close();
|
|
2559
|
+
process.exit(0);
|
|
2560
|
+
}
|
|
2561
|
+
} else {
|
|
2562
|
+
log.info('🚀 Force mode: skipping confirmation...');
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
console.log('');
|
|
2566
|
+
log.warn('📋 Installing anchi-toolkit components...');
|
|
2567
|
+
console.log('');
|
|
2568
|
+
|
|
2569
|
+
// Components to install (Cursor AI specific)
|
|
2570
|
+
const cursorDest = __nccwpck_require__.ab + ".cursor";
|
|
2571
|
+
if (!fs.existsSync(__nccwpck_require__.ab + ".cursor")) fs.mkdirSync(__nccwpck_require__.ab + ".cursor", { recursive: true });
|
|
2572
|
+
|
|
2573
|
+
const components = [
|
|
2574
|
+
// Folders go INSIDE .cursor/
|
|
2575
|
+
{ source: '.cursor', dest: '.cursor', isDir: true, desc: 'Cursor commands, agents, skills' },
|
|
2576
|
+
{ source: 'presets', dest: '.cursor/presets', isDir: true, desc: 'Architecture presets' },
|
|
2577
|
+
{ source: 'docs', dest: '.cursor/docs', isDir: true, desc: 'Documentation templates' },
|
|
2578
|
+
{ source: 'scripts', dest: '.cursor/scripts', isDir: true, desc: 'Setup scripts' },
|
|
2579
|
+
{ source: '.ai-audit', dest: '.cursor/.ai-audit', isDir: true, desc: 'AI decision logs' },
|
|
2580
|
+
{ source: '.ai-memory', dest: '.cursor/.ai-memory', isDir: true, desc: 'Context storage' },
|
|
2581
|
+
|
|
2582
|
+
// Root files (Required for IDE)
|
|
2583
|
+
{ source: '.cursorrules', dest: '.cursorrules', isDir: false, desc: 'Cursor rules (Root)' },
|
|
2584
|
+
{ source: 'CURSOR.md', dest: 'CURSOR.md', isDir: false, desc: 'AI instructions (Root)' },
|
|
2585
|
+
];
|
|
2586
|
+
|
|
2587
|
+
for (const comp of components) {
|
|
2588
|
+
const sourcePath = path.join(kitPath, comp.source);
|
|
2589
|
+
const destPath = path.join(targetPath, comp.dest);
|
|
2590
|
+
|
|
2591
|
+
if (fs.existsSync(sourcePath)) {
|
|
2592
|
+
log.info(` 📦 ${comp.desc}...`);
|
|
2593
|
+
await copyWithConflictHandling(sourcePath, destPath, comp.isDir, isForce);
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
console.log('');
|
|
2598
|
+
log.info('═══════════════════════════════════════════════════════════════');
|
|
2599
|
+
log.success(' ✅ anchi-toolkit đã được cài đặt thành công!');
|
|
2600
|
+
log.info('═══════════════════════════════════════════════════════════════');
|
|
2601
|
+
console.log('');
|
|
2602
|
+
log.warn('📌 Bước tiếp theo:');
|
|
2603
|
+
console.log('');
|
|
2604
|
+
console.log(' 1. Mở Cursor IDE và chạy:');
|
|
2605
|
+
log.success(' /start');
|
|
2606
|
+
console.log('');
|
|
2607
|
+
console.log(' 2. Chọn preset phù hợp:');
|
|
2608
|
+
log.success(' /use-preset rapid|professional|enterprise');
|
|
2609
|
+
console.log('');
|
|
2610
|
+
console.log(' 3. Bắt đầu code:');
|
|
2611
|
+
log.success(' /plan "Feature description"');
|
|
2612
|
+
console.log('');
|
|
2613
|
+
|
|
2614
|
+
rl.close();
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
// Command handler
|
|
2618
|
+
const args = process.argv.slice(2);
|
|
2619
|
+
const flags = args.filter(a => a.startsWith('-'));
|
|
2620
|
+
const commands = args.filter(a => !a.startsWith('-'));
|
|
2621
|
+
const command = commands[0];
|
|
2622
|
+
const isForce = flags.includes('-y') || flags.includes('--force');
|
|
2623
|
+
|
|
2624
|
+
async function main() {
|
|
2625
|
+
switch (command) {
|
|
2626
|
+
case 'install':
|
|
2627
|
+
await install(isForce);
|
|
2628
|
+
break;
|
|
2629
|
+
|
|
2630
|
+
case 'init':
|
|
2631
|
+
const { init } = __nccwpck_require__(816);
|
|
2632
|
+
await init();
|
|
2633
|
+
break;
|
|
2634
|
+
|
|
2635
|
+
case 'update':
|
|
2636
|
+
const { update } = __nccwpck_require__(779);
|
|
2637
|
+
await update();
|
|
2638
|
+
break;
|
|
2639
|
+
|
|
2640
|
+
case 'uninstall':
|
|
2641
|
+
const { uninstall } = __nccwpck_require__(66);
|
|
2642
|
+
await uninstall();
|
|
2643
|
+
break;
|
|
2644
|
+
|
|
2645
|
+
case 'doctor':
|
|
2646
|
+
const { doctor } = __nccwpck_require__(181);
|
|
2647
|
+
await doctor();
|
|
2648
|
+
break;
|
|
2649
|
+
|
|
2650
|
+
case 'memory':
|
|
2651
|
+
const { memory } = __nccwpck_require__(697);
|
|
2652
|
+
await memory(args[1], args[2]);
|
|
2653
|
+
break;
|
|
2654
|
+
|
|
2655
|
+
case 'antigravity':
|
|
2656
|
+
await installAntigravity(isForce);
|
|
2657
|
+
break;
|
|
2658
|
+
|
|
2659
|
+
case 'clean':
|
|
2660
|
+
const { clean } = __nccwpck_require__(1);
|
|
2661
|
+
await clean(process.cwd(), {
|
|
2662
|
+
all: flags.includes('--all'),
|
|
2663
|
+
memory: flags.includes('--memory'),
|
|
2664
|
+
audit: flags.includes('--audit'),
|
|
2665
|
+
force: isForce
|
|
2666
|
+
});
|
|
2667
|
+
break;
|
|
2668
|
+
|
|
2669
|
+
default:
|
|
2670
|
+
showHelp();
|
|
2671
|
+
break;
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2675
|
+
function showHelp() {
|
|
2676
|
+
console.log('');
|
|
2677
|
+
log.info('🚀 anchi-toolkit - Cursor AI & Antigravity Toolkit');
|
|
2678
|
+
console.log('');
|
|
2679
|
+
console.log('Commands:');
|
|
2680
|
+
log.success(' npx anchi-toolkit install Cài đặt cho Cursor AI');
|
|
2681
|
+
log.success(' npx anchi-toolkit antigravity Cài đặt cho Antigravity (Gemini)');
|
|
2682
|
+
log.success(' npx anchi-toolkit init Cài đặt thông minh (chọn profile)');
|
|
2683
|
+
log.success(' npx anchi-toolkit update Kiểm tra cập nhật');
|
|
2684
|
+
log.success(' npx anchi-toolkit uninstall Gỡ cài đặt');
|
|
2685
|
+
log.success(' npx anchi-toolkit doctor Kiểm tra setup health');
|
|
2686
|
+
log.success(' npx anchi-toolkit memory Quản lý project context');
|
|
2687
|
+
log.success(' npx anchi-toolkit clean Dọn dẹp context/logs');
|
|
2688
|
+
console.log('');
|
|
2689
|
+
console.log('Flags:');
|
|
2690
|
+
log.success(' -y, --force Bỏ qua tất cả prompts (auto-overwrite)');
|
|
2691
|
+
console.log('');
|
|
2692
|
+
console.log('Examples:');
|
|
2693
|
+
log.gray(' npx anchi-toolkit install -y # Non-interactive install');
|
|
2694
|
+
log.gray(' npx anchi-toolkit antigravity -y # Non-interactive Antigravity install');
|
|
2695
|
+
console.log('');
|
|
2696
|
+
console.log('Documentation:');
|
|
2697
|
+
console.log(' https://github.com/ANCHI-STE/anchi-webkit-dev');
|
|
2698
|
+
console.log('');
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
main().catch((err) => {
|
|
2702
|
+
log.error(`❌ Error: ${err.message}`);
|
|
2703
|
+
rl.close();
|
|
2704
|
+
process.exit(1);
|
|
2705
|
+
});
|
|
2706
|
+
|
|
2707
|
+
module.exports = __webpack_exports__;
|
|
2708
|
+
/******/ })()
|
|
2709
|
+
;
|