@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.
- package/README.md +551 -0
- package/bin/wundr.js +39 -0
- package/dist/ai/ai-service.d.ts +152 -0
- package/dist/ai/ai-service.d.ts.map +1 -0
- package/dist/ai/ai-service.js +430 -0
- package/dist/ai/ai-service.js.map +1 -0
- package/dist/ai/claude-client.d.ts +130 -0
- package/dist/ai/claude-client.d.ts.map +1 -0
- package/dist/ai/claude-client.js +339 -0
- package/dist/ai/claude-client.js.map +1 -0
- package/dist/ai/conversation-manager.d.ts +164 -0
- package/dist/ai/conversation-manager.d.ts.map +1 -0
- package/dist/ai/conversation-manager.js +612 -0
- package/dist/ai/conversation-manager.js.map +1 -0
- package/dist/ai/index.d.ts +5 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +8 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/cli.d.ts +36 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +173 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/ai.d.ts +89 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +735 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/analyze-optimized.d.ts +14 -0
- package/dist/commands/analyze-optimized.d.ts.map +1 -0
- package/dist/commands/analyze-optimized.js +437 -0
- package/dist/commands/analyze-optimized.js.map +1 -0
- package/dist/commands/analyze.d.ts +65 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +435 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/batch.d.ts +71 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +738 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/chat.d.ts +71 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +674 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/claude-init.d.ts +28 -0
- package/dist/commands/claude-init.d.ts.map +1 -0
- package/dist/commands/claude-init.js +587 -0
- package/dist/commands/claude-init.js.map +1 -0
- package/dist/commands/claude-setup.d.ts +32 -0
- package/dist/commands/claude-setup.d.ts.map +1 -0
- package/dist/commands/claude-setup.js +570 -0
- package/dist/commands/claude-setup.js.map +1 -0
- package/dist/commands/computer-setup-commands.d.ts +39 -0
- package/dist/commands/computer-setup-commands.d.ts.map +1 -0
- package/dist/commands/computer-setup-commands.js +563 -0
- package/dist/commands/computer-setup-commands.js.map +1 -0
- package/dist/commands/computer-setup.d.ts +7 -0
- package/dist/commands/computer-setup.d.ts.map +1 -0
- package/dist/commands/computer-setup.js +481 -0
- package/dist/commands/computer-setup.js.map +1 -0
- package/dist/commands/create-command.d.ts +7 -0
- package/dist/commands/create-command.d.ts.map +1 -0
- package/dist/commands/create-command.js +158 -0
- package/dist/commands/create-command.js.map +1 -0
- package/dist/commands/create.d.ts +74 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +556 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/dashboard.d.ts +91 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +537 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/govern.d.ts +70 -0
- package/dist/commands/govern.d.ts.map +1 -0
- package/dist/commands/govern.js +480 -0
- package/dist/commands/govern.js.map +1 -0
- package/dist/commands/init.d.ts +55 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +584 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/performance-optimizer.d.ts +30 -0
- package/dist/commands/performance-optimizer.d.ts.map +1 -0
- package/dist/commands/performance-optimizer.js +649 -0
- package/dist/commands/performance-optimizer.js.map +1 -0
- package/dist/commands/plugins.d.ts +87 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +685 -0
- package/dist/commands/plugins.js.map +1 -0
- package/dist/commands/setup.d.ts +29 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +399 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/test-init.d.ts +9 -0
- package/dist/commands/test-init.d.ts.map +1 -0
- package/dist/commands/test-init.js +222 -0
- package/dist/commands/test-init.js.map +1 -0
- package/dist/commands/test.d.ts +25 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +217 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/watch.d.ts +76 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +610 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/context/context-manager.d.ts +155 -0
- package/dist/context/context-manager.d.ts.map +1 -0
- package/dist/context/context-manager.js +383 -0
- package/dist/context/context-manager.js.map +1 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +6 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/session-manager.d.ts +207 -0
- package/dist/context/session-manager.d.ts.map +1 -0
- package/dist/context/session-manager.js +682 -0
- package/dist/context/session-manager.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive/interactive-mode.d.ts +76 -0
- package/dist/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/interactive/interactive-mode.js +730 -0
- package/dist/interactive/interactive-mode.js.map +1 -0
- package/dist/nlp/command-mapper.d.ts +174 -0
- package/dist/nlp/command-mapper.d.ts.map +1 -0
- package/dist/nlp/command-mapper.js +623 -0
- package/dist/nlp/command-mapper.js.map +1 -0
- package/dist/nlp/command-parser.d.ts +106 -0
- package/dist/nlp/command-parser.d.ts.map +1 -0
- package/dist/nlp/command-parser.js +416 -0
- package/dist/nlp/command-parser.js.map +1 -0
- package/dist/nlp/index.d.ts +5 -0
- package/dist/nlp/index.d.ts.map +1 -0
- package/dist/nlp/index.js +8 -0
- package/dist/nlp/index.js.map +1 -0
- package/dist/nlp/intent-classifier.d.ts +59 -0
- package/dist/nlp/intent-classifier.d.ts.map +1 -0
- package/dist/nlp/intent-classifier.js +384 -0
- package/dist/nlp/intent-classifier.js.map +1 -0
- package/dist/nlp/intent-parser.d.ts +152 -0
- package/dist/nlp/intent-parser.d.ts.map +1 -0
- package/dist/nlp/intent-parser.js +739 -0
- package/dist/nlp/intent-parser.js.map +1 -0
- package/dist/plugins/plugin-manager.d.ts +120 -0
- package/dist/plugins/plugin-manager.d.ts.map +1 -0
- package/dist/plugins/plugin-manager.js +595 -0
- package/dist/plugins/plugin-manager.js.map +1 -0
- package/dist/types/index.d.ts +224 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config-manager.d.ts +73 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +339 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/error-handler.d.ts +46 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +169 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/logger.d.ts +25 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +94 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +119 -0
- package/src/ai/ai-service.ts +595 -0
- package/src/ai/claude-client.ts +490 -0
- package/src/ai/conversation-manager.ts +907 -0
- package/src/ai/index.ts +8 -0
- package/src/cli.ts +202 -0
- package/src/commands/ai.ts +995 -0
- package/src/commands/analyze-optimized.ts +641 -0
- package/src/commands/analyze.ts +576 -0
- package/src/commands/batch.ts +935 -0
- package/src/commands/chat.ts +876 -0
- package/src/commands/claude-init.ts +715 -0
- package/src/commands/claude-setup.ts +697 -0
- package/src/commands/computer-setup-commands.ts +709 -0
- package/src/commands/computer-setup.ts +565 -0
- package/src/commands/create-command.ts +175 -0
- package/src/commands/create.ts +727 -0
- package/src/commands/dashboard.ts +691 -0
- package/src/commands/govern.ts +635 -0
- package/src/commands/init.ts +677 -0
- package/src/commands/performance-optimizer.ts +864 -0
- package/src/commands/plugins.ts +848 -0
- package/src/commands/setup.ts +508 -0
- package/src/commands/test-init.ts +242 -0
- package/src/commands/test.ts +264 -0
- package/src/commands/watch.ts +755 -0
- package/src/context/context-manager.ts +546 -0
- package/src/context/index.ts +9 -0
- package/src/context/session-manager.ts +1019 -0
- package/src/index.ts +64 -0
- package/src/interactive/interactive-mode.ts +830 -0
- package/src/nlp/command-mapper.ts +885 -0
- package/src/nlp/command-parser.ts +564 -0
- package/src/nlp/index.ts +4 -0
- package/src/nlp/intent-classifier.ts +458 -0
- package/src/nlp/intent-parser.ts +1101 -0
- package/src/plugins/plugin-manager.ts +744 -0
- package/src/types/index.ts +252 -0
- package/src/types/modules.d.ts +56 -0
- package/src/utils/config-manager.ts +391 -0
- package/src/utils/error-handler.ts +192 -0
- package/src/utils/logger.ts +104 -0
- package/templates/batch/ci-cd.yaml +62 -0
- package/templates/component/{{fileName}}.test.tsx +17 -0
- package/templates/component/{{fileName}}.tsx +21 -0
- package/templates/service/{{fileName}}.ts +98 -0
- package/templates/wundr-test.config.js +0 -0
- package/test-suites/api/health.spec.ts +134 -0
- package/test-suites/helpers/test-config.ts +84 -0
- package/test-suites/ui/accessibility.spec.ts +102 -0
- package/test-suites/ui/smoke.spec.ts +92 -0
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
import { logger } from '../utils/logger';
|
|
2
|
+
import { AIService, ConversationContext } from '../ai/ai-service';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Natural language command parsing result
|
|
6
|
+
*/
|
|
7
|
+
export interface ParsedCommand {
|
|
8
|
+
originalInput: string;
|
|
9
|
+
intent: string;
|
|
10
|
+
command: string;
|
|
11
|
+
args: string[];
|
|
12
|
+
options: Record<string, any>;
|
|
13
|
+
confidence: number;
|
|
14
|
+
needsConfirmation: boolean;
|
|
15
|
+
suggestions?: string[];
|
|
16
|
+
clarificationQuestion?: string;
|
|
17
|
+
executionPlan?: ExecutionStep[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Execution step for complex commands
|
|
22
|
+
*/
|
|
23
|
+
export interface ExecutionStep {
|
|
24
|
+
step: number;
|
|
25
|
+
description: string;
|
|
26
|
+
command: string;
|
|
27
|
+
args: string[];
|
|
28
|
+
options: Record<string, any>;
|
|
29
|
+
dependencies?: number[];
|
|
30
|
+
optional?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Command template for pattern matching
|
|
35
|
+
*/
|
|
36
|
+
export interface CommandTemplate {
|
|
37
|
+
pattern: RegExp;
|
|
38
|
+
command: string;
|
|
39
|
+
extractParams: (match: RegExpMatchArray) => Record<string, any>;
|
|
40
|
+
confidence: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Natural language command parser
|
|
45
|
+
*/
|
|
46
|
+
export class CommandParser {
|
|
47
|
+
private aiService: AIService;
|
|
48
|
+
private commandTemplates: CommandTemplate[];
|
|
49
|
+
|
|
50
|
+
constructor(aiService: AIService) {
|
|
51
|
+
this.aiService = aiService;
|
|
52
|
+
this.commandTemplates = this.initializeTemplates();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Parse natural language input into CLI command
|
|
57
|
+
*/
|
|
58
|
+
async parseCommand(
|
|
59
|
+
input: string,
|
|
60
|
+
context?: ConversationContext
|
|
61
|
+
): Promise<ParsedCommand> {
|
|
62
|
+
try {
|
|
63
|
+
// First, try template-based parsing for common patterns
|
|
64
|
+
const templateResult = this.tryTemplateMatching(input);
|
|
65
|
+
|
|
66
|
+
if (templateResult && templateResult.confidence > 0.8) {
|
|
67
|
+
return {
|
|
68
|
+
originalInput: input,
|
|
69
|
+
intent: templateResult.intent,
|
|
70
|
+
command: templateResult.command,
|
|
71
|
+
args: templateResult.args,
|
|
72
|
+
options: templateResult.options,
|
|
73
|
+
confidence: templateResult.confidence,
|
|
74
|
+
needsConfirmation: false,
|
|
75
|
+
executionPlan: [this.createExecutionStep(templateResult)],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Fall back to AI-powered parsing
|
|
80
|
+
const aiResult = await this.aiService.parseNaturalLanguageCommand(
|
|
81
|
+
input,
|
|
82
|
+
context
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// Parse the command string into components
|
|
86
|
+
const parsedComponents = this.parseCommandString(aiResult.command);
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
originalInput: input,
|
|
90
|
+
intent: aiResult.intent,
|
|
91
|
+
command: parsedComponents.command,
|
|
92
|
+
args: parsedComponents.args,
|
|
93
|
+
options: parsedComponents.options,
|
|
94
|
+
confidence: aiResult.confidence,
|
|
95
|
+
needsConfirmation: aiResult.needsConfirmation,
|
|
96
|
+
clarificationQuestion: aiResult.clarificationQuestion,
|
|
97
|
+
executionPlan: [this.createExecutionStepFromParsed(parsedComponents)],
|
|
98
|
+
};
|
|
99
|
+
} catch (error) {
|
|
100
|
+
logger.error('Failed to parse command:', error);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
originalInput: input,
|
|
104
|
+
intent: 'unknown',
|
|
105
|
+
command: '',
|
|
106
|
+
args: [],
|
|
107
|
+
options: {},
|
|
108
|
+
confidence: 0,
|
|
109
|
+
needsConfirmation: true,
|
|
110
|
+
clarificationQuestion: `I couldn't understand "${input}". Could you please rephrase or provide more specific details?`,
|
|
111
|
+
suggestions: await this.generateSuggestions(input, context),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Parse complex multi-step commands
|
|
118
|
+
*/
|
|
119
|
+
async parseComplexCommand(
|
|
120
|
+
input: string,
|
|
121
|
+
context?: ConversationContext
|
|
122
|
+
): Promise<ParsedCommand> {
|
|
123
|
+
try {
|
|
124
|
+
// Check if this is a complex command (contains "and", "then", "after")
|
|
125
|
+
const complexPatterns = [
|
|
126
|
+
/\s+and\s+/i,
|
|
127
|
+
/\s+then\s+/i,
|
|
128
|
+
/\s+after\s+/i,
|
|
129
|
+
/[;,]\s*/,
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
const isComplex = complexPatterns.some(pattern => pattern.test(input));
|
|
133
|
+
|
|
134
|
+
if (!isComplex) {
|
|
135
|
+
return await this.parseCommand(input, context);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Split the input into steps
|
|
139
|
+
const steps = this.splitIntoSteps(input);
|
|
140
|
+
const executionPlan: ExecutionStep[] = [];
|
|
141
|
+
|
|
142
|
+
for (let i = 0; i < steps.length; i++) {
|
|
143
|
+
const step = steps[i];
|
|
144
|
+
if (!step) continue;
|
|
145
|
+
|
|
146
|
+
const stepResult = await this.parseCommand(step, context);
|
|
147
|
+
|
|
148
|
+
executionPlan.push({
|
|
149
|
+
step: i + 1,
|
|
150
|
+
description: step,
|
|
151
|
+
command: stepResult.command,
|
|
152
|
+
args: stepResult.args,
|
|
153
|
+
options: stepResult.options,
|
|
154
|
+
dependencies: i > 0 ? [i] : undefined,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
originalInput: input,
|
|
160
|
+
intent: 'complex_workflow',
|
|
161
|
+
command: 'batch',
|
|
162
|
+
args: ['--interactive'],
|
|
163
|
+
options: { steps: executionPlan.length },
|
|
164
|
+
confidence: 0.9,
|
|
165
|
+
needsConfirmation: true,
|
|
166
|
+
executionPlan,
|
|
167
|
+
};
|
|
168
|
+
} catch (error) {
|
|
169
|
+
logger.error('Failed to parse complex command:', error);
|
|
170
|
+
return await this.parseCommand(input, context);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Validate parsed command before execution
|
|
176
|
+
*/
|
|
177
|
+
async validateCommand(parsedCommand: ParsedCommand): Promise<{
|
|
178
|
+
valid: boolean;
|
|
179
|
+
issues: string[];
|
|
180
|
+
recommendations?: string[];
|
|
181
|
+
}> {
|
|
182
|
+
const issues: string[] = [];
|
|
183
|
+
const recommendations: string[] = [];
|
|
184
|
+
|
|
185
|
+
// Check if command exists
|
|
186
|
+
if (!parsedCommand.command || parsedCommand.command.trim() === '') {
|
|
187
|
+
issues.push('No valid command identified');
|
|
188
|
+
recommendations.push(
|
|
189
|
+
'Try rephrasing with a specific action like "analyze", "create", or "init"'
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Validate command format
|
|
194
|
+
if (parsedCommand.command && !parsedCommand.command.startsWith('wundr ')) {
|
|
195
|
+
if (this.isValidWundrCommand(parsedCommand.command)) {
|
|
196
|
+
parsedCommand.command = `wundr ${parsedCommand.command}`;
|
|
197
|
+
} else {
|
|
198
|
+
issues.push(`Unknown command: ${parsedCommand.command}`);
|
|
199
|
+
recommendations.push('Use "wundr help" to see available commands');
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Check confidence level
|
|
204
|
+
if (parsedCommand.confidence < 0.6) {
|
|
205
|
+
issues.push('Low confidence in command interpretation');
|
|
206
|
+
recommendations.push(
|
|
207
|
+
'Consider providing more specific details about what you want to accomplish'
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Validate required parameters for specific commands
|
|
212
|
+
await this.validateCommandSpecifics(parsedCommand, issues, recommendations);
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
valid: issues.length === 0,
|
|
216
|
+
issues,
|
|
217
|
+
recommendations: recommendations.length > 0 ? recommendations : undefined,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Generate command suggestions based on input
|
|
223
|
+
*/
|
|
224
|
+
async generateSuggestions(
|
|
225
|
+
input: string,
|
|
226
|
+
context?: ConversationContext
|
|
227
|
+
): Promise<string[]> {
|
|
228
|
+
try {
|
|
229
|
+
const suggestions = await this.aiService.suggestCommands(input, context);
|
|
230
|
+
return suggestions.map(s => s.command);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
logger.error('Failed to generate suggestions:', error);
|
|
233
|
+
|
|
234
|
+
// Fallback to template-based suggestions
|
|
235
|
+
return this.getFallbackSuggestions(input);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Initialize command templates for pattern matching
|
|
241
|
+
*/
|
|
242
|
+
private initializeTemplates(): CommandTemplate[] {
|
|
243
|
+
return [
|
|
244
|
+
// Analysis commands
|
|
245
|
+
{
|
|
246
|
+
pattern: /analyze|check|scan|examine/i,
|
|
247
|
+
command: 'wundr analyze',
|
|
248
|
+
extractParams: match => ({}),
|
|
249
|
+
confidence: 0.9,
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
pattern: /analyze.*dependencies|dependency analysis|check deps/i,
|
|
253
|
+
command: 'wundr analyze --focus dependencies',
|
|
254
|
+
extractParams: match => ({ focus: 'dependencies' }),
|
|
255
|
+
confidence: 0.95,
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
pattern: /analyze.*duplicates|find duplicates|duplicate analysis/i,
|
|
259
|
+
command: 'wundr analyze --focus duplicates',
|
|
260
|
+
extractParams: match => ({ focus: 'duplicates' }),
|
|
261
|
+
confidence: 0.95,
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
// Initialization commands
|
|
265
|
+
{
|
|
266
|
+
pattern: /init|initialize|setup|start new/i,
|
|
267
|
+
command: 'wundr init',
|
|
268
|
+
extractParams: match => ({}),
|
|
269
|
+
confidence: 0.9,
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
pattern: /init.*project|initialize project|setup project/i,
|
|
273
|
+
command: 'wundr init --type project',
|
|
274
|
+
extractParams: match => ({ type: 'project' }),
|
|
275
|
+
confidence: 0.95,
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
// Creation commands
|
|
279
|
+
{
|
|
280
|
+
pattern: /create.*service|new service|generate service/i,
|
|
281
|
+
command: 'wundr create service',
|
|
282
|
+
extractParams: match => ({}),
|
|
283
|
+
confidence: 0.9,
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
pattern: /create.*component|new component|generate component/i,
|
|
287
|
+
command: 'wundr create component',
|
|
288
|
+
extractParams: match => ({}),
|
|
289
|
+
confidence: 0.9,
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
// Dashboard commands
|
|
293
|
+
{
|
|
294
|
+
pattern: /show dashboard|open dashboard|start dashboard/i,
|
|
295
|
+
command: 'wundr dashboard --start',
|
|
296
|
+
extractParams: match => ({ start: true }),
|
|
297
|
+
confidence: 0.9,
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
// Governance commands
|
|
301
|
+
{
|
|
302
|
+
pattern: /apply governance|governance check|compliance check/i,
|
|
303
|
+
command: 'wundr govern --check',
|
|
304
|
+
extractParams: match => ({ check: true }),
|
|
305
|
+
confidence: 0.9,
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
// Watch commands
|
|
309
|
+
{
|
|
310
|
+
pattern: /watch.*files|monitor files|auto.*run/i,
|
|
311
|
+
command: 'wundr watch',
|
|
312
|
+
extractParams: match => ({}),
|
|
313
|
+
confidence: 0.9,
|
|
314
|
+
},
|
|
315
|
+
];
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Try to match input against command templates
|
|
320
|
+
*/
|
|
321
|
+
private tryTemplateMatching(input: string): {
|
|
322
|
+
intent: string;
|
|
323
|
+
command: string;
|
|
324
|
+
args: string[];
|
|
325
|
+
options: Record<string, any>;
|
|
326
|
+
confidence: number;
|
|
327
|
+
} | null {
|
|
328
|
+
for (const template of this.commandTemplates) {
|
|
329
|
+
const match = input.match(template.pattern);
|
|
330
|
+
|
|
331
|
+
if (match) {
|
|
332
|
+
const params = template.extractParams(match);
|
|
333
|
+
const parsedCommand = this.parseCommandString(template.command);
|
|
334
|
+
|
|
335
|
+
return {
|
|
336
|
+
intent: this.extractIntent(template.command),
|
|
337
|
+
command: parsedCommand.command,
|
|
338
|
+
args: parsedCommand.args,
|
|
339
|
+
options: { ...parsedCommand.options, ...params },
|
|
340
|
+
confidence: template.confidence,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Parse command string into components
|
|
350
|
+
*/
|
|
351
|
+
private parseCommandString(commandStr: string): {
|
|
352
|
+
command: string;
|
|
353
|
+
args: string[];
|
|
354
|
+
options: Record<string, any>;
|
|
355
|
+
} {
|
|
356
|
+
const parts = commandStr.trim().split(/\s+/);
|
|
357
|
+
const command = parts.slice(0, 2).join(' '); // "wundr analyze"
|
|
358
|
+
const remaining = parts.slice(2);
|
|
359
|
+
|
|
360
|
+
const args: string[] = [];
|
|
361
|
+
const options: Record<string, any> = {};
|
|
362
|
+
|
|
363
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
364
|
+
const part = remaining[i];
|
|
365
|
+
|
|
366
|
+
if (part?.startsWith('--')) {
|
|
367
|
+
const optionName = part.slice(2);
|
|
368
|
+
const nextPart = remaining[i + 1];
|
|
369
|
+
|
|
370
|
+
if (nextPart && !nextPart.startsWith('-')) {
|
|
371
|
+
options[optionName] = nextPart;
|
|
372
|
+
i++; // Skip next part
|
|
373
|
+
} else {
|
|
374
|
+
options[optionName] = true;
|
|
375
|
+
}
|
|
376
|
+
} else if (part?.startsWith('-')) {
|
|
377
|
+
const optionName = part.slice(1);
|
|
378
|
+
options[optionName] = true;
|
|
379
|
+
} else if (part) {
|
|
380
|
+
args.push(part);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return { command, args, options };
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Extract intent from command
|
|
389
|
+
*/
|
|
390
|
+
private extractIntent(command: string): string {
|
|
391
|
+
const parts = command.split(' ');
|
|
392
|
+
if (parts.length >= 2 && parts[1]) {
|
|
393
|
+
return parts[1]; // "analyze", "create", etc.
|
|
394
|
+
}
|
|
395
|
+
return 'unknown';
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Create execution step from template result
|
|
400
|
+
*/
|
|
401
|
+
private createExecutionStep(templateResult: {
|
|
402
|
+
command: string;
|
|
403
|
+
args: string[];
|
|
404
|
+
options: Record<string, any>;
|
|
405
|
+
}): ExecutionStep {
|
|
406
|
+
return {
|
|
407
|
+
step: 1,
|
|
408
|
+
description: `Execute ${templateResult.command}`,
|
|
409
|
+
command: templateResult.command,
|
|
410
|
+
args: templateResult.args,
|
|
411
|
+
options: templateResult.options,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Create execution step from parsed command
|
|
417
|
+
*/
|
|
418
|
+
private createExecutionStepFromParsed(parsedComponents: {
|
|
419
|
+
command: string;
|
|
420
|
+
args: string[];
|
|
421
|
+
options: Record<string, any>;
|
|
422
|
+
}): ExecutionStep {
|
|
423
|
+
return {
|
|
424
|
+
step: 1,
|
|
425
|
+
description: `Execute ${parsedComponents.command}`,
|
|
426
|
+
command: parsedComponents.command,
|
|
427
|
+
args: parsedComponents.args,
|
|
428
|
+
options: parsedComponents.options,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Split complex input into execution steps
|
|
434
|
+
*/
|
|
435
|
+
private splitIntoSteps(input: string): string[] {
|
|
436
|
+
// Split on coordinating conjunctions and punctuation
|
|
437
|
+
const separators = /\s+(and|then|after|next|followed by)[,\s]+|[;,]\s+/i;
|
|
438
|
+
return input
|
|
439
|
+
.split(separators)
|
|
440
|
+
.map(step => step.trim())
|
|
441
|
+
.filter(
|
|
442
|
+
step =>
|
|
443
|
+
step.length > 0 &&
|
|
444
|
+
!['and', 'then', 'after', 'next', 'followed by'].includes(
|
|
445
|
+
step.toLowerCase()
|
|
446
|
+
)
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Check if command is a valid Wundr command
|
|
452
|
+
*/
|
|
453
|
+
private isValidWundrCommand(command: string): boolean {
|
|
454
|
+
const validCommands = [
|
|
455
|
+
'init',
|
|
456
|
+
'create',
|
|
457
|
+
'analyze',
|
|
458
|
+
'govern',
|
|
459
|
+
'dashboard',
|
|
460
|
+
'watch',
|
|
461
|
+
'batch',
|
|
462
|
+
'plugins',
|
|
463
|
+
'chat',
|
|
464
|
+
'help',
|
|
465
|
+
];
|
|
466
|
+
|
|
467
|
+
const baseCommand = command.split(' ')[0];
|
|
468
|
+
return baseCommand ? validCommands.includes(baseCommand) : false;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Validate command-specific requirements
|
|
473
|
+
*/
|
|
474
|
+
private async validateCommandSpecifics(
|
|
475
|
+
parsedCommand: ParsedCommand,
|
|
476
|
+
issues: string[],
|
|
477
|
+
recommendations: string[]
|
|
478
|
+
): Promise<void> {
|
|
479
|
+
const commandParts = parsedCommand.command.split(' ');
|
|
480
|
+
const baseCommand = commandParts[1]; // Skip "wundr"
|
|
481
|
+
|
|
482
|
+
switch (baseCommand) {
|
|
483
|
+
case 'create':
|
|
484
|
+
if (parsedCommand.args.length === 0) {
|
|
485
|
+
issues.push(
|
|
486
|
+
'Create command requires a type (service, component, etc.)'
|
|
487
|
+
);
|
|
488
|
+
recommendations.push(
|
|
489
|
+
'Specify what you want to create: "wundr create service MyService"'
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
break;
|
|
493
|
+
|
|
494
|
+
case 'analyze':
|
|
495
|
+
// Analyze command is flexible, but we can suggest focus areas
|
|
496
|
+
if (!parsedCommand.options['focus']) {
|
|
497
|
+
recommendations.push(
|
|
498
|
+
'Consider using --focus to target specific areas (dependencies, duplicates, quality)'
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
break;
|
|
502
|
+
|
|
503
|
+
case 'watch':
|
|
504
|
+
if (
|
|
505
|
+
!parsedCommand.options['pattern'] &&
|
|
506
|
+
parsedCommand.args.length === 0
|
|
507
|
+
) {
|
|
508
|
+
recommendations.push(
|
|
509
|
+
'Specify file patterns to watch: "wundr watch --pattern "**/*.ts""'
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
break;
|
|
513
|
+
|
|
514
|
+
case 'batch':
|
|
515
|
+
if (
|
|
516
|
+
!parsedCommand.options['file'] &&
|
|
517
|
+
!parsedCommand.options['interactive']
|
|
518
|
+
) {
|
|
519
|
+
issues.push(
|
|
520
|
+
'Batch command requires either a batch file or interactive mode'
|
|
521
|
+
);
|
|
522
|
+
recommendations.push(
|
|
523
|
+
'Use --file <batch-file> or --interactive for step-by-step execution'
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
break;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Get fallback suggestions when AI fails
|
|
532
|
+
*/
|
|
533
|
+
private getFallbackSuggestions(input: string): string[] {
|
|
534
|
+
const suggestions: string[] = [];
|
|
535
|
+
const lowerInput = input.toLowerCase();
|
|
536
|
+
|
|
537
|
+
if (lowerInput.includes('analyze') || lowerInput.includes('check')) {
|
|
538
|
+
suggestions.push('wundr analyze --path ./src');
|
|
539
|
+
suggestions.push('wundr analyze --focus dependencies');
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (lowerInput.includes('create') || lowerInput.includes('new')) {
|
|
543
|
+
suggestions.push('wundr create service MyService');
|
|
544
|
+
suggestions.push('wundr create component MyComponent');
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (lowerInput.includes('init') || lowerInput.includes('setup')) {
|
|
548
|
+
suggestions.push('wundr init --type project');
|
|
549
|
+
suggestions.push('wundr init --template basic');
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
if (lowerInput.includes('dashboard') || lowerInput.includes('show')) {
|
|
553
|
+
suggestions.push('wundr dashboard --start');
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (suggestions.length === 0) {
|
|
557
|
+
suggestions.push('wundr help');
|
|
558
|
+
suggestions.push('wundr analyze --path .');
|
|
559
|
+
suggestions.push('wundr init');
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return suggestions.slice(0, 3); // Limit to 3 suggestions
|
|
563
|
+
}
|
|
564
|
+
}
|
package/src/nlp/index.ts
ADDED