aiwf 0.3.18 → 0.3.20

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.
@@ -34,7 +34,6 @@ import {
34
34
  import {
35
35
  FILES,
36
36
  TOOL_DIRS,
37
- TEMP_DIRS,
38
37
  AIWF_DIRS,
39
38
  BASE_DIRS,
40
39
  getAllAiwfDirectories,
@@ -507,14 +506,112 @@ async function updateCommands(languagePath, spinner, msg, debugLog) {
507
506
  }
508
507
  }
509
508
 
509
+ /**
510
+ * Check if tool directories exist and handle them
511
+ * @param {Object} spinner - Ora spinner instance
512
+ * @param {Object} msg - Localized messages
513
+ * @param {boolean} debugLog - Debug mode flag
514
+ * @returns {Promise<Object>} Directory status info
515
+ */
516
+ async function checkAndHandleExistingToolDirs(spinner, msg, debugLog) {
517
+ const toolDirStatus = {
518
+ cursor: {
519
+ exists: false,
520
+ hadFiles: false,
521
+ backedUp: false
522
+ },
523
+ windsurf: {
524
+ exists: false,
525
+ hadFiles: false,
526
+ backedUp: false
527
+ }
528
+ };
529
+
530
+ // Check Cursor directory
531
+ try {
532
+ await fs.access(TOOL_DIRS.CURSOR_RULES);
533
+ toolDirStatus.cursor.exists = true;
534
+
535
+ const cursorFiles = await fs.readdir(TOOL_DIRS.CURSOR_RULES);
536
+ const mdcFiles = cursorFiles.filter(file => file.endsWith('.mdc'));
537
+
538
+ if (mdcFiles.length > 0) {
539
+ toolDirStatus.cursor.hadFiles = true;
540
+ logWithSpinner(spinner, `${msg.foundExistingCursor} (${mdcFiles.length} files)`, debugLog);
541
+
542
+ // Backup existing files
543
+ logWithSpinner(spinner, msg.backingUpToolFiles, debugLog);
544
+ const backupDir = path.join(TOOL_DIRS.CURSOR_RULES, `backup_${Date.now()}`);
545
+ await fs.mkdir(backupDir, { recursive: true });
546
+
547
+ for (const file of mdcFiles) {
548
+ const srcPath = path.join(TOOL_DIRS.CURSOR_RULES, file);
549
+ const backupPath = path.join(backupDir, file);
550
+ await fs.copyFile(srcPath, backupPath);
551
+ }
552
+
553
+ toolDirStatus.cursor.backedUp = true;
554
+ logWithSpinner(spinner, `${msg.toolBackupCreated}: ${backupDir}`, debugLog);
555
+
556
+ // Remove existing files
557
+ for (const file of mdcFiles) {
558
+ await fs.unlink(path.join(TOOL_DIRS.CURSOR_RULES, file));
559
+ }
560
+ }
561
+ } catch (error) {
562
+ // Directory doesn't exist, that's fine
563
+ logWithSpinner(spinner, `Cursor rules directory not found, will create new`, debugLog);
564
+ }
565
+
566
+ // Check Windsurf directory
567
+ try {
568
+ await fs.access(TOOL_DIRS.WINDSURF_RULES);
569
+ toolDirStatus.windsurf.exists = true;
570
+
571
+ const windsurfFiles = await fs.readdir(TOOL_DIRS.WINDSURF_RULES);
572
+ const mdFiles = windsurfFiles.filter(file => file.endsWith('.md'));
573
+
574
+ if (mdFiles.length > 0) {
575
+ toolDirStatus.windsurf.hadFiles = true;
576
+ logWithSpinner(spinner, `${msg.foundExistingWindsurf} (${mdFiles.length} files)`, debugLog);
577
+
578
+ // Backup existing files
579
+ logWithSpinner(spinner, msg.backingUpToolFiles, debugLog);
580
+ const backupDir = path.join(TOOL_DIRS.WINDSURF_RULES, `backup_${Date.now()}`);
581
+ await fs.mkdir(backupDir, { recursive: true });
582
+
583
+ for (const file of mdFiles) {
584
+ const srcPath = path.join(TOOL_DIRS.WINDSURF_RULES, file);
585
+ const backupPath = path.join(backupDir, file);
586
+ await fs.copyFile(srcPath, backupPath);
587
+ }
588
+
589
+ toolDirStatus.windsurf.backedUp = true;
590
+ logWithSpinner(spinner, `${msg.toolBackupCreated}: ${backupDir}`, debugLog);
591
+
592
+ // Remove existing files
593
+ for (const file of mdFiles) {
594
+ await fs.unlink(path.join(TOOL_DIRS.WINDSURF_RULES, file));
595
+ }
596
+ }
597
+ } catch (error) {
598
+ // Directory doesn't exist, that's fine
599
+ logWithSpinner(spinner, `Windsurf rules directory not found, will create new`, debugLog);
600
+ }
601
+
602
+ return toolDirStatus;
603
+ }
604
+
510
605
  /**
511
606
  * Download and process rules
512
607
  * @param {Object} spinner - Ora spinner instance
513
- {{ ... }}
514
608
  * @param {Object} msg - Localized messages
515
609
  * @param {boolean} debugLog - Debug mode flag
516
610
  */
517
611
  async function downloadAndProcessRules(spinner, msg, debugLog) {
612
+ // Check and handle existing tool directories first
613
+ logWithSpinner(spinner, msg.checkingExistingTools, debugLog);
614
+ const toolDirStatus = await checkAndHandleExistingToolDirs(spinner, msg, debugLog);
518
615
  // Try to download from GitHub first, fallback to local files
519
616
  const tmpRulesGlobal = path.join(os.tmpdir(), 'aiwf-rules-global');
520
617
  const tmpRulesManual = path.join(os.tmpdir(), 'aiwf-rules-manual');
@@ -670,6 +767,32 @@ async function downloadAndProcessRules(spinner, msg, debugLog) {
670
767
  } catch (error) {
671
768
  logWithSpinner(spinner, `No rules/manual directory found`, debugLog);
672
769
  }
770
+
771
+ // Success message for tool rules installation
772
+ logWithSpinner(spinner, msg.toolRulesInstalled, debugLog);
773
+
774
+ // Display installation results for tool directories
775
+ if (toolDirStatus.cursor.backedUp || toolDirStatus.windsurf.backedUp) {
776
+ console.log(chalk.cyan(`\n📂 Tool Directory Installation Results:`));
777
+
778
+ if (toolDirStatus.cursor.backedUp) {
779
+ console.log(chalk.yellow(` • Cursor: Existing rules backed up and replaced`));
780
+ } else if (toolDirStatus.cursor.exists) {
781
+ console.log(chalk.green(` • Cursor: Rules installed (directory was empty)`));
782
+ } else {
783
+ console.log(chalk.green(` • Cursor: Rules installed (new directory)`));
784
+ }
785
+
786
+ if (toolDirStatus.windsurf.backedUp) {
787
+ console.log(chalk.yellow(` • Windsurf: Existing rules backed up and replaced`));
788
+ } else if (toolDirStatus.windsurf.exists) {
789
+ console.log(chalk.green(` • Windsurf: Rules installed (directory was empty)`));
790
+ } else {
791
+ console.log(chalk.green(` • Windsurf: Rules installed (new directory)`));
792
+ }
793
+ }
794
+
795
+ return toolDirStatus;
673
796
  }
674
797
 
675
798
  /**
@@ -819,7 +942,7 @@ export async function installAIWF(options = {}) {
819
942
  await updateCommands(languagePath, spinner, msg, debugLog);
820
943
 
821
944
  // Download and process rules
822
- await downloadAndProcessRules(spinner, msg, debugLog);
945
+ const toolDirStatus = await downloadAndProcessRules(spinner, msg, debugLog);
823
946
 
824
947
  // Restore project files if needed
825
948
  if (projectBackupDir) {
@@ -3,322 +3,17 @@ import path from 'path';
3
3
  import chalk from 'chalk';
4
4
  import { TOOL_DIRS, AIWF_DIRS, FILES } from '../utils/paths.js';
5
5
 
6
- // Essential files configuration for each tool
7
- const ESSENTIAL_FILES = {
8
- claudeCode: {
9
- baseDir: TOOL_DIRS.CLAUDE_COMMANDS,
10
- requiredFiles: [
11
- 'aiwf_initialize.md',
12
- 'aiwf_do_task.md',
13
- 'aiwf_commit.md',
14
- 'aiwf_create_sprint_tasks.md',
15
- 'aiwf_code_review.md'
16
- ],
17
- minFileCount: 5,
18
- description: 'Claude Code Commands'
19
- },
20
- geminiCLI: {
21
- baseDir: TOOL_DIRS.GEMINI_PROMPTS,
22
- requiredFiles: ['README.md'],
23
- minFileCount: 1,
24
- description: 'Gemini-CLI Prompts'
25
- },
26
- cursor: {
27
- baseDir: TOOL_DIRS.CURSOR_RULES,
28
- requiredFiles: [],
29
- minFileCount: 2,
30
- fileExtension: '.mdc',
31
- description: 'Cursor IDE Rules'
32
- },
33
- windsurf: {
34
- baseDir: TOOL_DIRS.WINDSURF_RULES,
35
- requiredFiles: [],
36
- minFileCount: 2,
37
- fileExtension: '.md',
38
- description: 'Windsurf IDE Rules'
39
- },
40
- aiwf: {
41
- baseDir: AIWF_DIRS.ROOT,
42
- requiredFiles: ['CLAUDE.md', '00_PROJECT_MANIFEST.md'],
43
- minFileCount: 2,
44
- description: 'AIWF Core Structure'
6
+ // Validation constants
7
+ const VALIDATION_CONSTANTS = {
8
+ MIN_FILE_SIZE: 10,
9
+ MIN_RULE_FILE_SIZE: 50,
10
+ MIN_FILE_COUNT: {
11
+ CURSOR_MDC: 2,
12
+ WINDSURF_MD: 2,
13
+ CLAUDE_COMMANDS: 4
45
14
  }
46
15
  };
47
16
 
48
- /**
49
- * Validate tool installation based on configuration
50
- * @param {Object} config - Tool configuration
51
- * @returns {Promise<Object>} Validation results
52
- */
53
- async function validateToolInstallation(config) {
54
- const results = {
55
- success: true,
56
- description: config.description,
57
- baseDir: config.baseDir,
58
- checks: {
59
- directoryExists: false,
60
- fileCount: 0,
61
- requiredFiles: [],
62
- totalSize: 0,
63
- issues: []
64
- }
65
- };
66
-
67
- try {
68
- // 1. Check directory exists
69
- await fs.access(config.baseDir);
70
- const dirStat = await fs.stat(config.baseDir);
71
- if (dirStat.isDirectory()) {
72
- results.checks.directoryExists = true;
73
- } else {
74
- results.checks.issues.push(`${config.baseDir} is not a directory`);
75
- results.success = false;
76
- return results;
77
- }
78
-
79
- // 2. Get file list
80
- const actualFiles = await fs.readdir(config.baseDir);
81
- results.checks.fileCount = actualFiles.length;
82
-
83
- // 3. Check required files
84
- for (const requiredFile of config.requiredFiles || []) {
85
- const filePath = path.join(config.baseDir, requiredFile);
86
- const fileCheck = {
87
- file: requiredFile,
88
- exists: false,
89
- size: 0,
90
- valid: false
91
- };
92
-
93
- if (actualFiles.includes(requiredFile)) {
94
- fileCheck.exists = true;
95
- try {
96
- const stats = await fs.stat(filePath);
97
- fileCheck.size = stats.size;
98
- results.checks.totalSize += stats.size;
99
-
100
- // Validate file size (minimum 10 bytes)
101
- if (stats.size < 10) {
102
- results.checks.issues.push(
103
- `File ${requiredFile} is too small (${stats.size} bytes)`
104
- );
105
- results.success = false;
106
- } else {
107
- fileCheck.valid = true;
108
- }
109
- } catch (error) {
110
- results.checks.issues.push(
111
- `Cannot read stats for ${requiredFile}: ${error.message}`
112
- );
113
- results.success = false;
114
- }
115
- } else {
116
- results.checks.issues.push(`Required file ${requiredFile} is missing`);
117
- results.success = false;
118
- }
119
-
120
- results.checks.requiredFiles.push(fileCheck);
121
- }
122
-
123
- // 4. File extension validation (Cursor/Windsurf)
124
- if (config.fileExtension) {
125
- const matchingFiles = actualFiles.filter(f => f.endsWith(config.fileExtension));
126
- if (matchingFiles.length < config.minFileCount) {
127
- results.checks.issues.push(
128
- `Expected at least ${config.minFileCount} ${config.fileExtension} files, found ${matchingFiles.length}`
129
- );
130
- results.success = false;
131
- }
132
-
133
- // Validate file sizes for extension files
134
- for (const file of matchingFiles) {
135
- const filePath = path.join(config.baseDir, file);
136
- try {
137
- const stats = await fs.stat(filePath);
138
- results.checks.totalSize += stats.size;
139
-
140
- if (stats.size < 50) {
141
- // Rules files should be at least 50 bytes
142
- results.checks.issues.push(
143
- `Rules file ${file} is too small (${stats.size} bytes)`
144
- );
145
- results.success = false;
146
- }
147
- } catch (error) {
148
- results.checks.issues.push(`Cannot read ${file}: ${error.message}`);
149
- results.success = false;
150
- }
151
- }
152
- }
153
-
154
- // 5. Minimum file count validation
155
- if (results.checks.fileCount < config.minFileCount) {
156
- results.checks.issues.push(
157
- `Expected at least ${config.minFileCount} files, found ${results.checks.fileCount}`
158
- );
159
- results.success = false;
160
- }
161
- } catch (error) {
162
- results.success = false;
163
- results.checks.issues.push(`Validation error: ${error.message}`);
164
- }
165
-
166
- return results;
167
- }
168
-
169
- /**
170
- * Validate Claude Code installation
171
- * @returns {Promise<Object>} Validation results
172
- */
173
- export async function validateClaudeInstall() {
174
- return await validateToolInstallation(ESSENTIAL_FILES.claudeCode);
175
- }
176
-
177
- /**
178
- * Validate Gemini CLI installation
179
- * @returns {Promise<Object>} Validation results
180
- */
181
- export async function validateGeminiInstall() {
182
- return await validateToolInstallation(ESSENTIAL_FILES.geminiCLI);
183
- }
184
-
185
- /**
186
- * Validate Cursor installation
187
- * @returns {Promise<Object>} Validation results
188
- */
189
- export async function validateCursorInstall() {
190
- return await validateToolInstallation(ESSENTIAL_FILES.cursor);
191
- }
192
-
193
- /**
194
- * Validate Windsurf installation
195
- * @returns {Promise<Object>} Validation results
196
- */
197
- export async function validateWindsurfInstall() {
198
- return await validateToolInstallation(ESSENTIAL_FILES.windsurf);
199
- }
200
-
201
- /**
202
- * Validate AIWF Core installation
203
- * @returns {Promise<Object>} Validation results
204
- */
205
- export async function validateAIWFCore() {
206
- return await validateToolInstallation(ESSENTIAL_FILES.aiwf);
207
- }
208
-
209
- /**
210
- * Validate installation with detailed results
211
- * @returns {Promise<Object>} Detailed validation results
212
- */
213
- export async function validateInstallationDetailed() {
214
- const validationResults = {
215
- overall: {
216
- success: true,
217
- toolsChecked: 0,
218
- toolsPassed: 0,
219
- toolsFailed: 0,
220
- totalIssues: 0
221
- },
222
- tools: {}
223
- };
224
-
225
- // Always validate AIWF core
226
- const aiwfResult = await validateAIWFCore();
227
- validationResults.tools.aiwf = aiwfResult;
228
- validationResults.overall.toolsChecked++;
229
-
230
- if (aiwfResult.success) {
231
- validationResults.overall.toolsPassed++;
232
- } else {
233
- validationResults.overall.toolsFailed++;
234
- validationResults.overall.success = false;
235
- validationResults.overall.totalIssues += aiwfResult.checks.issues.length;
236
- }
237
-
238
- // Validate all tools
239
- const toolValidators = {
240
- claudeCode: validateClaudeInstall,
241
- geminiCLI: validateGeminiInstall,
242
- cursor: validateCursorInstall,
243
- windsurf: validateWindsurfInstall
244
- };
245
-
246
- for (const [toolName, validator] of Object.entries(toolValidators)) {
247
- const result = await validator();
248
- validationResults.tools[toolName] = result;
249
- validationResults.overall.toolsChecked++;
250
-
251
- if (result.success) {
252
- validationResults.overall.toolsPassed++;
253
- } else {
254
- validationResults.overall.toolsFailed++;
255
- validationResults.overall.success = false;
256
- validationResults.overall.totalIssues += result.checks.issues.length;
257
- }
258
- }
259
-
260
- return validationResults;
261
- }
262
-
263
- /**
264
- * Enhanced installation validation with tool selection
265
- * @param {Array|null} selectedTools - Tools to validate
266
- * @param {string} language - Language code
267
- * @returns {Promise<Object>} Validation results
268
- */
269
- export async function validateInstallationEnhanced(selectedTools = null, language = 'en') {
270
- const validationResults = {
271
- overall: {
272
- success: true,
273
- toolsChecked: 0,
274
- toolsPassed: 0,
275
- toolsFailed: 0,
276
- totalIssues: 0
277
- },
278
- tools: {}
279
- };
280
-
281
- // Always validate AIWF core
282
- const aiwfResult = await validateAIWFCore();
283
- validationResults.tools.aiwf = aiwfResult;
284
- validationResults.overall.toolsChecked++;
285
-
286
- if (aiwfResult.success) {
287
- validationResults.overall.toolsPassed++;
288
- } else {
289
- validationResults.overall.toolsFailed++;
290
- validationResults.overall.success = false;
291
- validationResults.overall.totalIssues += aiwfResult.checks.issues.length;
292
- }
293
-
294
- // Determine tools to validate
295
- const toolsToValidate = selectedTools || ['claudeCode', 'geminiCLI', 'cursor', 'windsurf'];
296
-
297
- const toolValidators = {
298
- claudeCode: validateClaudeInstall,
299
- geminiCLI: validateGeminiInstall,
300
- cursor: validateCursorInstall,
301
- windsurf: validateWindsurfInstall
302
- };
303
-
304
- for (const toolName of toolsToValidate) {
305
- if (toolValidators[toolName]) {
306
- const result = await toolValidators[toolName]();
307
- validationResults.tools[toolName] = result;
308
- validationResults.overall.toolsChecked++;
309
-
310
- if (result.success) {
311
- validationResults.overall.toolsPassed++;
312
- } else {
313
- validationResults.overall.toolsFailed++;
314
- validationResults.overall.success = false;
315
- validationResults.overall.totalIssues += result.checks.issues.length;
316
- }
317
- }
318
- }
319
-
320
- return validationResults;
321
- }
322
17
 
323
18
  /**
324
19
  * Simplified validation with clean interface
@@ -440,6 +135,16 @@ async function validateClaudeCode() {
440
135
  if (!exists) {
441
136
  return { success: false, reason: `Missing file: ${filePath}` };
442
137
  }
138
+
139
+ // Check file size
140
+ try {
141
+ const stats = await fs.stat(filePath);
142
+ if (stats.size < VALIDATION_CONSTANTS.MIN_FILE_SIZE) {
143
+ return { success: false, reason: `File ${fileName} is too small (${stats.size} bytes)` };
144
+ }
145
+ } catch (error) {
146
+ return { success: false, reason: `Cannot read file ${fileName}: ${error.message}` };
147
+ }
443
148
  }
444
149
 
445
150
  return { success: true };
@@ -485,6 +190,36 @@ async function validateCursorTool() {
485
190
  return { success: false, reason: `Missing Cursor rules directory: ${TOOL_DIRS.CURSOR_RULES}` };
486
191
  }
487
192
 
193
+ // Enhanced validation: Check file count and types
194
+ const files = await fs.readdir(TOOL_DIRS.CURSOR_RULES);
195
+ const mdcFiles = files.filter(file => file.endsWith('.mdc'));
196
+
197
+ if (mdcFiles.length < VALIDATION_CONSTANTS.MIN_FILE_COUNT.CURSOR_MDC) {
198
+ return {
199
+ success: false,
200
+ reason: `Cursor rules: Expected at least ${VALIDATION_CONSTANTS.MIN_FILE_COUNT.CURSOR_MDC} .mdc files, found ${mdcFiles.length}`
201
+ };
202
+ }
203
+
204
+ // Validate file sizes
205
+ for (const file of mdcFiles) {
206
+ const filePath = path.join(TOOL_DIRS.CURSOR_RULES, file);
207
+ try {
208
+ const stats = await fs.stat(filePath);
209
+ if (stats.size < VALIDATION_CONSTANTS.MIN_RULE_FILE_SIZE) {
210
+ return {
211
+ success: false,
212
+ reason: `Cursor rules file ${file} is too small (${stats.size} bytes, minimum ${VALIDATION_CONSTANTS.MIN_RULE_FILE_SIZE})`
213
+ };
214
+ }
215
+ } catch (error) {
216
+ return {
217
+ success: false,
218
+ reason: `Cannot read Cursor rules file ${file}: ${error.message}`
219
+ };
220
+ }
221
+ }
222
+
488
223
  return { success: true };
489
224
  } catch (error) {
490
225
  return { success: false, reason: `Cursor validation error: ${error.message}` };
@@ -505,6 +240,36 @@ async function validateWindsurfTool() {
505
240
  return { success: false, reason: `Missing Windsurf rules directory: ${TOOL_DIRS.WINDSURF_RULES}` };
506
241
  }
507
242
 
243
+ // Enhanced validation: Check file count and types
244
+ const files = await fs.readdir(TOOL_DIRS.WINDSURF_RULES);
245
+ const mdFiles = files.filter(file => file.endsWith('.md'));
246
+
247
+ if (mdFiles.length < VALIDATION_CONSTANTS.MIN_FILE_COUNT.WINDSURF_MD) {
248
+ return {
249
+ success: false,
250
+ reason: `Windsurf rules: Expected at least ${VALIDATION_CONSTANTS.MIN_FILE_COUNT.WINDSURF_MD} .md files, found ${mdFiles.length}`
251
+ };
252
+ }
253
+
254
+ // Validate file sizes
255
+ for (const file of mdFiles) {
256
+ const filePath = path.join(TOOL_DIRS.WINDSURF_RULES, file);
257
+ try {
258
+ const stats = await fs.stat(filePath);
259
+ if (stats.size < VALIDATION_CONSTANTS.MIN_RULE_FILE_SIZE) {
260
+ return {
261
+ success: false,
262
+ reason: `Windsurf rules file ${file} is too small (${stats.size} bytes, minimum ${VALIDATION_CONSTANTS.MIN_RULE_FILE_SIZE})`
263
+ };
264
+ }
265
+ } catch (error) {
266
+ return {
267
+ success: false,
268
+ reason: `Cannot read Windsurf rules file ${file}: ${error.message}`
269
+ };
270
+ }
271
+ }
272
+
508
273
  return { success: true };
509
274
  } catch (error) {
510
275
  return { success: false, reason: `Windsurf validation error: ${error.message}` };
@@ -69,7 +69,14 @@ export const messages = {
69
69
  checkingInstallation: 'AIWF 설치 상태를 확인하는 중...',
70
70
  creatingDirectories: 'AIWF 디렉토리 구조를 생성하는 중...',
71
71
  restoringBackup: '백업에서 파일을 복원하는 중...',
72
- backupRestored: '{count}개 파일이 복원되었습니다'
72
+ backupRestored: '{count}개 파일이 복원되었습니다',
73
+ checkingExistingTools: '기존 도구 디렉토리를 확인하는 중...',
74
+ foundExistingCursor: 'Cursor 규칙 파일이 발견되었습니다',
75
+ foundExistingWindsurf: 'Windsurf 규칙 파일이 발견되었습니다',
76
+ backingUpToolFiles: '기존 도구 파일을 백업하는 중...',
77
+ toolBackupCreated: '도구 파일 백업이 생성되었습니다',
78
+ installingToolRules: '도구 규칙을 설치하는 중...',
79
+ toolRulesInstalled: '도구 규칙이 성공적으로 설치되었습니다',
73
80
  },
74
81
  en: {
75
82
  welcome: '\n🎉 Welcome to AIWF!\n',
@@ -138,7 +145,14 @@ export const messages = {
138
145
  checkingInstallation: 'Checking AIWF installation status...',
139
146
  creatingDirectories: 'Creating AIWF directory structure...',
140
147
  restoringBackup: 'Restoring files from backup...',
141
- backupRestored: '{count} files restored'
148
+ backupRestored: '{count} files restored',
149
+ checkingExistingTools: 'Checking existing tool directories...',
150
+ foundExistingCursor: 'Found existing Cursor rules',
151
+ foundExistingWindsurf: 'Found existing Windsurf rules',
152
+ backingUpToolFiles: 'Backing up existing tool files...',
153
+ toolBackupCreated: 'Tool files backup created',
154
+ installingToolRules: 'Installing tool rules...',
155
+ toolRulesInstalled: 'Tool rules installed successfully',
142
156
  }
143
157
  };
144
158
 
@@ -56,11 +56,6 @@ export const FILES = {
56
56
  }
57
57
  };
58
58
 
59
- // Temporary directories
60
- export const TEMP_DIRS = {
61
- RULES_GLOBAL: path.join(AIWF_DIRS.ROOT, '_tmp_rules_global'),
62
- RULES_MANUAL: path.join(AIWF_DIRS.ROOT, '_tmp_rules_manual')
63
- };
64
59
 
65
60
  // User cache directory (for global cache)
66
61
  export const USER_CACHE_DIR = path.join(
@@ -103,18 +98,6 @@ export function getToolDirectory(tool) {
103
98
  return mapping[tool] || null;
104
99
  }
105
100
 
106
- // Get backup directory name with timestamp
107
- export function getBackupDirName() {
108
- const now = new Date();
109
- const pad = n => n.toString().padStart(2, '0');
110
- const y = now.getFullYear();
111
- const m = pad(now.getMonth() + 1);
112
- const d = pad(now.getDate());
113
- const h = pad(now.getHours());
114
- const min = pad(now.getMinutes());
115
- const s = pad(now.getSeconds());
116
- return path.join(AIWF_DIRS.ROOT, `backup_${y}${m}${d}_${h}${min}${s}`);
117
- }
118
101
 
119
102
  // Export all for convenience
120
103
  export default {
@@ -122,10 +105,8 @@ export default {
122
105
  AIWF_DIRS,
123
106
  TOOL_DIRS,
124
107
  FILES,
125
- TEMP_DIRS,
126
108
  USER_CACHE_DIR,
127
109
  getAllAiwfDirectories,
128
110
  getAllClaudeMdFiles,
129
- getToolDirectory,
130
- getBackupDirName
111
+ getToolDirectory
131
112
  };