anchi-toolkit 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ai-audit/README.md +53 -0
- package/.ai-memory/README.md +137 -0
- package/.ai-memory/context.json +26 -0
- package/.ai-memory/decisions.json +3 -0
- package/.antigravity/agent-skill-index.yaml +24 -0
- package/.antigravity/anchi-toolkit.config.yaml +12 -0
- package/.antigravity/docs/README.md +9 -0
- package/.antigravity/skills/_template.md +30 -0
- package/.antigravity/team.yaml +154 -0
- package/.antigravity/workflows/config.md +144 -0
- package/.antigravity/workflows/demo.md +50 -0
- package/.antigravity/workflows/help.md +11 -4
- package/.antigravity/workflows/skill-learn.md +48 -0
- package/.antigravity/workflows/start.md +38 -117
- package/.antigravity/workflows/status.md +8 -8
- package/.antigravity/workflows/undo.md +7 -7
- package/.cursor/agent-skill-index.yaml +39 -0
- package/.cursor/agents/graph-architect.md +30 -0
- package/.cursor/agents/trend-watcher.md +24 -0
- package/.cursor/commands/config.md +144 -0
- package/.cursor/commands/demo.md +50 -0
- package/.cursor/commands/do.md +127 -90
- package/.cursor/commands/help.md +23 -16
- package/.cursor/commands/skill-learn.md +48 -0
- package/.cursor/commands/start.md +38 -117
- package/.cursor/commands/status.md +19 -19
- package/.cursor/commands/undo.md +19 -19
- package/.cursor/orchestration.yaml +18 -0
- package/.cursor/skills/_template.md +30 -0
- package/ANTIGRAVITY.md +84 -0
- package/CURSOR.md +50 -157
- package/LICENSE +17 -14
- package/README.md +64 -89
- package/docs/ALL_COMMANDS.md +31 -73
- package/docs/CI_CD.md +44 -0
- package/docs/COMPARISON.md +65 -0
- package/docs/ROADMAP.md +45 -161
- package/docs/WORKFLOW.md +56 -317
- package/package.json +9 -2
- package/presets/ci-cd/ai-review.yml +49 -0
- package/scripts/install-hooks.ps1 +21 -7
- package/scripts/install-hooks.sh +18 -3
- package/src/cli.js +111 -59
- package/src/commands/clean.js +87 -0
- package/src/commands/doctor.js +88 -21
- package/src/commands/init.js +22 -2
- package/src/commands/uninstall.js +17 -2
- package/src/lib/configManager.js +20 -5
- package/src/lib/memoryManager.js +7 -4
- package/docs/CODEBASE.md +0 -178
- package/docs/COMMAND_MAPPING.md +0 -217
- package/docs/FAQ.md +0 -174
- package/docs/ONBOARDING.md +0 -111
- package/docs/ORCHESTRATION_RUNTIME.md +0 -173
- package/docs/WALKTHROUGH.md +0 -192
- /package/.cursor/{anchi-kit.config.yaml → anchi-toolkit.config.yaml} +0 -0
package/src/cli.js
CHANGED
|
@@ -186,8 +186,8 @@ function getAllFiles(dir, files = []) {
|
|
|
186
186
|
async function installAntigravity(isForce = false) {
|
|
187
187
|
console.log('');
|
|
188
188
|
log.info('╔═══════════════════════════════════════════════════════════╗');
|
|
189
|
-
log.info('║ 🌌 anchi-toolkit for Antigravity (Gemini)
|
|
190
|
-
log.info('║
|
|
189
|
+
log.info('║ 🌌 anchi-toolkit for Antigravity (Gemini) ║');
|
|
190
|
+
log.info('║ All-in-One Installation ║');
|
|
191
191
|
log.info('╚═══════════════════════════════════════════════════════════╝');
|
|
192
192
|
console.log('');
|
|
193
193
|
|
|
@@ -198,19 +198,16 @@ async function installAntigravity(isForce = false) {
|
|
|
198
198
|
log.gray(`📂 Target: ${targetPath}`);
|
|
199
199
|
console.log('');
|
|
200
200
|
|
|
201
|
-
// Show what will be installed
|
|
202
|
-
log.warn('📦
|
|
203
|
-
console.log(' ├── .antigravity/
|
|
204
|
-
console.log(' ├── .
|
|
205
|
-
console.log(' ├── .
|
|
206
|
-
console.log('
|
|
207
|
-
console.log(' ├── docs/ Documentation');
|
|
208
|
-
console.log(' ├── GEMINI.md AI instructions');
|
|
209
|
-
console.log(' └── ANTIGRAVITY.md Antigravity config');
|
|
201
|
+
// Show what will be installed - ALL into .antigravity/
|
|
202
|
+
log.warn('📦 Installing:');
|
|
203
|
+
console.log(' ├── .antigravity/ 19 commands, 19 agents, 35 skills');
|
|
204
|
+
console.log(' ├── .ai-audit/ Decision logging');
|
|
205
|
+
console.log(' ├── .ai-memory/ Context storage');
|
|
206
|
+
console.log(' └── presets/docs Architecture & docs');
|
|
210
207
|
console.log('');
|
|
211
208
|
|
|
212
209
|
if (!isForce) {
|
|
213
|
-
const confirm = await ask('Tiếp tục cài đặt
|
|
210
|
+
const confirm = await ask('Tiếp tục cài đặt? (Y/n): ');
|
|
214
211
|
if (confirm.toLowerCase() === 'n') {
|
|
215
212
|
log.error('❌ Đã hủy.');
|
|
216
213
|
rl.close();
|
|
@@ -224,77 +221,112 @@ async function installAntigravity(isForce = false) {
|
|
|
224
221
|
log.warn('📋 Installing anchi-toolkit for Antigravity...');
|
|
225
222
|
console.log('');
|
|
226
223
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
224
|
+
const antigravityDest = path.join(targetPath, '.antigravity');
|
|
225
|
+
|
|
226
|
+
// Ensure .antigravity folder exists
|
|
227
|
+
if (!fs.existsSync(antigravityDest)) {
|
|
228
|
+
fs.mkdirSync(antigravityDest, { recursive: true });
|
|
229
|
+
}
|
|
230
230
|
|
|
231
|
+
// 1. Copy .antigravity folder (workflows, agents, skills)
|
|
232
|
+
const agentSource = path.join(kitPath, '.antigravity');
|
|
231
233
|
if (fs.existsSync(agentSource)) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
log.success(' ✅
|
|
235
|
-
log.success(' ✅
|
|
236
|
-
log.success(' ✅ .antigravity/skills/ - 35 skills');
|
|
234
|
+
await copyWithConflictHandling(agentSource, antigravityDest, true, isForce);
|
|
235
|
+
log.success(' ✅ workflows/ - 18 commands');
|
|
236
|
+
log.success(' ✅ agents/ - 19 agents');
|
|
237
|
+
log.success(' ✅ skills/ - 35 skills');
|
|
237
238
|
} else {
|
|
238
239
|
log.error(` ❌ .antigravity folder not found at: ${agentSource}`);
|
|
239
240
|
}
|
|
240
241
|
|
|
241
|
-
// 2. Copy presets
|
|
242
|
+
// 2. Copy presets INTO .antigravity/presets/
|
|
242
243
|
const presetsSource = path.join(kitPath, 'presets');
|
|
243
|
-
const presetsDest = path.join(
|
|
244
|
+
const presetsDest = path.join(antigravityDest, 'presets');
|
|
244
245
|
if (fs.existsSync(presetsSource)) {
|
|
245
246
|
await copyWithConflictHandling(presetsSource, presetsDest, true, isForce);
|
|
246
247
|
log.success(' ✅ presets/ - 3 architecture presets');
|
|
247
248
|
}
|
|
248
249
|
|
|
249
|
-
// 3. Copy docs
|
|
250
|
+
// 3. Copy docs INTO .antigravity/docs/
|
|
250
251
|
const docsSource = path.join(kitPath, 'docs');
|
|
251
|
-
const docsDest = path.join(
|
|
252
|
+
const docsDest = path.join(antigravityDest, 'docs');
|
|
252
253
|
if (fs.existsSync(docsSource)) {
|
|
253
254
|
await copyWithConflictHandling(docsSource, docsDest, true, isForce);
|
|
254
|
-
log.success(' ✅ docs/ - Documentation
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// 4. Copy AI instruction files
|
|
258
|
-
const geminiMdPath = path.join(kitPath, 'GEMINI.md');
|
|
259
|
-
if (fs.existsSync(geminiMdPath)) {
|
|
260
|
-
fs.copyFileSync(geminiMdPath, path.join(targetPath, 'GEMINI.md'));
|
|
261
|
-
log.success(' ✅ GEMINI.md');
|
|
255
|
+
log.success(' ✅ docs/ - Documentation');
|
|
262
256
|
}
|
|
263
257
|
|
|
264
|
-
|
|
265
|
-
if (fs.existsSync(antigravityMdPath)) {
|
|
266
|
-
fs.copyFileSync(antigravityMdPath, path.join(targetPath, 'ANTIGRAVITY.md'));
|
|
267
|
-
log.success(' ✅ ANTIGRAVITY.md');
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// 5. Copy config files to .antigravity/
|
|
258
|
+
// 4. Copy config files from .cursor to .antigravity
|
|
271
259
|
const configFiles = [
|
|
272
260
|
'orchestration.yaml',
|
|
273
261
|
'failure-modes.yaml',
|
|
274
262
|
'agent-skill-index.yaml',
|
|
275
|
-
'team.yaml'
|
|
263
|
+
'team.yaml',
|
|
264
|
+
'anchi-toolkit.config.yaml'
|
|
276
265
|
];
|
|
277
266
|
|
|
278
267
|
for (const configFile of configFiles) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (fs.existsSync(configSource)) {
|
|
268
|
+
// First check if exists in .antigravity source
|
|
269
|
+
let configSource = path.join(kitPath, '.antigravity', configFile);
|
|
270
|
+
if (!fs.existsSync(configSource)) {
|
|
271
|
+
// Fallback to .cursor
|
|
272
|
+
configSource = path.join(kitPath, '.cursor', configFile);
|
|
273
|
+
}
|
|
274
|
+
const configDest = path.join(antigravityDest, configFile);
|
|
275
|
+
if (fs.existsSync(configSource) && !fs.existsSync(configDest)) {
|
|
282
276
|
fs.copyFileSync(configSource, configDest);
|
|
283
277
|
}
|
|
284
278
|
}
|
|
285
|
-
|
|
279
|
+
// 5. Create .ai-audit folder (for logging)
|
|
280
|
+
const auditSource = path.join(kitPath, '.ai-audit');
|
|
281
|
+
const auditDest = path.join(antigravityDest, '.ai-audit'); // Inside .antigravity
|
|
282
|
+
if (fs.existsSync(auditSource)) {
|
|
283
|
+
await copyWithConflictHandling(auditSource, auditDest, true, isForce);
|
|
284
|
+
log.success(' ✅ .ai-audit/ - Decision logs');
|
|
285
|
+
}
|
|
286
286
|
|
|
287
|
+
// 6. Create .ai-memory folder (for context)
|
|
288
|
+
const memorySource = path.join(kitPath, '.ai-memory');
|
|
289
|
+
const memoryDest = path.join(antigravityDest, '.ai-memory'); // Inside .antigravity
|
|
290
|
+
if (fs.existsSync(memorySource)) {
|
|
291
|
+
await copyWithConflictHandling(memorySource, memoryDest, true, isForce);
|
|
292
|
+
log.success(' ✅ .ai-memory/ - Context storage');
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// 7. Create scripts folder (for setup)
|
|
296
|
+
const scriptsSource = path.join(kitPath, 'scripts');
|
|
297
|
+
const scriptsDest = path.join(antigravityDest, 'scripts');
|
|
298
|
+
if (fs.existsSync(scriptsSource)) {
|
|
299
|
+
await copyWithConflictHandling(scriptsSource, scriptsDest, true, isForce);
|
|
300
|
+
log.success(' ✅ scripts/ - Setup tools');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// 8. Copy ANTIGRAVITY.md to root (entry point doc)
|
|
304
|
+
const antigravityMdPath = path.join(kitPath, 'ANTIGRAVITY.md');
|
|
305
|
+
if (fs.existsSync(antigravityMdPath)) {
|
|
306
|
+
fs.copyFileSync(antigravityMdPath, path.join(targetPath, 'ANTIGRAVITY.md'));
|
|
307
|
+
log.success(' ✅ ANTIGRAVITY.md (root)');
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// =====================================================================
|
|
311
|
+
// SUCCESS MESSAGE - Clear Next Steps
|
|
312
|
+
// =====================================================================
|
|
313
|
+
console.log('');
|
|
314
|
+
console.log('');
|
|
315
|
+
log.success('╔═══════════════════════════════════════════════════════════╗');
|
|
316
|
+
log.success('║ ✅ INSTALLATION COMPLETE! ║');
|
|
317
|
+
log.success('╚═══════════════════════════════════════════════════════════╝');
|
|
318
|
+
console.log('');
|
|
319
|
+
log.info('📂 Installed to: .antigravity/');
|
|
287
320
|
console.log('');
|
|
288
|
-
log
|
|
289
|
-
log
|
|
290
|
-
log.success('
|
|
321
|
+
console.log('╭───────────────────────────────────────────────────────────╮');
|
|
322
|
+
console.log('│ │');
|
|
323
|
+
log.success('│ 🚀 START NOW: Open Antigravity Chat and type: │');
|
|
324
|
+
console.log('│ │');
|
|
325
|
+
log.warn('│ /start │');
|
|
326
|
+
console.log('│ │');
|
|
327
|
+
console.log('╰───────────────────────────────────────────────────────────╯');
|
|
291
328
|
console.log('');
|
|
292
|
-
|
|
293
|
-
log.info(' Open Antigravity Chat → Use slash commands:');
|
|
294
|
-
log.info(' /start - Initialize project');
|
|
295
|
-
log.info(' /do - Universal command');
|
|
296
|
-
log.info(' /commit - Git operations');
|
|
297
|
-
log.info(' /help - Show all commands');
|
|
329
|
+
log.gray('Other commands: /do, /commit, /test, /help');
|
|
298
330
|
console.log('');
|
|
299
331
|
|
|
300
332
|
rl.close();
|
|
@@ -331,17 +363,26 @@ async function install(isForce = false) {
|
|
|
331
363
|
console.log('');
|
|
332
364
|
|
|
333
365
|
// Components to install (Cursor AI specific)
|
|
366
|
+
const cursorDest = path.join(targetPath, '.cursor');
|
|
367
|
+
if (!fs.existsSync(cursorDest)) fs.mkdirSync(cursorDest, { recursive: true });
|
|
368
|
+
|
|
334
369
|
const components = [
|
|
335
|
-
|
|
336
|
-
{ source: '
|
|
337
|
-
{ source: '
|
|
338
|
-
{ source: '.
|
|
339
|
-
{ source: '
|
|
370
|
+
// Folders go INSIDE .cursor/
|
|
371
|
+
{ source: '.cursor', dest: '.cursor', isDir: true, desc: 'Cursor commands, agents, skills' },
|
|
372
|
+
{ source: 'presets', dest: '.cursor/presets', isDir: true, desc: 'Architecture presets' },
|
|
373
|
+
{ source: 'docs', dest: '.cursor/docs', isDir: true, desc: 'Documentation templates' },
|
|
374
|
+
{ source: 'scripts', dest: '.cursor/scripts', isDir: true, desc: 'Setup scripts' },
|
|
375
|
+
{ source: '.ai-audit', dest: '.cursor/.ai-audit', isDir: true, desc: 'AI decision logs' },
|
|
376
|
+
{ source: '.ai-memory', dest: '.cursor/.ai-memory', isDir: true, desc: 'Context storage' },
|
|
377
|
+
|
|
378
|
+
// Root files (Required for IDE)
|
|
379
|
+
{ source: '.cursorrules', dest: '.cursorrules', isDir: false, desc: 'Cursor rules (Root)' },
|
|
380
|
+
{ source: 'CURSOR.md', dest: 'CURSOR.md', isDir: false, desc: 'AI instructions (Root)' },
|
|
340
381
|
];
|
|
341
382
|
|
|
342
383
|
for (const comp of components) {
|
|
343
384
|
const sourcePath = path.join(kitPath, comp.source);
|
|
344
|
-
const destPath = path.join(targetPath, comp.
|
|
385
|
+
const destPath = path.join(targetPath, comp.dest);
|
|
345
386
|
|
|
346
387
|
if (fs.existsSync(sourcePath)) {
|
|
347
388
|
log.info(` 📦 ${comp.desc}...`);
|
|
@@ -411,6 +452,16 @@ async function main() {
|
|
|
411
452
|
await installAntigravity(isForce);
|
|
412
453
|
break;
|
|
413
454
|
|
|
455
|
+
case 'clean':
|
|
456
|
+
const { clean } = require('./commands/clean');
|
|
457
|
+
await clean(process.cwd(), {
|
|
458
|
+
all: flags.includes('--all'),
|
|
459
|
+
memory: flags.includes('--memory'),
|
|
460
|
+
audit: flags.includes('--audit'),
|
|
461
|
+
force: isForce
|
|
462
|
+
});
|
|
463
|
+
break;
|
|
464
|
+
|
|
414
465
|
default:
|
|
415
466
|
showHelp();
|
|
416
467
|
break;
|
|
@@ -429,6 +480,7 @@ function showHelp() {
|
|
|
429
480
|
log.success(' npx anchi-toolkit uninstall Gỡ cài đặt');
|
|
430
481
|
log.success(' npx anchi-toolkit doctor Kiểm tra setup health');
|
|
431
482
|
log.success(' npx anchi-toolkit memory Quản lý project context');
|
|
483
|
+
log.success(' npx anchi-toolkit clean Dọn dẹp context/logs');
|
|
432
484
|
console.log('');
|
|
433
485
|
console.log('Flags:');
|
|
434
486
|
log.success(' -y, --force Bỏ qua tất cả prompts (auto-overwrite)');
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// anchi-toolkit Clean Command
|
|
3
|
+
// Reset project context and logs
|
|
4
|
+
// =============================================================================
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const readline = require('readline');
|
|
9
|
+
const { getConfigDir } = require('../lib/configManager');
|
|
10
|
+
|
|
11
|
+
const rl = readline.createInterface({
|
|
12
|
+
input: process.stdin,
|
|
13
|
+
output: process.stdout,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function ask(question) {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
rl.question(question, (answer) => {
|
|
19
|
+
resolve(answer);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function clean(targetDir = process.cwd(), options = {}) {
|
|
25
|
+
console.log('');
|
|
26
|
+
console.log('🧹 anchi-toolkit Clean');
|
|
27
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
28
|
+
console.log('');
|
|
29
|
+
|
|
30
|
+
const configDir = getConfigDir(targetDir);
|
|
31
|
+
const auditDir = path.join(configDir, '.ai-audit');
|
|
32
|
+
const memoryDir = path.join(configDir, '.ai-memory');
|
|
33
|
+
|
|
34
|
+
const cleanMemory = options.memory || options.all;
|
|
35
|
+
const cleanAudit = options.audit || options.all;
|
|
36
|
+
const isForce = options.force;
|
|
37
|
+
|
|
38
|
+
if (!cleanMemory && !cleanAudit) {
|
|
39
|
+
console.log('Usage:');
|
|
40
|
+
console.log(' npx anchi-toolkit clean --memory Clear AI context');
|
|
41
|
+
console.log(' npx anchi-toolkit clean --audit Clear logs');
|
|
42
|
+
console.log(' npx anchi-toolkit clean --all Clear everything');
|
|
43
|
+
rl.close();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log('Checking targets:');
|
|
48
|
+
if (cleanMemory) console.log(` • Context Memory: ${memoryDir}`);
|
|
49
|
+
if (cleanAudit) console.log(` • Audit Logs: ${auditDir}`);
|
|
50
|
+
console.log('');
|
|
51
|
+
|
|
52
|
+
if (!isForce) {
|
|
53
|
+
const confirm = await ask('⚠️ Are you sure you want to delete these files? (Y/n): ');
|
|
54
|
+
if (confirm.toLowerCase() === 'n') {
|
|
55
|
+
console.log('❌ Cancelled.');
|
|
56
|
+
rl.close();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (cleanMemory) {
|
|
62
|
+
if (fs.existsSync(memoryDir)) {
|
|
63
|
+
// Keep the directory, just empty it or recreate it
|
|
64
|
+
fs.rmSync(memoryDir, { recursive: true, force: true });
|
|
65
|
+
fs.mkdirSync(memoryDir, { recursive: true });
|
|
66
|
+
console.log('✅ Memory cleared.');
|
|
67
|
+
} else {
|
|
68
|
+
console.log('⚪ Memory already clean.');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (cleanAudit) {
|
|
73
|
+
if (fs.existsSync(auditDir)) {
|
|
74
|
+
fs.rmSync(auditDir, { recursive: true, force: true });
|
|
75
|
+
fs.mkdirSync(auditDir, { recursive: true });
|
|
76
|
+
console.log('✅ Audit logs cleared.');
|
|
77
|
+
} else {
|
|
78
|
+
console.log('⚪ Audit logs already clean.');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log('');
|
|
83
|
+
console.log('✨ Clean complete!');
|
|
84
|
+
rl.close();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = { clean };
|
package/src/commands/doctor.js
CHANGED
|
@@ -14,28 +14,47 @@ async function doctor(targetDir = process.cwd()) {
|
|
|
14
14
|
|
|
15
15
|
const checks = [];
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
const
|
|
17
|
+
const { getConfigDir, CONFIG_FILENAME } = require('../lib/configManager');
|
|
18
|
+
const configDir = getConfigDir(targetDir);
|
|
19
|
+
const configDirName = path.basename(configDir);
|
|
20
|
+
|
|
21
|
+
// Check config folder
|
|
19
22
|
checks.push({
|
|
20
|
-
name:
|
|
21
|
-
ok: fs.existsSync(
|
|
23
|
+
name: `${configDirName} folder`,
|
|
24
|
+
ok: fs.existsSync(configDir),
|
|
22
25
|
fix: 'Run: npx anchi-toolkit init'
|
|
23
26
|
});
|
|
24
27
|
|
|
25
28
|
// Check commands
|
|
26
|
-
const commandsDir = path.join(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
const commandsDir = path.join(configDir, (configDirName === '.antigravity' ? 'workflows' : 'commands'));
|
|
30
|
+
// Antigravity has workflows, Cursor has commands. Though user might want consistency?
|
|
31
|
+
// Wait, my ANTIGRAVITY.md says .antigravity/workflows.
|
|
32
|
+
// cli.js installs .antigravity/workflows.
|
|
33
|
+
// So if configDir is .antigravity, check workflows.
|
|
34
|
+
// If configDir is .cursor, check commands.
|
|
35
|
+
// Actually, cli.js installs 'workflows' into .antigravity.
|
|
36
|
+
// Let's check logic:
|
|
37
|
+
// If .antigravity install: src: .cursor/commands (*.md) -> target: .antigravity/workflows (*.md)
|
|
38
|
+
// If .cursor install: src: .cursor/commands -> target: .cursor/commands.
|
|
39
|
+
|
|
40
|
+
// I need to detect which folder to check based on configDirName.
|
|
41
|
+
let cmdFolderName = 'commands';
|
|
42
|
+
if (configDirName === '.antigravity') cmdFolderName = 'workflows';
|
|
43
|
+
|
|
44
|
+
const cmdDir = path.join(configDir, cmdFolderName);
|
|
45
|
+
|
|
46
|
+
const commandCount = fs.existsSync(cmdDir)
|
|
47
|
+
? fs.readdirSync(cmdDir, { recursive: true }).filter(f => f.endsWith('.md')).length
|
|
29
48
|
: 0;
|
|
30
49
|
checks.push({
|
|
31
|
-
name:
|
|
50
|
+
name: `Commands/Workflows (${cmdFolderName})`,
|
|
32
51
|
ok: commandCount > 0,
|
|
33
52
|
value: `${commandCount} files`,
|
|
34
53
|
fix: 'Run: npx anchi-toolkit install'
|
|
35
54
|
});
|
|
36
55
|
|
|
37
56
|
// Check agents
|
|
38
|
-
const agentsDir = path.join(
|
|
57
|
+
const agentsDir = path.join(configDir, 'agents');
|
|
39
58
|
const agentCount = fs.existsSync(agentsDir)
|
|
40
59
|
? fs.readdirSync(agentsDir).filter(f => f.endsWith('.md')).length
|
|
41
60
|
: 0;
|
|
@@ -46,24 +65,46 @@ async function doctor(targetDir = process.cwd()) {
|
|
|
46
65
|
fix: 'Run: npx anchi-toolkit install'
|
|
47
66
|
});
|
|
48
67
|
|
|
49
|
-
// Check .cursorrules
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
// Check .cursorrules (Only for Cursor?)
|
|
69
|
+
if (configDirName === '.cursor') {
|
|
70
|
+
const rulesFile = path.join(targetDir, '.cursorrules');
|
|
71
|
+
checks.push({
|
|
72
|
+
name: '.cursorrules',
|
|
73
|
+
ok: fs.existsSync(rulesFile),
|
|
74
|
+
fix: 'Run: /use-preset [name]'
|
|
75
|
+
});
|
|
76
|
+
}
|
|
56
77
|
|
|
57
78
|
// Check config
|
|
58
|
-
const configFile = path.join(
|
|
79
|
+
const configFile = path.join(configDir, CONFIG_FILENAME);
|
|
80
|
+
let configValid = false;
|
|
81
|
+
if (fs.existsSync(configFile)) {
|
|
82
|
+
try {
|
|
83
|
+
const content = fs.readFileSync(configFile, 'utf-8');
|
|
84
|
+
// Basic YAML validation check
|
|
85
|
+
if (content.trim().length > 0) {
|
|
86
|
+
configValid = true;
|
|
87
|
+
// Try parsing if possible
|
|
88
|
+
try {
|
|
89
|
+
const { parseYaml } = require('../lib/configManager');
|
|
90
|
+
parseYaml(content);
|
|
91
|
+
} catch (e) {
|
|
92
|
+
configValid = false;
|
|
93
|
+
console.log(` ❌ Config syntax error: ${e.message}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} catch (e) {
|
|
97
|
+
configValid = false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
59
100
|
checks.push({
|
|
60
|
-
name: 'Config file',
|
|
61
|
-
ok:
|
|
62
|
-
fix: 'Run: npx anchi-toolkit init'
|
|
101
|
+
name: 'Config file syntax',
|
|
102
|
+
ok: configValid,
|
|
103
|
+
fix: 'Run: npx anchi-toolkit init (or fix YAML)'
|
|
63
104
|
});
|
|
64
105
|
|
|
65
106
|
// Check docs
|
|
66
|
-
const docsDir = path.join(
|
|
107
|
+
const docsDir = path.join(configDir, 'docs');
|
|
67
108
|
checks.push({
|
|
68
109
|
name: 'Docs folder',
|
|
69
110
|
ok: fs.existsSync(docsDir),
|
|
@@ -78,6 +119,32 @@ async function doctor(targetDir = process.cwd()) {
|
|
|
78
119
|
fix: 'Run: npm init -y'
|
|
79
120
|
});
|
|
80
121
|
|
|
122
|
+
// Check Write Permissions (.ai-memory)
|
|
123
|
+
const memoryDir = path.join(configDir, '.ai-memory');
|
|
124
|
+
let memoryWriteable = false;
|
|
125
|
+
if (!fs.existsSync(memoryDir)) {
|
|
126
|
+
// Create checks will fail later if not exists, but we can try to create
|
|
127
|
+
// Actually, install should create it.
|
|
128
|
+
// If missing, check ok=false
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// We check if we can write to configDir (essential for logs/memory)
|
|
132
|
+
try {
|
|
133
|
+
if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, {recursive: true});
|
|
134
|
+
const testFile = path.join(configDir, '.perm-test');
|
|
135
|
+
fs.writeFileSync(testFile, 'test');
|
|
136
|
+
fs.unlinkSync(testFile);
|
|
137
|
+
memoryWriteable = true;
|
|
138
|
+
} catch (e) {
|
|
139
|
+
memoryWriteable = false;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
checks.push({
|
|
143
|
+
name: 'Write Permissions',
|
|
144
|
+
ok: memoryWriteable,
|
|
145
|
+
fix: 'Check folder permissions'
|
|
146
|
+
});
|
|
147
|
+
|
|
81
148
|
// Display results
|
|
82
149
|
let allOk = true;
|
|
83
150
|
for (const check of checks) {
|
package/src/commands/init.js
CHANGED
|
@@ -286,7 +286,7 @@ async function init() {
|
|
|
286
286
|
if (finalConfig.includePresets) {
|
|
287
287
|
const presetsPath = path.join(kitPath, 'presets');
|
|
288
288
|
if (fs.existsSync(presetsPath)) {
|
|
289
|
-
copyDirRecursive(presetsPath, path.join(targetPath, 'presets'));
|
|
289
|
+
copyDirRecursive(presetsPath, path.join(targetPath, '.cursor/presets'));
|
|
290
290
|
log.success(' ✅ Presets');
|
|
291
291
|
}
|
|
292
292
|
}
|
|
@@ -294,11 +294,31 @@ async function init() {
|
|
|
294
294
|
if (finalConfig.includeDocs) {
|
|
295
295
|
const docsPath = path.join(kitPath, 'docs');
|
|
296
296
|
if (fs.existsSync(docsPath)) {
|
|
297
|
-
copyDirRecursive(docsPath, path.join(targetPath, 'docs'));
|
|
297
|
+
copyDirRecursive(docsPath, path.join(targetPath, '.cursor/docs'));
|
|
298
298
|
log.success(' ✅ Docs');
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
+
// Install AI folders (Implicit)
|
|
303
|
+
const auditPath = path.join(kitPath, '.ai-audit');
|
|
304
|
+
if (fs.existsSync(auditPath)) {
|
|
305
|
+
copyDirRecursive(auditPath, path.join(targetPath, '.cursor/.ai-audit'));
|
|
306
|
+
log.success(' ✅ .ai-audit');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const memoryPath = path.join(kitPath, '.ai-memory');
|
|
310
|
+
if (fs.existsSync(memoryPath)) {
|
|
311
|
+
copyDirRecursive(memoryPath, path.join(targetPath, '.cursor/.ai-memory'));
|
|
312
|
+
log.success(' ✅ .ai-memory');
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Install scripts
|
|
316
|
+
const scriptsPath = path.join(kitPath, 'scripts');
|
|
317
|
+
if (fs.existsSync(scriptsPath)) {
|
|
318
|
+
copyDirRecursive(scriptsPath, path.join(targetPath, '.cursor/scripts'));
|
|
319
|
+
log.success(' ✅ scripts');
|
|
320
|
+
}
|
|
321
|
+
|
|
302
322
|
// Always include
|
|
303
323
|
const cursorRulesPath = path.join(kitPath, '.cursorrules');
|
|
304
324
|
if (fs.existsSync(cursorRulesPath)) {
|
|
@@ -59,18 +59,33 @@ async function uninstall() {
|
|
|
59
59
|
|
|
60
60
|
const targetPath = process.cwd();
|
|
61
61
|
|
|
62
|
+
// Items to remove
|
|
62
63
|
// Items to remove
|
|
63
64
|
const itemsToRemove = [
|
|
65
|
+
// Cursor
|
|
64
66
|
{ path: '.cursor/commands', type: 'dir', desc: 'Commands' },
|
|
65
67
|
{ path: '.cursor/agents', type: 'dir', desc: 'Agents' },
|
|
66
68
|
{ path: '.cursor/skills', type: 'dir', desc: 'Skills' },
|
|
69
|
+
{ path: '.cursor/presets', type: 'dir', desc: 'Presets' },
|
|
70
|
+
{ path: '.cursor/docs', type: 'dir', desc: 'Docs' },
|
|
71
|
+
{ path: '.cursor/.ai-audit', type: 'dir', desc: 'Audit Logs' },
|
|
72
|
+
{ path: '.cursor/.ai-memory', type: 'dir', desc: 'Memory' },
|
|
67
73
|
{ path: '.cursor/MODEL_COSTS.md', type: 'file', desc: 'Model costs guide' },
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
|
|
75
|
+
// Antigravity
|
|
76
|
+
{ path: '.antigravity', type: 'dir', desc: 'Antigravity Folder' },
|
|
77
|
+
|
|
78
|
+
// Root files
|
|
70
79
|
{ path: '.cursorrules', type: 'file', desc: 'Cursor rules' },
|
|
71
80
|
{ path: 'CURSOR.md', type: 'file', desc: 'Cursor instructions' },
|
|
72
81
|
{ path: 'GEMINI.md', type: 'file', desc: 'Gemini instructions' },
|
|
73
82
|
{ path: 'ANTIGRAVITY.md', type: 'file', desc: 'Antigravity instructions' },
|
|
83
|
+
|
|
84
|
+
// Legacy (Root) - Cleanup old installs
|
|
85
|
+
{ path: 'presets', type: 'dir', desc: 'Presets (Legacy)' },
|
|
86
|
+
{ path: 'docs', type: 'dir', desc: 'Docs (Legacy)' },
|
|
87
|
+
{ path: '.ai-audit', type: 'dir', desc: 'Audit Logs (Legacy)' },
|
|
88
|
+
{ path: '.ai-memory', type: 'dir', desc: 'Memory (Legacy)' },
|
|
74
89
|
];
|
|
75
90
|
|
|
76
91
|
// Check what exists
|
package/src/lib/configManager.js
CHANGED
|
@@ -128,11 +128,25 @@ function deepMerge(target, source) {
|
|
|
128
128
|
return result;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Get config directory (.antigravity or .cursor)
|
|
133
|
+
*/
|
|
134
|
+
function getConfigDir(targetDir) {
|
|
135
|
+
// Check for Antigravity first
|
|
136
|
+
const antigravityDir = path.join(targetDir, '.antigravity');
|
|
137
|
+
if (fs.existsSync(antigravityDir)) {
|
|
138
|
+
return antigravityDir;
|
|
139
|
+
}
|
|
140
|
+
// Fallback to Cursor
|
|
141
|
+
return path.join(targetDir, '.cursor');
|
|
142
|
+
}
|
|
143
|
+
|
|
131
144
|
/**
|
|
132
145
|
* Load config from target directory
|
|
133
146
|
*/
|
|
134
147
|
function loadConfig(targetDir) {
|
|
135
|
-
const
|
|
148
|
+
const configDir = getConfigDir(targetDir);
|
|
149
|
+
const configPath = path.join(configDir, CONFIG_FILENAME);
|
|
136
150
|
|
|
137
151
|
if (!fs.existsSync(configPath)) {
|
|
138
152
|
return DEFAULT_CONFIG;
|
|
@@ -152,11 +166,11 @@ function loadConfig(targetDir) {
|
|
|
152
166
|
* Save config to target directory
|
|
153
167
|
*/
|
|
154
168
|
function saveConfig(targetDir, config) {
|
|
155
|
-
const
|
|
156
|
-
const configPath = path.join(
|
|
169
|
+
const configDir = getConfigDir(targetDir);
|
|
170
|
+
const configPath = path.join(configDir, CONFIG_FILENAME);
|
|
157
171
|
|
|
158
|
-
if (!fs.existsSync(
|
|
159
|
-
fs.mkdirSync(
|
|
172
|
+
if (!fs.existsSync(configDir)) {
|
|
173
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
160
174
|
}
|
|
161
175
|
|
|
162
176
|
const header = `# anchi-toolkit Configuration
|
|
@@ -197,4 +211,5 @@ module.exports = {
|
|
|
197
211
|
deepMerge,
|
|
198
212
|
getConfigValue,
|
|
199
213
|
setConfigValue,
|
|
214
|
+
getConfigDir,
|
|
200
215
|
};
|
package/src/lib/memoryManager.js
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
const path = require('path');
|
|
8
|
+
const { getConfigDir } = require('./configManager');
|
|
8
9
|
|
|
9
|
-
const
|
|
10
|
-
const MEMORY_FILE = '
|
|
10
|
+
const MEMORY_DIR_NAME = '.ai-memory';
|
|
11
|
+
const MEMORY_FILE = 'context.json'; // Changed from memory.json to context.json based on what I saw in ls
|
|
11
12
|
|
|
12
13
|
// Default memory structure
|
|
13
14
|
const DEFAULT_MEMORY = {
|
|
@@ -36,14 +37,16 @@ const DEFAULT_MEMORY = {
|
|
|
36
37
|
* Get memory file path
|
|
37
38
|
*/
|
|
38
39
|
function getMemoryPath(targetDir) {
|
|
39
|
-
|
|
40
|
+
const configDir = getConfigDir(targetDir);
|
|
41
|
+
return path.join(configDir, MEMORY_DIR_NAME, MEMORY_FILE);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
45
|
* Ensure memory directory exists
|
|
44
46
|
*/
|
|
45
47
|
function ensureMemoryDir(targetDir) {
|
|
46
|
-
const
|
|
48
|
+
const configDir = getConfigDir(targetDir);
|
|
49
|
+
const memoryDir = path.join(configDir, MEMORY_DIR_NAME);
|
|
47
50
|
if (!fs.existsSync(memoryDir)) {
|
|
48
51
|
fs.mkdirSync(memoryDir, { recursive: true });
|
|
49
52
|
}
|