@defai.digital/ax-cli 2.3.1 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/.ax-cli/CUSTOM.md +111 -89
  2. package/.ax-cli/index.json +4 -3
  3. package/README.md +43 -16
  4. package/config/prompts.yaml +9 -0
  5. package/config/settings.yaml +2 -0
  6. package/dist/agent/llm-agent.d.ts +17 -0
  7. package/dist/agent/llm-agent.js +151 -52
  8. package/dist/agent/llm-agent.js.map +1 -1
  9. package/dist/commands/init/wizard.d.ts +66 -0
  10. package/dist/commands/init/wizard.js +310 -0
  11. package/dist/commands/init/wizard.js.map +1 -0
  12. package/dist/commands/init.js +145 -31
  13. package/dist/commands/init.js.map +1 -1
  14. package/dist/commands/mcp.js +3 -2
  15. package/dist/commands/mcp.js.map +1 -1
  16. package/dist/commands/memory.d.ts +5 -0
  17. package/dist/commands/memory.js +257 -0
  18. package/dist/commands/memory.js.map +1 -0
  19. package/dist/commands/setup.js +1 -1
  20. package/dist/commands/setup.js.map +1 -1
  21. package/dist/commands/templates.d.ts +5 -0
  22. package/dist/commands/templates.js +244 -0
  23. package/dist/commands/templates.js.map +1 -0
  24. package/dist/commands/update.js +9 -2
  25. package/dist/commands/update.js.map +1 -1
  26. package/dist/commands/usage.js +1 -1
  27. package/dist/commands/usage.js.map +1 -1
  28. package/dist/constants.d.ts +2 -0
  29. package/dist/constants.js +2 -0
  30. package/dist/constants.js.map +1 -1
  31. package/dist/hooks/use-input-handler.js +18 -4
  32. package/dist/hooks/use-input-handler.js.map +1 -1
  33. package/dist/index.js +147 -20
  34. package/dist/index.js.map +1 -1
  35. package/dist/llm/client.d.ts +5 -0
  36. package/dist/llm/client.js +45 -39
  37. package/dist/llm/client.js.map +1 -1
  38. package/dist/schemas/index.d.ts +69 -0
  39. package/dist/schemas/index.js +29 -0
  40. package/dist/schemas/index.js.map +1 -1
  41. package/dist/schemas/yaml-schemas.d.ts +10 -0
  42. package/dist/schemas/yaml-schemas.js +2 -0
  43. package/dist/schemas/yaml-schemas.js.map +1 -1
  44. package/dist/tools/search.js +7 -1
  45. package/dist/tools/search.js.map +1 -1
  46. package/dist/tools/text-editor.js +24 -14
  47. package/dist/tools/text-editor.js.map +1 -1
  48. package/dist/tools/todo-tool.js +62 -21
  49. package/dist/tools/todo-tool.js.map +1 -1
  50. package/dist/types/template.d.ts +53 -0
  51. package/dist/types/template.js +5 -0
  52. package/dist/types/template.js.map +1 -0
  53. package/dist/ui/components/chat-interface.js +5 -1
  54. package/dist/ui/components/chat-interface.js.map +1 -1
  55. package/dist/ui/components/command-suggestions.js +2 -2
  56. package/dist/ui/components/command-suggestions.js.map +1 -1
  57. package/dist/utils/cache.d.ts +1 -0
  58. package/dist/utils/cache.js +39 -5
  59. package/dist/utils/cache.js.map +1 -1
  60. package/dist/utils/config-loader.d.ts +2 -0
  61. package/dist/utils/config-loader.js +2 -1
  62. package/dist/utils/config-loader.js.map +1 -1
  63. package/dist/utils/confirmation-service.js +6 -3
  64. package/dist/utils/confirmation-service.js.map +1 -1
  65. package/dist/utils/error-handler.d.ts +5 -0
  66. package/dist/utils/error-handler.js +9 -3
  67. package/dist/utils/error-handler.js.map +1 -1
  68. package/dist/utils/init-previewer.d.ts +56 -0
  69. package/dist/utils/init-previewer.js +217 -0
  70. package/dist/utils/init-previewer.js.map +1 -0
  71. package/dist/utils/init-validator.d.ts +61 -0
  72. package/dist/utils/init-validator.js +248 -0
  73. package/dist/utils/init-validator.js.map +1 -0
  74. package/dist/utils/onboarding-manager.js +34 -9
  75. package/dist/utils/onboarding-manager.js.map +1 -1
  76. package/dist/utils/path-utils.d.ts +83 -0
  77. package/dist/utils/path-utils.js +122 -0
  78. package/dist/utils/path-utils.js.map +1 -0
  79. package/dist/utils/progress-tracker.d.ts +51 -0
  80. package/dist/utils/progress-tracker.js +152 -0
  81. package/dist/utils/progress-tracker.js.map +1 -0
  82. package/dist/utils/project-analyzer.js +8 -14
  83. package/dist/utils/project-analyzer.js.map +1 -1
  84. package/dist/utils/settings-manager.d.ts +3 -3
  85. package/dist/utils/settings-manager.js +6 -13
  86. package/dist/utils/settings-manager.js.map +1 -1
  87. package/dist/utils/string-utils.d.ts +19 -0
  88. package/dist/utils/string-utils.js +28 -0
  89. package/dist/utils/string-utils.js.map +1 -0
  90. package/dist/utils/template-manager.d.ts +54 -0
  91. package/dist/utils/template-manager.js +421 -0
  92. package/dist/utils/template-manager.js.map +1 -0
  93. package/dist/utils/text-utils.js +3 -1
  94. package/dist/utils/text-utils.js.map +1 -1
  95. package/package.json +2 -1
  96. package/vitest.config.ts +6 -0
  97. package/dist/utils/model-config.d.ts +0 -28
  98. package/dist/utils/model-config.js +0 -43
  99. package/dist/utils/model-config.js.map +0 -1
  100. package/dist/utils/tool-helpers.d.ts +0 -25
  101. package/dist/utils/tool-helpers.js +0 -53
  102. package/dist/utils/tool-helpers.js.map +0 -1
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Validation utilities for init command
3
+ */
4
+ import * as fs from 'fs';
5
+ import * as path from 'path';
6
+ import { parseJson, parseJsonFile } from './json-utils.js';
7
+ export class InitValidator {
8
+ projectRoot;
9
+ constructor(projectRoot) {
10
+ this.projectRoot = projectRoot;
11
+ }
12
+ /**
13
+ * Run all validation checks
14
+ */
15
+ validate(projectInfo) {
16
+ const result = {
17
+ valid: true,
18
+ warnings: [],
19
+ errors: [],
20
+ suggestions: [],
21
+ };
22
+ // Check for package.json
23
+ this.checkPackageJson(result);
24
+ // Check for git repository
25
+ this.checkGitRepo(result);
26
+ // Check for existing AX CLI config
27
+ this.checkExistingConfig(result);
28
+ // Check project structure
29
+ this.checkProjectStructure(result);
30
+ // Check if project has minimum files
31
+ this.checkMinimumFiles(result);
32
+ // Validate project info if provided
33
+ if (projectInfo) {
34
+ this.validateProjectInfo(projectInfo, result);
35
+ }
36
+ // Set overall validity
37
+ result.valid = result.errors.length === 0;
38
+ return result;
39
+ }
40
+ /**
41
+ * Check for package.json
42
+ */
43
+ checkPackageJson(result) {
44
+ const packageJsonPath = path.join(this.projectRoot, 'package.json');
45
+ if (!fs.existsSync(packageJsonPath)) {
46
+ result.warnings.push('No package.json found - may not be a Node.js project');
47
+ result.suggestions.push('Run: npm init (if this is a Node.js project)');
48
+ }
49
+ else {
50
+ try {
51
+ const content = fs.readFileSync(packageJsonPath, 'utf-8');
52
+ // Check for empty file
53
+ if (!content || content.trim() === '') {
54
+ result.errors.push('package.json is empty');
55
+ return;
56
+ }
57
+ const parseResult = parseJson(content);
58
+ if (!parseResult.success) {
59
+ result.errors.push(`Invalid package.json - ${parseResult.error}`);
60
+ return;
61
+ }
62
+ const packageJson = parseResult.data;
63
+ // Check if package.json is actually an object
64
+ if (typeof packageJson !== 'object' || packageJson === null) {
65
+ result.errors.push('package.json is not a valid JSON object');
66
+ return;
67
+ }
68
+ // Check for common issues
69
+ if (!packageJson.name) {
70
+ result.warnings.push('package.json missing "name" field');
71
+ }
72
+ if (!packageJson.version) {
73
+ result.warnings.push('package.json missing "version" field');
74
+ }
75
+ // Check for type: module (ESM)
76
+ if (packageJson.type !== 'module') {
77
+ result.suggestions.push('Consider adding "type": "module" for ESM support');
78
+ }
79
+ }
80
+ catch (error) {
81
+ result.errors.push(`Invalid package.json - ${error instanceof Error ? error.message : 'File read error'}`);
82
+ }
83
+ }
84
+ }
85
+ /**
86
+ * Check for git repository
87
+ */
88
+ checkGitRepo(result) {
89
+ const gitDir = path.join(this.projectRoot, '.git');
90
+ if (!fs.existsSync(gitDir)) {
91
+ result.warnings.push('Not a git repository');
92
+ result.suggestions.push('Run: git init (for version control)');
93
+ }
94
+ }
95
+ /**
96
+ * Check for existing AX CLI configuration
97
+ */
98
+ checkExistingConfig(result) {
99
+ const axCliDir = path.join(this.projectRoot, '.ax-cli');
100
+ const customMdPath = path.join(axCliDir, 'CUSTOM.md');
101
+ const indexPath = path.join(axCliDir, 'index.json');
102
+ if (fs.existsSync(customMdPath)) {
103
+ result.warnings.push('Existing CUSTOM.md found - will be overwritten unless --force is used');
104
+ }
105
+ if (fs.existsSync(indexPath)) {
106
+ const parseResult = parseJsonFile(indexPath);
107
+ if (parseResult.success) {
108
+ const indexData = parseResult.data;
109
+ const lastUpdated = indexData.lastAnalyzed || indexData.templateAppliedAt;
110
+ if (lastUpdated) {
111
+ const date = new Date(lastUpdated);
112
+ const daysSince = Math.floor((Date.now() - date.getTime()) / (1000 * 60 * 60 * 24));
113
+ if (daysSince > 30) {
114
+ result.suggestions.push(`CUSTOM.md is ${daysSince} days old - consider refreshing`);
115
+ }
116
+ }
117
+ }
118
+ else {
119
+ result.warnings.push('Existing index.json is invalid');
120
+ }
121
+ }
122
+ }
123
+ /**
124
+ * Check project structure
125
+ */
126
+ checkProjectStructure(result) {
127
+ const commonDirs = ['src', 'lib', 'dist', 'build', 'test', 'tests', '__tests__'];
128
+ const foundDirs = commonDirs.filter(dir => fs.existsSync(path.join(this.projectRoot, dir)));
129
+ if (foundDirs.length === 0) {
130
+ result.warnings.push('No standard project directories found (src/, lib/, etc.)');
131
+ result.suggestions.push('Project may be empty or have non-standard structure');
132
+ }
133
+ }
134
+ /**
135
+ * Check for minimum files
136
+ */
137
+ checkMinimumFiles(result) {
138
+ try {
139
+ const files = fs.readdirSync(this.projectRoot);
140
+ const nonHiddenFiles = files.filter(f => !f.startsWith('.'));
141
+ if (nonHiddenFiles.length === 0) {
142
+ result.errors.push('Project directory is empty');
143
+ return;
144
+ }
145
+ if (nonHiddenFiles.length === 1 && nonHiddenFiles[0] === 'package.json') {
146
+ result.warnings.push('Project only contains package.json - no source files found');
147
+ result.suggestions.push('Add source files before initializing AX CLI');
148
+ }
149
+ }
150
+ catch (error) {
151
+ result.errors.push(`Cannot read project directory: ${error instanceof Error ? error.message : 'Unknown error'}`);
152
+ }
153
+ }
154
+ /**
155
+ * Validate project info
156
+ */
157
+ validateProjectInfo(projectInfo, result) {
158
+ // Check if project type was detected
159
+ if (projectInfo.projectType === 'unknown' || projectInfo.projectType === 'application') {
160
+ result.warnings.push('Could not determine specific project type');
161
+ result.suggestions.push('Consider using a template: ax-cli init --template <type>');
162
+ }
163
+ // Check if primary language was detected
164
+ if (projectInfo.primaryLanguage === 'Unknown') {
165
+ result.warnings.push('Could not determine primary programming language');
166
+ }
167
+ // Check if tech stack was detected
168
+ if (projectInfo.techStack.length === 0) {
169
+ result.warnings.push('No tech stack detected');
170
+ result.suggestions.push('Ensure package.json has dependencies listed');
171
+ }
172
+ // Check entry point
173
+ if (!projectInfo.entryPoint) {
174
+ result.warnings.push('No entry point detected');
175
+ }
176
+ }
177
+ /**
178
+ * Validate custom instructions content
179
+ */
180
+ static validateCustomInstructions(content) {
181
+ const result = {
182
+ valid: true,
183
+ warnings: [],
184
+ errors: [],
185
+ suggestions: [],
186
+ };
187
+ // Check minimum length
188
+ if (content.length < 100) {
189
+ result.errors.push('CUSTOM.md is too short (< 100 characters)');
190
+ }
191
+ // Check for required sections
192
+ const requiredSections = [
193
+ '## 🎯 Critical Rules',
194
+ '## 📋 Project Overview',
195
+ '## 🔧 Code Patterns',
196
+ ];
197
+ for (const section of requiredSections) {
198
+ if (!content.includes(section)) {
199
+ result.warnings.push(`Missing recommended section: ${section}`);
200
+ }
201
+ }
202
+ // Check token count (rough estimate)
203
+ const estimatedTokens = Math.ceil(content.length / 4);
204
+ if (estimatedTokens > 2000) {
205
+ result.warnings.push(`CUSTOM.md is large (~${estimatedTokens} tokens)`);
206
+ result.suggestions.push('Consider using template imports or reducing content');
207
+ }
208
+ // Check for common issues
209
+ if (content.includes('TODO') || content.includes('FIXME')) {
210
+ result.warnings.push('CUSTOM.md contains TODO/FIXME markers');
211
+ }
212
+ if (content.includes('__placeholder__') || content.includes('<insert')) {
213
+ result.errors.push('CUSTOM.md contains placeholder text');
214
+ }
215
+ result.valid = result.errors.length === 0;
216
+ return result;
217
+ }
218
+ /**
219
+ * Check if force flag is needed
220
+ */
221
+ needsForceFlag() {
222
+ const customMdPath = path.join(this.projectRoot, '.ax-cli', 'CUSTOM.md');
223
+ return fs.existsSync(customMdPath);
224
+ }
225
+ /**
226
+ * Get validation summary string
227
+ */
228
+ static formatValidationResult(result) {
229
+ const parts = [];
230
+ if (result.errors.length > 0) {
231
+ parts.push('❌ Errors:');
232
+ result.errors.forEach(e => parts.push(` - ${e}`));
233
+ }
234
+ if (result.warnings.length > 0) {
235
+ parts.push('⚠️ Warnings:');
236
+ result.warnings.forEach(w => parts.push(` - ${w}`));
237
+ }
238
+ if (result.suggestions.length > 0) {
239
+ parts.push('💡 Suggestions:');
240
+ result.suggestions.forEach(s => parts.push(` - ${s}`));
241
+ }
242
+ if (result.valid && result.warnings.length === 0 && result.suggestions.length === 0) {
243
+ parts.push('✅ All validation checks passed');
244
+ }
245
+ return parts.join('\n');
246
+ }
247
+ }
248
+ //# sourceMappingURL=init-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-validator.js","sourceRoot":"","sources":["../../src/utils/init-validator.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,8 @@
4
4
  import * as fs from 'fs';
5
5
  import * as path from 'path';
6
6
  import * as os from 'os';
7
+ import { fileURLToPath } from 'url';
8
+ import { parseJsonFile } from './json-utils.js';
7
9
  export class OnboardingManager {
8
10
  static FIRST_RUN_MARKER = '.first-run-complete';
9
11
  static USER_CONFIG_DIR = '.ax-cli';
@@ -43,7 +45,24 @@ export class OnboardingManager {
43
45
  completedAt: new Date().toISOString(),
44
46
  version: this.getVersion(),
45
47
  };
46
- fs.writeFileSync(markerPath, JSON.stringify(state, null, 2), 'utf-8');
48
+ // Atomic write using temp file
49
+ const tmpPath = `${markerPath}.tmp`;
50
+ try {
51
+ fs.writeFileSync(tmpPath, JSON.stringify(state, null, 2), 'utf-8');
52
+ fs.renameSync(tmpPath, markerPath); // Atomic on POSIX systems
53
+ }
54
+ catch (error) {
55
+ // Cleanup temp file on error
56
+ if (fs.existsSync(tmpPath)) {
57
+ try {
58
+ fs.unlinkSync(tmpPath);
59
+ }
60
+ catch {
61
+ // Ignore cleanup errors
62
+ }
63
+ }
64
+ throw error;
65
+ }
47
66
  }
48
67
  /**
49
68
  * Get current onboarding state
@@ -57,11 +76,8 @@ export class OnboardingManager {
57
76
  version: this.getVersion(),
58
77
  };
59
78
  }
60
- try {
61
- const content = fs.readFileSync(markerPath, 'utf-8');
62
- return JSON.parse(content);
63
- }
64
- catch {
79
+ const parseResult = parseJsonFile(markerPath);
80
+ if (!parseResult.success) {
65
81
  // If marker file is corrupted, treat as first run
66
82
  return {
67
83
  isFirstRun: true,
@@ -69,6 +85,7 @@ export class OnboardingManager {
69
85
  version: this.getVersion(),
70
86
  };
71
87
  }
88
+ return parseResult.data;
72
89
  }
73
90
  /**
74
91
  * Reset onboarding state (useful for testing)
@@ -90,10 +107,18 @@ export class OnboardingManager {
90
107
  */
91
108
  static getVersion() {
92
109
  try {
93
- const packageJsonPath = path.join(process.cwd(), 'package.json');
110
+ // Use import.meta.url to find the actual CLI installation path
111
+ const currentModulePath = fileURLToPath(import.meta.url);
112
+ const cliRootPath = path.join(path.dirname(currentModulePath), '../..');
113
+ const packageJsonPath = path.join(cliRootPath, 'package.json');
94
114
  if (fs.existsSync(packageJsonPath)) {
95
- const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
96
- return pkg.version || '0.0.0';
115
+ const parseResult = parseJsonFile(packageJsonPath);
116
+ if (parseResult.success) {
117
+ const pkg = parseResult.data;
118
+ if (pkg && typeof pkg === 'object' && 'version' in pkg && typeof pkg.version === 'string') {
119
+ return pkg.version;
120
+ }
121
+ }
97
122
  }
98
123
  }
99
124
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding-manager.js","sourceRoot":"","sources":["../../src/utils/onboarding-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"onboarding-manager.js","sourceRoot":"","sources":["../../src/utils/onboarding-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Cross-platform path utility functions
3
+ *
4
+ * This module provides utilities for handling file paths consistently
5
+ * across different operating systems (Windows, macOS, Linux).
6
+ *
7
+ * @module path-utils
8
+ */
9
+ /**
10
+ * Normalize path separators to forward slashes (for display and logging)
11
+ *
12
+ * This function converts all path separators to forward slashes, which is
13
+ * useful for consistent display across platforms and for comparison in tests.
14
+ *
15
+ * @example
16
+ * // Windows
17
+ * normalizePath('C:\\Users\\foo\\bar') // => 'C:/Users/foo/bar'
18
+ *
19
+ * // Unix
20
+ * normalizePath('/Users/foo/bar') // => '/Users/foo/bar'
21
+ *
22
+ * @param filePath - The path to normalize
23
+ * @returns Path with forward slashes (empty string if input is falsy)
24
+ */
25
+ export declare function normalizePath(filePath: string): string;
26
+ /**
27
+ * Convert path to platform-native format (for filesystem operations)
28
+ *
29
+ * This function normalizes the path to use the platform's native separator,
30
+ * which is necessary for filesystem operations.
31
+ *
32
+ * @example
33
+ * // Windows
34
+ * platformPath('foo/bar/baz') // => 'foo\\bar\\baz'
35
+ *
36
+ * // Unix
37
+ * platformPath('foo/bar/baz') // => 'foo/bar/baz'
38
+ *
39
+ * @param filePath - The path to convert
40
+ * @returns Path with platform-native separators (empty string if input is falsy)
41
+ */
42
+ export declare function platformPath(filePath: string): string;
43
+ /**
44
+ * Check if running on Windows
45
+ *
46
+ * @returns True if running on Windows platform
47
+ */
48
+ export declare function isWindows(): boolean;
49
+ /**
50
+ * Compare two paths for equality (ignoring separator differences)
51
+ *
52
+ * This function compares two paths by normalizing both to forward slashes
53
+ * and then comparing case-insensitively on Windows.
54
+ *
55
+ * @example
56
+ * // Windows
57
+ * pathsEqual('foo/bar', 'foo\\bar') // => true
58
+ * pathsEqual('Foo/Bar', 'foo/bar') // => true
59
+ *
60
+ * // Unix
61
+ * pathsEqual('foo/bar', 'foo/bar') // => true
62
+ * pathsEqual('Foo/Bar', 'foo/bar') // => false
63
+ *
64
+ * @param path1 - First path to compare
65
+ * @param path2 - Second path to compare
66
+ * @returns True if paths are equal
67
+ */
68
+ export declare function pathsEqual(path1: string, path2: string): boolean;
69
+ /**
70
+ * Check if a path contains a segment (cross-platform)
71
+ *
72
+ * This function checks if a full path contains a specific segment,
73
+ * normalizing both paths before comparison.
74
+ *
75
+ * @example
76
+ * pathContains('/foo/bar/baz', 'bar/baz') // => true
77
+ * pathContains('C:\\foo\\bar', 'bar') // => true
78
+ *
79
+ * @param fullPath - Full path to search in
80
+ * @param segment - Segment to search for
81
+ * @returns True if fullPath contains segment
82
+ */
83
+ export declare function pathContains(fullPath: string, segment: string): boolean;
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Cross-platform path utility functions
3
+ *
4
+ * This module provides utilities for handling file paths consistently
5
+ * across different operating systems (Windows, macOS, Linux).
6
+ *
7
+ * @module path-utils
8
+ */
9
+ import path from 'node:path';
10
+ import os from 'node:os';
11
+ import { equalsIgnoreCase, containsIgnoreCase } from './string-utils.js';
12
+ /**
13
+ * Normalize path separators to forward slashes (for display and logging)
14
+ *
15
+ * This function converts all path separators to forward slashes, which is
16
+ * useful for consistent display across platforms and for comparison in tests.
17
+ *
18
+ * @example
19
+ * // Windows
20
+ * normalizePath('C:\\Users\\foo\\bar') // => 'C:/Users/foo/bar'
21
+ *
22
+ * // Unix
23
+ * normalizePath('/Users/foo/bar') // => '/Users/foo/bar'
24
+ *
25
+ * @param filePath - The path to normalize
26
+ * @returns Path with forward slashes (empty string if input is falsy)
27
+ */
28
+ export function normalizePath(filePath) {
29
+ if (!filePath)
30
+ return '';
31
+ // Replace all backslashes with forward slashes
32
+ // This works consistently across all platforms
33
+ return filePath.replace(/\\/g, '/');
34
+ }
35
+ /**
36
+ * Convert path to platform-native format (for filesystem operations)
37
+ *
38
+ * This function normalizes the path to use the platform's native separator,
39
+ * which is necessary for filesystem operations.
40
+ *
41
+ * @example
42
+ * // Windows
43
+ * platformPath('foo/bar/baz') // => 'foo\\bar\\baz'
44
+ *
45
+ * // Unix
46
+ * platformPath('foo/bar/baz') // => 'foo/bar/baz'
47
+ *
48
+ * @param filePath - The path to convert
49
+ * @returns Path with platform-native separators (empty string if input is falsy)
50
+ */
51
+ export function platformPath(filePath) {
52
+ if (!filePath)
53
+ return '';
54
+ return path.normalize(filePath);
55
+ }
56
+ /**
57
+ * Check if running on Windows
58
+ *
59
+ * @returns True if running on Windows platform
60
+ */
61
+ export function isWindows() {
62
+ return os.platform() === 'win32';
63
+ }
64
+ /**
65
+ * Compare two paths for equality (ignoring separator differences)
66
+ *
67
+ * This function compares two paths by normalizing both to forward slashes
68
+ * and then comparing case-insensitively on Windows.
69
+ *
70
+ * @example
71
+ * // Windows
72
+ * pathsEqual('foo/bar', 'foo\\bar') // => true
73
+ * pathsEqual('Foo/Bar', 'foo/bar') // => true
74
+ *
75
+ * // Unix
76
+ * pathsEqual('foo/bar', 'foo/bar') // => true
77
+ * pathsEqual('Foo/Bar', 'foo/bar') // => false
78
+ *
79
+ * @param path1 - First path to compare
80
+ * @param path2 - Second path to compare
81
+ * @returns True if paths are equal
82
+ */
83
+ export function pathsEqual(path1, path2) {
84
+ // Handle null/undefined/empty cases
85
+ if (!path1 || !path2) {
86
+ return path1 === path2;
87
+ }
88
+ const normalized1 = normalizePath(path1);
89
+ const normalized2 = normalizePath(path2);
90
+ // Windows is case-insensitive
91
+ if (isWindows()) {
92
+ return equalsIgnoreCase(normalized1, normalized2);
93
+ }
94
+ return normalized1 === normalized2;
95
+ }
96
+ /**
97
+ * Check if a path contains a segment (cross-platform)
98
+ *
99
+ * This function checks if a full path contains a specific segment,
100
+ * normalizing both paths before comparison.
101
+ *
102
+ * @example
103
+ * pathContains('/foo/bar/baz', 'bar/baz') // => true
104
+ * pathContains('C:\\foo\\bar', 'bar') // => true
105
+ *
106
+ * @param fullPath - Full path to search in
107
+ * @param segment - Segment to search for
108
+ * @returns True if fullPath contains segment
109
+ */
110
+ export function pathContains(fullPath, segment) {
111
+ if (!fullPath || !segment) {
112
+ return false;
113
+ }
114
+ const normalizedFull = normalizePath(fullPath);
115
+ const normalizedSegment = normalizePath(segment);
116
+ // Windows is case-insensitive
117
+ if (isWindows()) {
118
+ return containsIgnoreCase(normalizedFull, normalizedSegment);
119
+ }
120
+ return normalizedFull.includes(normalizedSegment);
121
+ }
122
+ //# sourceMappingURL=path-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/utils/path-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEzE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IACzB,+CAA+C;IAC/C,+CAA+C;IAC/C,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IACzB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,KAAa;IACrD,oCAAoC;IACpC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,KAAK,KAAK,KAAK,CAAC;IACzB,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEzC,8BAA8B;IAC9B,IAAI,SAAS,EAAE,EAAE,CAAC;QAChB,OAAO,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,WAAW,KAAK,WAAW,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,OAAe;IAC5D,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,iBAAiB,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAEjD,8BAA8B;IAC9B,IAAI,SAAS,EAAE,EAAE,CAAC;QAChB,OAAO,kBAAkB,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,cAAc,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Progress tracking utility for init command
3
+ */
4
+ export interface ProgressStep {
5
+ name: string;
6
+ status: 'pending' | 'in_progress' | 'completed' | 'failed';
7
+ startTime?: number;
8
+ endTime?: number;
9
+ details?: string;
10
+ }
11
+ export declare class ProgressTracker {
12
+ private steps;
13
+ private spinner?;
14
+ private currentStep?;
15
+ /**
16
+ * Add a step to track
17
+ */
18
+ addStep(id: string, name: string): void;
19
+ /**
20
+ * Start a step
21
+ */
22
+ startStep(id: string, message?: string): Promise<void>;
23
+ /**
24
+ * Complete a step
25
+ */
26
+ completeStep(id: string, details?: string): Promise<void>;
27
+ /**
28
+ * Fail a step
29
+ */
30
+ failStep(id: string, error: string): Promise<void>;
31
+ /**
32
+ * Update step message
33
+ */
34
+ updateMessage(message: string): void;
35
+ /**
36
+ * Format duration in human-readable form
37
+ */
38
+ private formatDuration;
39
+ /**
40
+ * Get summary of all steps
41
+ */
42
+ getSummary(): string;
43
+ /**
44
+ * Stop any active spinner
45
+ */
46
+ stop(): void;
47
+ /**
48
+ * Cleanup and destroy tracker
49
+ */
50
+ destroy(): void;
51
+ }