@wundr.io/cli 1.0.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.
Files changed (213) hide show
  1. package/README.md +551 -0
  2. package/bin/wundr.js +39 -0
  3. package/dist/ai/ai-service.d.ts +152 -0
  4. package/dist/ai/ai-service.d.ts.map +1 -0
  5. package/dist/ai/ai-service.js +430 -0
  6. package/dist/ai/ai-service.js.map +1 -0
  7. package/dist/ai/claude-client.d.ts +130 -0
  8. package/dist/ai/claude-client.d.ts.map +1 -0
  9. package/dist/ai/claude-client.js +339 -0
  10. package/dist/ai/claude-client.js.map +1 -0
  11. package/dist/ai/conversation-manager.d.ts +164 -0
  12. package/dist/ai/conversation-manager.d.ts.map +1 -0
  13. package/dist/ai/conversation-manager.js +612 -0
  14. package/dist/ai/conversation-manager.js.map +1 -0
  15. package/dist/ai/index.d.ts +5 -0
  16. package/dist/ai/index.d.ts.map +1 -0
  17. package/dist/ai/index.js +8 -0
  18. package/dist/ai/index.js.map +1 -0
  19. package/dist/cli.d.ts +36 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +173 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/commands/ai.d.ts +89 -0
  24. package/dist/commands/ai.d.ts.map +1 -0
  25. package/dist/commands/ai.js +735 -0
  26. package/dist/commands/ai.js.map +1 -0
  27. package/dist/commands/analyze-optimized.d.ts +14 -0
  28. package/dist/commands/analyze-optimized.d.ts.map +1 -0
  29. package/dist/commands/analyze-optimized.js +437 -0
  30. package/dist/commands/analyze-optimized.js.map +1 -0
  31. package/dist/commands/analyze.d.ts +65 -0
  32. package/dist/commands/analyze.d.ts.map +1 -0
  33. package/dist/commands/analyze.js +435 -0
  34. package/dist/commands/analyze.js.map +1 -0
  35. package/dist/commands/batch.d.ts +71 -0
  36. package/dist/commands/batch.d.ts.map +1 -0
  37. package/dist/commands/batch.js +738 -0
  38. package/dist/commands/batch.js.map +1 -0
  39. package/dist/commands/chat.d.ts +71 -0
  40. package/dist/commands/chat.d.ts.map +1 -0
  41. package/dist/commands/chat.js +674 -0
  42. package/dist/commands/chat.js.map +1 -0
  43. package/dist/commands/claude-init.d.ts +28 -0
  44. package/dist/commands/claude-init.d.ts.map +1 -0
  45. package/dist/commands/claude-init.js +587 -0
  46. package/dist/commands/claude-init.js.map +1 -0
  47. package/dist/commands/claude-setup.d.ts +32 -0
  48. package/dist/commands/claude-setup.d.ts.map +1 -0
  49. package/dist/commands/claude-setup.js +570 -0
  50. package/dist/commands/claude-setup.js.map +1 -0
  51. package/dist/commands/computer-setup-commands.d.ts +39 -0
  52. package/dist/commands/computer-setup-commands.d.ts.map +1 -0
  53. package/dist/commands/computer-setup-commands.js +563 -0
  54. package/dist/commands/computer-setup-commands.js.map +1 -0
  55. package/dist/commands/computer-setup.d.ts +7 -0
  56. package/dist/commands/computer-setup.d.ts.map +1 -0
  57. package/dist/commands/computer-setup.js +481 -0
  58. package/dist/commands/computer-setup.js.map +1 -0
  59. package/dist/commands/create-command.d.ts +7 -0
  60. package/dist/commands/create-command.d.ts.map +1 -0
  61. package/dist/commands/create-command.js +158 -0
  62. package/dist/commands/create-command.js.map +1 -0
  63. package/dist/commands/create.d.ts +74 -0
  64. package/dist/commands/create.d.ts.map +1 -0
  65. package/dist/commands/create.js +556 -0
  66. package/dist/commands/create.js.map +1 -0
  67. package/dist/commands/dashboard.d.ts +91 -0
  68. package/dist/commands/dashboard.d.ts.map +1 -0
  69. package/dist/commands/dashboard.js +537 -0
  70. package/dist/commands/dashboard.js.map +1 -0
  71. package/dist/commands/govern.d.ts +70 -0
  72. package/dist/commands/govern.d.ts.map +1 -0
  73. package/dist/commands/govern.js +480 -0
  74. package/dist/commands/govern.js.map +1 -0
  75. package/dist/commands/init.d.ts +55 -0
  76. package/dist/commands/init.d.ts.map +1 -0
  77. package/dist/commands/init.js +584 -0
  78. package/dist/commands/init.js.map +1 -0
  79. package/dist/commands/performance-optimizer.d.ts +30 -0
  80. package/dist/commands/performance-optimizer.d.ts.map +1 -0
  81. package/dist/commands/performance-optimizer.js +649 -0
  82. package/dist/commands/performance-optimizer.js.map +1 -0
  83. package/dist/commands/plugins.d.ts +87 -0
  84. package/dist/commands/plugins.d.ts.map +1 -0
  85. package/dist/commands/plugins.js +685 -0
  86. package/dist/commands/plugins.js.map +1 -0
  87. package/dist/commands/setup.d.ts +29 -0
  88. package/dist/commands/setup.d.ts.map +1 -0
  89. package/dist/commands/setup.js +399 -0
  90. package/dist/commands/setup.js.map +1 -0
  91. package/dist/commands/test-init.d.ts +9 -0
  92. package/dist/commands/test-init.d.ts.map +1 -0
  93. package/dist/commands/test-init.js +222 -0
  94. package/dist/commands/test-init.js.map +1 -0
  95. package/dist/commands/test.d.ts +25 -0
  96. package/dist/commands/test.d.ts.map +1 -0
  97. package/dist/commands/test.js +217 -0
  98. package/dist/commands/test.js.map +1 -0
  99. package/dist/commands/watch.d.ts +76 -0
  100. package/dist/commands/watch.d.ts.map +1 -0
  101. package/dist/commands/watch.js +610 -0
  102. package/dist/commands/watch.js.map +1 -0
  103. package/dist/context/context-manager.d.ts +155 -0
  104. package/dist/context/context-manager.d.ts.map +1 -0
  105. package/dist/context/context-manager.js +383 -0
  106. package/dist/context/context-manager.js.map +1 -0
  107. package/dist/context/index.d.ts +3 -0
  108. package/dist/context/index.d.ts.map +1 -0
  109. package/dist/context/index.js +6 -0
  110. package/dist/context/index.js.map +1 -0
  111. package/dist/context/session-manager.d.ts +207 -0
  112. package/dist/context/session-manager.d.ts.map +1 -0
  113. package/dist/context/session-manager.js +682 -0
  114. package/dist/context/session-manager.js.map +1 -0
  115. package/dist/index.d.ts +8 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +51 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/interactive/interactive-mode.d.ts +76 -0
  120. package/dist/interactive/interactive-mode.d.ts.map +1 -0
  121. package/dist/interactive/interactive-mode.js +730 -0
  122. package/dist/interactive/interactive-mode.js.map +1 -0
  123. package/dist/nlp/command-mapper.d.ts +174 -0
  124. package/dist/nlp/command-mapper.d.ts.map +1 -0
  125. package/dist/nlp/command-mapper.js +623 -0
  126. package/dist/nlp/command-mapper.js.map +1 -0
  127. package/dist/nlp/command-parser.d.ts +106 -0
  128. package/dist/nlp/command-parser.d.ts.map +1 -0
  129. package/dist/nlp/command-parser.js +416 -0
  130. package/dist/nlp/command-parser.js.map +1 -0
  131. package/dist/nlp/index.d.ts +5 -0
  132. package/dist/nlp/index.d.ts.map +1 -0
  133. package/dist/nlp/index.js +8 -0
  134. package/dist/nlp/index.js.map +1 -0
  135. package/dist/nlp/intent-classifier.d.ts +59 -0
  136. package/dist/nlp/intent-classifier.d.ts.map +1 -0
  137. package/dist/nlp/intent-classifier.js +384 -0
  138. package/dist/nlp/intent-classifier.js.map +1 -0
  139. package/dist/nlp/intent-parser.d.ts +152 -0
  140. package/dist/nlp/intent-parser.d.ts.map +1 -0
  141. package/dist/nlp/intent-parser.js +739 -0
  142. package/dist/nlp/intent-parser.js.map +1 -0
  143. package/dist/plugins/plugin-manager.d.ts +120 -0
  144. package/dist/plugins/plugin-manager.d.ts.map +1 -0
  145. package/dist/plugins/plugin-manager.js +595 -0
  146. package/dist/plugins/plugin-manager.js.map +1 -0
  147. package/dist/types/index.d.ts +224 -0
  148. package/dist/types/index.d.ts.map +1 -0
  149. package/dist/types/index.js +3 -0
  150. package/dist/types/index.js.map +1 -0
  151. package/dist/utils/config-manager.d.ts +73 -0
  152. package/dist/utils/config-manager.d.ts.map +1 -0
  153. package/dist/utils/config-manager.js +339 -0
  154. package/dist/utils/config-manager.js.map +1 -0
  155. package/dist/utils/error-handler.d.ts +46 -0
  156. package/dist/utils/error-handler.d.ts.map +1 -0
  157. package/dist/utils/error-handler.js +169 -0
  158. package/dist/utils/error-handler.js.map +1 -0
  159. package/dist/utils/logger.d.ts +25 -0
  160. package/dist/utils/logger.d.ts.map +1 -0
  161. package/dist/utils/logger.js +94 -0
  162. package/dist/utils/logger.js.map +1 -0
  163. package/package.json +119 -0
  164. package/src/ai/ai-service.ts +595 -0
  165. package/src/ai/claude-client.ts +490 -0
  166. package/src/ai/conversation-manager.ts +907 -0
  167. package/src/ai/index.ts +8 -0
  168. package/src/cli.ts +202 -0
  169. package/src/commands/ai.ts +995 -0
  170. package/src/commands/analyze-optimized.ts +641 -0
  171. package/src/commands/analyze.ts +576 -0
  172. package/src/commands/batch.ts +935 -0
  173. package/src/commands/chat.ts +876 -0
  174. package/src/commands/claude-init.ts +715 -0
  175. package/src/commands/claude-setup.ts +697 -0
  176. package/src/commands/computer-setup-commands.ts +709 -0
  177. package/src/commands/computer-setup.ts +565 -0
  178. package/src/commands/create-command.ts +175 -0
  179. package/src/commands/create.ts +727 -0
  180. package/src/commands/dashboard.ts +691 -0
  181. package/src/commands/govern.ts +635 -0
  182. package/src/commands/init.ts +677 -0
  183. package/src/commands/performance-optimizer.ts +864 -0
  184. package/src/commands/plugins.ts +848 -0
  185. package/src/commands/setup.ts +508 -0
  186. package/src/commands/test-init.ts +242 -0
  187. package/src/commands/test.ts +264 -0
  188. package/src/commands/watch.ts +755 -0
  189. package/src/context/context-manager.ts +546 -0
  190. package/src/context/index.ts +9 -0
  191. package/src/context/session-manager.ts +1019 -0
  192. package/src/index.ts +64 -0
  193. package/src/interactive/interactive-mode.ts +830 -0
  194. package/src/nlp/command-mapper.ts +885 -0
  195. package/src/nlp/command-parser.ts +564 -0
  196. package/src/nlp/index.ts +4 -0
  197. package/src/nlp/intent-classifier.ts +458 -0
  198. package/src/nlp/intent-parser.ts +1101 -0
  199. package/src/plugins/plugin-manager.ts +744 -0
  200. package/src/types/index.ts +252 -0
  201. package/src/types/modules.d.ts +56 -0
  202. package/src/utils/config-manager.ts +391 -0
  203. package/src/utils/error-handler.ts +192 -0
  204. package/src/utils/logger.ts +104 -0
  205. package/templates/batch/ci-cd.yaml +62 -0
  206. package/templates/component/{{fileName}}.test.tsx +17 -0
  207. package/templates/component/{{fileName}}.tsx +21 -0
  208. package/templates/service/{{fileName}}.ts +98 -0
  209. package/templates/wundr-test.config.js +0 -0
  210. package/test-suites/api/health.spec.ts +134 -0
  211. package/test-suites/helpers/test-config.ts +84 -0
  212. package/test-suites/ui/accessibility.spec.ts +102 -0
  213. package/test-suites/ui/smoke.spec.ts +92 -0
@@ -0,0 +1,508 @@
1
+ /**
2
+ * Simple Setup Commands - Main setup entry points
3
+ * Provides the primary wundr setup commands that integrate with computer-setup
4
+ */
5
+
6
+ import { Command } from 'commander';
7
+ import chalk from 'chalk';
8
+ import ora from 'ora';
9
+ import inquirer from 'inquirer';
10
+ import { ConfigManager } from '../utils/config-manager';
11
+ import { PluginManager } from '../plugins/plugin-manager';
12
+ import { logger } from '../utils/logger';
13
+ // Note: Using relative path import due to workspace resolution issues in this monorepo setup
14
+ // The computer-setup package must be built first before building this CLI package
15
+ import {
16
+ SetupPlatform,
17
+ SetupProgress,
18
+ SetupResult,
19
+ RealSetupOrchestrator,
20
+ } from '../../../computer-setup/dist';
21
+
22
+ export class SetupCommands {
23
+ private orchestrator: RealSetupOrchestrator;
24
+ private platform: SetupPlatform;
25
+
26
+ constructor(
27
+ private program: Command,
28
+ private configManager: ConfigManager,
29
+ private pluginManager: PluginManager
30
+ ) {
31
+ this.platform = this.detectPlatform();
32
+ this.orchestrator = new RealSetupOrchestrator(this.platform);
33
+ this.registerCommands();
34
+ }
35
+
36
+ private registerCommands(): void {
37
+ // Main setup command (wundr setup)
38
+ this.program
39
+ .command('setup')
40
+ .description('Set up developer machine with required tools')
41
+ .option(
42
+ '-p, --profile <profile>',
43
+ 'Use specific profile (frontend, backend, fullstack, devops)',
44
+ 'fullstack'
45
+ )
46
+ .option(
47
+ '--dry-run',
48
+ 'Show what would be installed without making changes'
49
+ )
50
+ .option('--interactive', 'Run in interactive mode')
51
+ .action(async options => {
52
+ await this.runSetup(options);
53
+ });
54
+
55
+ // Setup with specific profile (wundr setup:profile frontend)
56
+ const setupProfile = this.program
57
+ .command('setup:profile')
58
+ .description('Set up using a specific developer profile');
59
+
60
+ setupProfile
61
+ .command('frontend')
62
+ .description('Set up frontend development environment')
63
+ .action(async () => {
64
+ await this.runSetup({ profile: 'frontend' });
65
+ });
66
+
67
+ setupProfile
68
+ .command('backend')
69
+ .description('Set up backend development environment')
70
+ .action(async () => {
71
+ await this.runSetup({ profile: 'backend' });
72
+ });
73
+
74
+ setupProfile
75
+ .command('fullstack')
76
+ .description('Set up full-stack development environment')
77
+ .action(async () => {
78
+ await this.runSetup({ profile: 'fullstack' });
79
+ });
80
+
81
+ setupProfile
82
+ .command('devops')
83
+ .description('Set up DevOps engineering environment')
84
+ .action(async () => {
85
+ await this.runSetup({ profile: 'devops' });
86
+ });
87
+
88
+ // Validate setup (wundr setup:validate)
89
+ this.program
90
+ .command('setup:validate')
91
+ .description('Validate current development environment setup')
92
+ .option('--profile <profile>', 'Validate against specific profile')
93
+ .option('--fix', 'Attempt to fix issues found')
94
+ .action(async options => {
95
+ await this.validateSetup(options);
96
+ });
97
+
98
+ // Resume setup (wundr setup:resume)
99
+ this.program
100
+ .command('setup:resume')
101
+ .description('Resume interrupted setup from saved state')
102
+ .action(async () => {
103
+ await this.resumeSetup();
104
+ });
105
+
106
+ // Personalize setup (wundr setup:personalize)
107
+ this.program
108
+ .command('setup:personalize')
109
+ .description('Run personalization and configuration')
110
+ .action(async () => {
111
+ await this.personalizeSetup();
112
+ });
113
+ }
114
+
115
+ private async runSetup(options: any): Promise<void> {
116
+ console.log(chalk.cyan('\n🚀 Wundr Development Environment Setup'));
117
+ console.log(chalk.gray('Setting up your development machine...\n'));
118
+
119
+ try {
120
+ // Check for resumable setup
121
+ const canResume = await this.orchestrator.canResume();
122
+ if (canResume && !options.dryRun) {
123
+ const { resume } = await inquirer.prompt([
124
+ {
125
+ type: 'confirm',
126
+ name: 'resume',
127
+ message: 'Found incomplete setup. Resume from where you left off?',
128
+ default: true,
129
+ },
130
+ ]);
131
+
132
+ if (resume) {
133
+ return await this.resumeSetup();
134
+ }
135
+ }
136
+
137
+ // Get profile
138
+ let profileName = options.profile;
139
+ if (options.interactive && !profileName) {
140
+ profileName = await this.selectProfile();
141
+ }
142
+
143
+ // Validate profile
144
+ const availableProfiles = this.orchestrator.getAvailableProfiles();
145
+
146
+ // Try different matching strategies
147
+ let profile = availableProfiles.find(
148
+ p => p.name.toLowerCase() === profileName.toLowerCase()
149
+ );
150
+
151
+ if (!profile) {
152
+ // Try partial match
153
+ profile = availableProfiles.find(
154
+ p =>
155
+ p.name.toLowerCase().includes(profileName.toLowerCase()) ||
156
+ profileName
157
+ .toLowerCase()
158
+ .includes(p.name.toLowerCase().split(' ')[0])
159
+ );
160
+ }
161
+
162
+ // Map common aliases
163
+ if (!profile) {
164
+ const aliases: Record<string, string> = {
165
+ fullstack: 'Full Stack Developer',
166
+ 'full-stack': 'Full Stack Developer',
167
+ frontend: 'Frontend Developer',
168
+ backend: 'Backend Developer',
169
+ devops: 'DevOps Engineer',
170
+ };
171
+
172
+ const mappedName = aliases[profileName.toLowerCase()];
173
+ if (mappedName) {
174
+ profile = availableProfiles.find(p => p.name === mappedName);
175
+ }
176
+ }
177
+
178
+ if (!profile) {
179
+ console.error(chalk.red(`❌ Unknown profile: ${profileName}`));
180
+ console.log(chalk.cyan('\n📋 Available profiles:'));
181
+ availableProfiles.forEach(p =>
182
+ console.log(
183
+ ` • ${chalk.white(p.name)}: ${chalk.gray(p.description)}`
184
+ )
185
+ );
186
+ return;
187
+ }
188
+
189
+ console.log(
190
+ chalk.cyan(`\n📋 Selected Profile: ${chalk.white(profile.name)}`)
191
+ );
192
+ console.log(chalk.gray(`${profile.description}`));
193
+ console.log(
194
+ chalk.gray(`Estimated time: ${profile.estimatedTimeMinutes} minutes\n`)
195
+ );
196
+
197
+ if (options.dryRun) {
198
+ console.log(
199
+ chalk.yellow('🔍 DRY RUN - Showing what would be installed:\n')
200
+ );
201
+ console.log(chalk.cyan('Required tools:'));
202
+ profile.requiredTools.forEach(tool => console.log(` ✓ ${tool}`));
203
+ if (profile.optionalTools.length > 0) {
204
+ console.log(chalk.cyan('\nOptional tools:'));
205
+ profile.optionalTools.forEach(tool => console.log(` • ${tool}`));
206
+ }
207
+ return;
208
+ }
209
+
210
+ // Progress tracking
211
+ const progressCallback = (progress: SetupProgress) => {
212
+ process.stdout.clearLine(0);
213
+ process.stdout.cursorTo(0);
214
+ const progressBar = this.createProgressBar(progress.percentage);
215
+ process.stdout.write(
216
+ `${progressBar} ${progress.percentage.toFixed(1)}% - ${progress.currentStep}`
217
+ );
218
+ };
219
+
220
+ console.log(chalk.cyan('🚀 Starting setup...\n'));
221
+
222
+ const result: SetupResult = await this.orchestrator.orchestrate(
223
+ profileName,
224
+ {
225
+ dryRun: options.dryRun,
226
+ skipExisting: true,
227
+ parallel: false,
228
+ generateReport: true,
229
+ },
230
+ progressCallback
231
+ );
232
+
233
+ console.log('\n'); // New line after progress
234
+
235
+ if (result.success) {
236
+ console.log(chalk.green('\n✅ Setup completed successfully!'));
237
+ console.log(
238
+ chalk.gray(`Duration: ${Math.round(result.duration / 1000)}s\n`)
239
+ );
240
+
241
+ this.showSetupSummary(result);
242
+ this.showNextSteps();
243
+ } else {
244
+ console.log(chalk.red('\n❌ Setup failed!'));
245
+ this.showErrors(result);
246
+ console.log(chalk.cyan('\n💡 Resume with: wundr setup:resume'));
247
+ process.exit(1);
248
+ }
249
+ } catch (error) {
250
+ console.error(chalk.red('\n❌ Setup failed:'), (error as Error).message);
251
+ console.log(chalk.cyan('\n💡 Resume with: wundr setup:resume'));
252
+ process.exit(1);
253
+ }
254
+ }
255
+
256
+ private async validateSetup(options: any): Promise<void> {
257
+ console.log(chalk.cyan('\n🔍 Validating development environment...\n'));
258
+
259
+ const spinner = ora('Running validation checks...').start();
260
+
261
+ // Basic validation checks
262
+ const checks = [
263
+ { name: 'Node.js', test: () => this.checkCommand('node --version') },
264
+ { name: 'Git', test: () => this.checkCommand('git --version') },
265
+ { name: 'Homebrew', test: () => this.checkCommand('brew --version') },
266
+ { name: 'Docker', test: () => this.checkCommand('docker --version') },
267
+ ];
268
+
269
+ const results: Array<{
270
+ name: string;
271
+ status: 'pass' | 'fail';
272
+ version?: string;
273
+ error?: string;
274
+ }> = [];
275
+
276
+ for (const check of checks) {
277
+ try {
278
+ const result = await check.test();
279
+ results.push({
280
+ name: check.name,
281
+ status: 'pass',
282
+ version: result,
283
+ });
284
+ } catch (error) {
285
+ results.push({
286
+ name: check.name,
287
+ status: 'fail',
288
+ error: (error as Error).message,
289
+ });
290
+ }
291
+ }
292
+
293
+ spinner.stop();
294
+
295
+ console.log(chalk.cyan('📊 Validation Results:\n'));
296
+ results.forEach(result => {
297
+ const icon = result.status === 'pass' ? '✅' : '❌';
298
+ const status =
299
+ result.status === 'pass'
300
+ ? chalk.green(`${result.version || 'installed'}`)
301
+ : chalk.red('not found');
302
+ console.log(`${icon} ${result.name}: ${status}`);
303
+ });
304
+
305
+ const failed = results.filter(r => r.status === 'fail');
306
+ if (failed.length > 0) {
307
+ console.log(chalk.yellow(`\n⚠️ ${failed.length} issues found`));
308
+
309
+ if (options.fix) {
310
+ console.log(chalk.cyan('\n🔧 Attempting to fix issues...'));
311
+ await this.runSetup({ profile: options.profile || 'fullstack' });
312
+ } else {
313
+ console.log(
314
+ chalk.cyan('\n💡 Fix issues with: wundr setup:validate --fix')
315
+ );
316
+ }
317
+ } else {
318
+ console.log(chalk.green('\n✅ All checks passed! Environment is ready.'));
319
+ }
320
+ }
321
+
322
+ private async resumeSetup(): Promise<void> {
323
+ console.log(chalk.cyan('\n🔄 Resuming setup...\n'));
324
+
325
+ const progressCallback = (progress: SetupProgress) => {
326
+ process.stdout.clearLine(0);
327
+ process.stdout.cursorTo(0);
328
+ const progressBar = this.createProgressBar(progress.percentage);
329
+ process.stdout.write(
330
+ `${progressBar} ${progress.percentage.toFixed(1)}% - ${progress.currentStep}`
331
+ );
332
+ };
333
+
334
+ try {
335
+ const result = await this.orchestrator.resume(progressCallback);
336
+ console.log('\n');
337
+
338
+ if (result.success) {
339
+ console.log(chalk.green('✅ Setup completed successfully!'));
340
+ this.showSetupSummary(result);
341
+ this.showNextSteps();
342
+ } else {
343
+ console.log(chalk.red('❌ Resume failed!'));
344
+ this.showErrors(result);
345
+ process.exit(1);
346
+ }
347
+ } catch (error) {
348
+ console.error(chalk.red('❌ Resume failed:'), (error as Error).message);
349
+ process.exit(1);
350
+ }
351
+ }
352
+
353
+ private async personalizeSetup(): Promise<void> {
354
+ console.log(chalk.cyan('\n👤 Personal Configuration Setup\n'));
355
+
356
+ const answers = await inquirer.prompt([
357
+ {
358
+ type: 'input',
359
+ name: 'name',
360
+ message: 'Your name:',
361
+ validate: (input: string) => input.length > 0 || 'Name is required',
362
+ },
363
+ {
364
+ type: 'input',
365
+ name: 'email',
366
+ message: 'Your email:',
367
+ validate: (input: string) =>
368
+ /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input) || 'Valid email required',
369
+ },
370
+ {
371
+ type: 'list',
372
+ name: 'shell',
373
+ message: 'Preferred shell:',
374
+ choices: ['zsh', 'bash', 'fish'],
375
+ default: 'zsh',
376
+ },
377
+ {
378
+ type: 'confirm',
379
+ name: 'aliases',
380
+ message: 'Install helpful shell aliases?',
381
+ default: true,
382
+ },
383
+ ]);
384
+
385
+ console.log(chalk.cyan('\n⚙️ Configuring personal settings...'));
386
+
387
+ // Configure Git
388
+ try {
389
+ await this.runCommand(`git config --global user.name "${answers.name}"`);
390
+ await this.runCommand(
391
+ `git config --global user.email "${answers.email}"`
392
+ );
393
+ console.log(chalk.green('✅ Git configured'));
394
+ } catch (error) {
395
+ console.log(chalk.yellow('⚠️ Could not configure Git'));
396
+ }
397
+
398
+ console.log(chalk.green('\n✅ Personalization complete!'));
399
+ }
400
+
401
+ private async selectProfile(): Promise<string> {
402
+ const profiles = this.orchestrator.getAvailableProfiles();
403
+
404
+ const { selectedProfile } = await inquirer.prompt([
405
+ {
406
+ type: 'list',
407
+ name: 'selectedProfile',
408
+ message: 'Select your development profile:',
409
+ choices: profiles.map(p => ({
410
+ name: `${p.name} - ${p.description}`,
411
+ value: p.name.toLowerCase().replace(/\s+/g, ''),
412
+ short: p.name,
413
+ })),
414
+ },
415
+ ]);
416
+
417
+ return selectedProfile;
418
+ }
419
+
420
+ private createProgressBar(percentage: number): string {
421
+ const width = 20;
422
+ const filled = Math.round((percentage / 100) * width);
423
+ const empty = width - filled;
424
+ return (
425
+ chalk.cyan('[') +
426
+ chalk.green('='.repeat(filled)) +
427
+ chalk.gray('-'.repeat(empty)) +
428
+ chalk.cyan(']')
429
+ );
430
+ }
431
+
432
+ private showSetupSummary(result: SetupResult): void {
433
+ if (result.completedSteps.length > 0) {
434
+ console.log(
435
+ chalk.cyan(`🎯 Completed (${result.completedSteps.length}):`)
436
+ );
437
+ result.completedSteps
438
+ .slice(0, 5)
439
+ .forEach(step => console.log(` ✅ ${step.replace('install-', '')}`));
440
+ if (result.completedSteps.length > 5) {
441
+ console.log(` ... and ${result.completedSteps.length - 5} more`);
442
+ }
443
+ }
444
+
445
+ if (result.skippedSteps.length > 0) {
446
+ console.log(
447
+ chalk.yellow(`\n⏭️ Skipped (${result.skippedSteps.length}):`)
448
+ );
449
+ result.skippedSteps
450
+ .slice(0, 3)
451
+ .forEach(step =>
452
+ console.log(
453
+ ` ⏭️ ${step.replace('install-', '')} (already installed)`
454
+ )
455
+ );
456
+ }
457
+ }
458
+
459
+ private showErrors(result: SetupResult): void {
460
+ if (result.failedSteps.length > 0) {
461
+ console.log(chalk.red(`❌ Failed (${result.failedSteps.length}):`));
462
+ result.failedSteps.forEach(step =>
463
+ console.log(` ❌ ${step.replace('install-', '')}`)
464
+ );
465
+ }
466
+
467
+ if (result.errors.length > 0) {
468
+ console.log(chalk.red('\n🔍 Errors:'));
469
+ result.errors
470
+ .slice(0, 3)
471
+ .forEach(error => console.log(` • ${error.message}`));
472
+ }
473
+ }
474
+
475
+ private showNextSteps(): void {
476
+ console.log(chalk.cyan('\n📝 Next Steps:'));
477
+ const steps = [
478
+ 'Restart your terminal to apply changes',
479
+ 'Validate setup: wundr setup:validate',
480
+ 'Personalize: wundr setup:personalize',
481
+ 'Start coding! 🚀',
482
+ ];
483
+
484
+ steps.forEach((step, i) => {
485
+ console.log(` ${i + 1}. ${step}`);
486
+ });
487
+ console.log();
488
+ }
489
+
490
+ private detectPlatform(): SetupPlatform {
491
+ return {
492
+ os: process.platform as 'darwin' | 'linux' | 'win32',
493
+ arch: process.arch as 'x64' | 'arm64',
494
+ version: process.version || 'unknown',
495
+ };
496
+ }
497
+
498
+ private async checkCommand(command: string): Promise<string> {
499
+ const { execa } = await import('execa');
500
+ const { stdout } = await execa('sh', ['-c', command]);
501
+ return stdout?.split('\n')[0] || '';
502
+ }
503
+
504
+ private async runCommand(command: string): Promise<void> {
505
+ const { execa } = await import('execa');
506
+ await execa('sh', ['-c', command]);
507
+ }
508
+ }