@wundr.io/cli 1.0.12 → 1.0.13
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/LICENSE +21 -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 +340 -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 +614 -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 +192 -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 +954 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/alignment.d.ts +78 -0
- package/dist/commands/alignment.d.ts.map +1 -0
- package/dist/commands/alignment.js +817 -0
- package/dist/commands/alignment.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 +609 -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 +93 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +854 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/chat.d.ts +72 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +678 -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 +591 -0
- package/dist/commands/claude-init.js.map +1 -0
- package/dist/commands/claude-setup.d.ts +119 -0
- package/dist/commands/claude-setup.d.ts.map +1 -0
- package/dist/commands/claude-setup.js +1079 -0
- package/dist/commands/claude-setup.js.map +1 -0
- package/dist/commands/computer-setup.d.ts +8 -0
- package/dist/commands/computer-setup.d.ts.map +1 -0
- package/dist/commands/computer-setup.js +877 -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 +538 -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 +481 -0
- package/dist/commands/govern.js.map +1 -0
- package/dist/commands/governance.d.ts +17 -0
- package/dist/commands/governance.d.ts.map +1 -0
- package/dist/commands/governance.js +703 -0
- package/dist/commands/governance.js.map +1 -0
- package/dist/commands/guardian.d.ts +20 -0
- package/dist/commands/guardian.d.ts.map +1 -0
- package/dist/commands/guardian.js +597 -0
- package/dist/commands/guardian.js.map +1 -0
- package/dist/commands/init.d.ts +59 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +650 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/orchestrator.d.ts +7 -0
- package/dist/commands/orchestrator.d.ts.map +1 -0
- package/dist/commands/orchestrator.js +578 -0
- package/dist/commands/orchestrator.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 +650 -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/rag.d.ts +7 -0
- package/dist/commands/rag.d.ts.map +1 -0
- package/dist/commands/rag.js +751 -0
- package/dist/commands/rag.js.map +1 -0
- package/dist/commands/session.d.ts +41 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +441 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/setup.d.ts +24 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +172 -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 +613 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/worktree.d.ts +63 -0
- package/dist/commands/worktree.d.ts.map +1 -0
- package/dist/commands/worktree.js +774 -0
- package/dist/commands/worktree.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 +686 -0
- package/dist/context/session-manager.js.map +1 -0
- package/dist/framework/command-interface.d.ts +349 -0
- package/dist/framework/command-interface.d.ts.map +1 -0
- package/dist/framework/command-interface.js +101 -0
- package/dist/framework/command-interface.js.map +1 -0
- package/dist/framework/command-registry.d.ts +173 -0
- package/dist/framework/command-registry.d.ts.map +1 -0
- package/dist/framework/command-registry.js +734 -0
- package/dist/framework/command-registry.js.map +1 -0
- package/dist/framework/completion-exporter.d.ts +79 -0
- package/dist/framework/completion-exporter.d.ts.map +1 -0
- package/dist/framework/completion-exporter.js +259 -0
- package/dist/framework/completion-exporter.js.map +1 -0
- package/dist/framework/debug-logger.d.ts +163 -0
- package/dist/framework/debug-logger.d.ts.map +1 -0
- package/dist/framework/debug-logger.js +373 -0
- package/dist/framework/debug-logger.js.map +1 -0
- package/dist/framework/error-handler.d.ts +196 -0
- package/dist/framework/error-handler.d.ts.map +1 -0
- package/dist/framework/error-handler.js +613 -0
- package/dist/framework/error-handler.js.map +1 -0
- package/dist/framework/help-generator.d.ts +78 -0
- package/dist/framework/help-generator.d.ts.map +1 -0
- package/dist/framework/help-generator.js +414 -0
- package/dist/framework/help-generator.js.map +1 -0
- package/dist/framework/index.d.ts +62 -0
- package/dist/framework/index.d.ts.map +1 -0
- package/dist/framework/index.js +95 -0
- package/dist/framework/index.js.map +1 -0
- package/dist/framework/interactive-repl.d.ts +138 -0
- package/dist/framework/interactive-repl.d.ts.map +1 -0
- package/dist/framework/interactive-repl.js +567 -0
- package/dist/framework/interactive-repl.js.map +1 -0
- package/dist/framework/output-formatter.d.ts +274 -0
- package/dist/framework/output-formatter.d.ts.map +1 -0
- package/dist/framework/output-formatter.js +545 -0
- package/dist/framework/output-formatter.js.map +1 -0
- package/dist/framework/progress-manager.d.ts +192 -0
- package/dist/framework/progress-manager.d.ts.map +1 -0
- package/dist/framework/progress-manager.js +408 -0
- package/dist/framework/progress-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 +732 -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 +624 -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 +417 -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 +746 -0
- package/dist/nlp/intent-parser.js.map +1 -0
- package/dist/plugins/plugin-manager.d.ts +121 -0
- package/dist/plugins/plugin-manager.d.ts.map +1 -0
- package/dist/plugins/plugin-manager.js +606 -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/backup-rollback-manager.d.ts +72 -0
- package/dist/utils/backup-rollback-manager.d.ts.map +1 -0
- package/dist/utils/backup-rollback-manager.js +288 -0
- package/dist/utils/backup-rollback-manager.js.map +1 -0
- package/dist/utils/claude-config-installer.d.ts +98 -0
- package/dist/utils/claude-config-installer.d.ts.map +1 -0
- package/dist/utils/claude-config-installer.js +678 -0
- package/dist/utils/claude-config-installer.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 +105 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +23 -23
|
@@ -0,0 +1,746 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IntentParser = void 0;
|
|
4
|
+
const events_1 = require("events");
|
|
5
|
+
const logger_1 = require("../utils/logger");
|
|
6
|
+
/**
|
|
7
|
+
* Advanced NLP Intent Parser for converting natural language to CLI commands
|
|
8
|
+
*/
|
|
9
|
+
class IntentParser extends events_1.EventEmitter {
|
|
10
|
+
claudeClient;
|
|
11
|
+
config;
|
|
12
|
+
commandPatterns;
|
|
13
|
+
intentCache;
|
|
14
|
+
entityPatterns;
|
|
15
|
+
constructor(claudeClient, config = {}) {
|
|
16
|
+
super();
|
|
17
|
+
this.claudeClient = claudeClient;
|
|
18
|
+
this.config = {
|
|
19
|
+
confidenceThreshold: 0.7,
|
|
20
|
+
maxAlternatives: 3,
|
|
21
|
+
enableNER: true,
|
|
22
|
+
enableContextAwareness: true,
|
|
23
|
+
cacheDuration: 5 * 60 * 1000, // 5 minutes
|
|
24
|
+
...config,
|
|
25
|
+
};
|
|
26
|
+
this.commandPatterns = new Map();
|
|
27
|
+
this.intentCache = new Map();
|
|
28
|
+
this.entityPatterns = new Map();
|
|
29
|
+
this.initializePatterns();
|
|
30
|
+
this.initializeEntityRecognition();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Parse natural language input and extract intent
|
|
34
|
+
*/
|
|
35
|
+
async parseIntent(input, availableCommands, context = {}) {
|
|
36
|
+
const normalizedInput = this.normalizeInput(input);
|
|
37
|
+
const cacheKey = this.getCacheKey(normalizedInput, availableCommands, context);
|
|
38
|
+
// Check cache first
|
|
39
|
+
const cached = this.intentCache.get(cacheKey);
|
|
40
|
+
if (cached && Date.now() - cached.timestamp < this.config.cacheDuration) {
|
|
41
|
+
logger_1.logger.debug('Returning cached intent result');
|
|
42
|
+
return cached.result;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
// Step 1: Quick pattern matching for common commands
|
|
46
|
+
const patternResult = await this.patternMatching(normalizedInput, availableCommands);
|
|
47
|
+
if (patternResult.confidence >= 0.9) {
|
|
48
|
+
this.cacheResult(cacheKey, patternResult);
|
|
49
|
+
return patternResult;
|
|
50
|
+
}
|
|
51
|
+
// Step 2: Named Entity Recognition
|
|
52
|
+
const entities = this.config.enableNER
|
|
53
|
+
? await this.extractEntities(normalizedInput)
|
|
54
|
+
: [];
|
|
55
|
+
// Step 3: AI-powered intent analysis
|
|
56
|
+
const aiResult = await this.aiIntentAnalysis(normalizedInput, availableCommands, context, entities);
|
|
57
|
+
// Step 4: Combine results and validate
|
|
58
|
+
const finalResult = this.combineResults(patternResult, aiResult, entities);
|
|
59
|
+
// Step 5: Post-processing and validation
|
|
60
|
+
const validatedResult = await this.validateAndEnrich(finalResult, availableCommands, context);
|
|
61
|
+
this.cacheResult(cacheKey, validatedResult);
|
|
62
|
+
this.emit('intent_parsed', {
|
|
63
|
+
input: normalizedInput,
|
|
64
|
+
result: validatedResult,
|
|
65
|
+
});
|
|
66
|
+
return validatedResult;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
logger_1.logger.error('Intent parsing failed:', error);
|
|
70
|
+
return this.fallbackIntentParsing(normalizedInput, availableCommands, context);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Extract command parameters from natural language
|
|
75
|
+
*/
|
|
76
|
+
async extractParameters(input, command, commandPattern) {
|
|
77
|
+
const parameters = {};
|
|
78
|
+
if (!commandPattern) {
|
|
79
|
+
commandPattern = this.commandPatterns.get(command);
|
|
80
|
+
}
|
|
81
|
+
if (!commandPattern) {
|
|
82
|
+
logger_1.logger.debug(`No pattern found for command: ${command}`);
|
|
83
|
+
return parameters;
|
|
84
|
+
}
|
|
85
|
+
// Extract using AI
|
|
86
|
+
const systemPrompt = `You are a parameter extraction system. Extract parameters from user input for the command "${command}".
|
|
87
|
+
|
|
88
|
+
Command parameters:
|
|
89
|
+
${commandPattern.parameters.map(p => `- ${p.name} (${p.type}${p.required ? ', required' : ', optional'}): ${p.aliases?.join(', ') || ''}`).join('\n')}
|
|
90
|
+
|
|
91
|
+
Extract parameters from the user input and respond with JSON only:
|
|
92
|
+
{
|
|
93
|
+
"parameters": {
|
|
94
|
+
"paramName": "value"
|
|
95
|
+
},
|
|
96
|
+
"confidence": 0.9
|
|
97
|
+
}`;
|
|
98
|
+
try {
|
|
99
|
+
const response = await this.claudeClient.sendMessage(input, systemPrompt, {
|
|
100
|
+
temperature: 0.1,
|
|
101
|
+
maxTokens: 1024,
|
|
102
|
+
});
|
|
103
|
+
const result = JSON.parse(response.trim());
|
|
104
|
+
// Validate extracted parameters
|
|
105
|
+
for (const param of commandPattern.parameters) {
|
|
106
|
+
if (param.required && !result.parameters[param.name]) {
|
|
107
|
+
logger_1.logger.warn(`Missing required parameter: ${param.name}`);
|
|
108
|
+
}
|
|
109
|
+
if (result.parameters[param.name] && param.validation) {
|
|
110
|
+
if (!param.validation.test(result.parameters[param.name])) {
|
|
111
|
+
logger_1.logger.warn(`Parameter validation failed for ${param.name}: ${result.parameters[param.name]}`);
|
|
112
|
+
delete result.parameters[param.name];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Apply default values
|
|
116
|
+
if (!result.parameters[param.name] &&
|
|
117
|
+
param.defaultValue !== undefined) {
|
|
118
|
+
result.parameters[param.name] = param.defaultValue;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return result.parameters;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
logger_1.logger.error('Parameter extraction failed:', error);
|
|
125
|
+
return this.fallbackParameterExtraction(input, commandPattern);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Suggest commands based on partial input
|
|
130
|
+
*/
|
|
131
|
+
async suggestCommands(partialInput, availableCommands, context = {}, limit = 5) {
|
|
132
|
+
const suggestions = [];
|
|
133
|
+
// Pattern-based suggestions
|
|
134
|
+
const patternSuggestions = this.getPatternSuggestions(partialInput, availableCommands);
|
|
135
|
+
suggestions.push(...patternSuggestions);
|
|
136
|
+
// AI-powered suggestions if we need more
|
|
137
|
+
if (suggestions.length < limit) {
|
|
138
|
+
try {
|
|
139
|
+
const aiSuggestions = await this.getAISuggestions(partialInput, availableCommands, context, limit - suggestions.length);
|
|
140
|
+
suggestions.push(...aiSuggestions);
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
logger_1.logger.error('AI suggestions failed:', error);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Sort by confidence and limit results
|
|
147
|
+
suggestions.sort((a, b) => b.confidence - a.confidence);
|
|
148
|
+
return suggestions.slice(0, limit);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Register a custom command pattern
|
|
152
|
+
*/
|
|
153
|
+
registerCommandPattern(pattern) {
|
|
154
|
+
this.commandPatterns.set(pattern.intent, pattern);
|
|
155
|
+
logger_1.logger.debug(`Registered command pattern: ${pattern.intent}`);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Batch register multiple command patterns
|
|
159
|
+
*/
|
|
160
|
+
registerCommandPatterns(patterns) {
|
|
161
|
+
patterns.forEach(pattern => this.registerCommandPattern(pattern));
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get registered command patterns
|
|
165
|
+
*/
|
|
166
|
+
getCommandPatterns() {
|
|
167
|
+
return Array.from(this.commandPatterns.values());
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Clear intent cache
|
|
171
|
+
*/
|
|
172
|
+
clearCache() {
|
|
173
|
+
this.intentCache.clear();
|
|
174
|
+
this.emit('cache_cleared');
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get cache statistics
|
|
178
|
+
*/
|
|
179
|
+
getCacheStats() {
|
|
180
|
+
const now = Date.now();
|
|
181
|
+
const validEntries = Array.from(this.intentCache.values()).filter(entry => now - entry.timestamp < this.config.cacheDuration);
|
|
182
|
+
const oldestEntry = validEntries.length > 0
|
|
183
|
+
? new Date(Math.min(...validEntries.map(e => e.timestamp)))
|
|
184
|
+
: null;
|
|
185
|
+
return {
|
|
186
|
+
size: validEntries.length,
|
|
187
|
+
hitRate: this.intentCache.size > 0
|
|
188
|
+
? validEntries.length / this.intentCache.size
|
|
189
|
+
: 0,
|
|
190
|
+
oldestEntry,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// Private methods
|
|
194
|
+
initializePatterns() {
|
|
195
|
+
const defaultPatterns = [
|
|
196
|
+
{
|
|
197
|
+
intent: 'analyze',
|
|
198
|
+
patterns: [
|
|
199
|
+
'analyze {path?}',
|
|
200
|
+
'check {path?}',
|
|
201
|
+
'scan {path?}',
|
|
202
|
+
'examine {path?}',
|
|
203
|
+
'review {path?}',
|
|
204
|
+
],
|
|
205
|
+
parameters: [
|
|
206
|
+
{ name: 'path', type: 'path', required: false, defaultValue: '.' },
|
|
207
|
+
{
|
|
208
|
+
name: 'focus',
|
|
209
|
+
type: 'enum',
|
|
210
|
+
required: false,
|
|
211
|
+
enumValues: ['dependencies', 'quality', 'security', 'performance'],
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: 'format',
|
|
215
|
+
type: 'enum',
|
|
216
|
+
required: false,
|
|
217
|
+
enumValues: ['json', 'table', 'csv'],
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
examples: [
|
|
221
|
+
'analyze the project',
|
|
222
|
+
'check dependencies in src folder',
|
|
223
|
+
'scan for security issues',
|
|
224
|
+
],
|
|
225
|
+
category: 'analysis',
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
intent: 'create',
|
|
229
|
+
patterns: [
|
|
230
|
+
'create {type} {name}',
|
|
231
|
+
'new {type} {name}',
|
|
232
|
+
'generate {type} {name}',
|
|
233
|
+
'make {type} {name}',
|
|
234
|
+
],
|
|
235
|
+
parameters: [
|
|
236
|
+
{
|
|
237
|
+
name: 'type',
|
|
238
|
+
type: 'enum',
|
|
239
|
+
required: true,
|
|
240
|
+
enumValues: ['component', 'service', 'test', 'config'],
|
|
241
|
+
},
|
|
242
|
+
{ name: 'name', type: 'string', required: true },
|
|
243
|
+
{ name: 'template', type: 'string', required: false },
|
|
244
|
+
],
|
|
245
|
+
examples: [
|
|
246
|
+
'create component UserProfile',
|
|
247
|
+
'new service AuthService',
|
|
248
|
+
'generate test for UserService',
|
|
249
|
+
],
|
|
250
|
+
category: 'generation',
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
intent: 'init',
|
|
254
|
+
patterns: [
|
|
255
|
+
'init {project?}',
|
|
256
|
+
'initialize {project?}',
|
|
257
|
+
'setup {project?}',
|
|
258
|
+
'configure {project?}',
|
|
259
|
+
],
|
|
260
|
+
parameters: [
|
|
261
|
+
{ name: 'project', type: 'string', required: false },
|
|
262
|
+
{ name: 'template', type: 'string', required: false },
|
|
263
|
+
{ name: 'force', type: 'boolean', required: false },
|
|
264
|
+
],
|
|
265
|
+
examples: [
|
|
266
|
+
'init new project',
|
|
267
|
+
'initialize with React template',
|
|
268
|
+
'setup the workspace',
|
|
269
|
+
],
|
|
270
|
+
category: 'setup',
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
intent: 'help',
|
|
274
|
+
patterns: [
|
|
275
|
+
'help {command?}',
|
|
276
|
+
'how {action?}',
|
|
277
|
+
'what {question?}',
|
|
278
|
+
'explain {topic?}',
|
|
279
|
+
],
|
|
280
|
+
parameters: [
|
|
281
|
+
{ name: 'command', type: 'string', required: false },
|
|
282
|
+
{ name: 'topic', type: 'string', required: false },
|
|
283
|
+
],
|
|
284
|
+
examples: [
|
|
285
|
+
'help with analyze command',
|
|
286
|
+
'how to create components',
|
|
287
|
+
'what does this do',
|
|
288
|
+
],
|
|
289
|
+
category: 'help',
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
intent: 'dashboard',
|
|
293
|
+
patterns: [
|
|
294
|
+
'dashboard',
|
|
295
|
+
'ui',
|
|
296
|
+
'interface',
|
|
297
|
+
'show {view?}',
|
|
298
|
+
'open {view?}',
|
|
299
|
+
],
|
|
300
|
+
parameters: [
|
|
301
|
+
{
|
|
302
|
+
name: 'view',
|
|
303
|
+
type: 'enum',
|
|
304
|
+
required: false,
|
|
305
|
+
enumValues: ['overview', 'metrics', 'reports'],
|
|
306
|
+
},
|
|
307
|
+
{ name: 'port', type: 'number', required: false, defaultValue: 3000 },
|
|
308
|
+
],
|
|
309
|
+
examples: ['open dashboard', 'show metrics view', 'start ui'],
|
|
310
|
+
category: 'interface',
|
|
311
|
+
},
|
|
312
|
+
];
|
|
313
|
+
defaultPatterns.forEach(pattern => this.registerCommandPattern(pattern));
|
|
314
|
+
}
|
|
315
|
+
initializeEntityRecognition() {
|
|
316
|
+
this.entityPatterns.set('file_path', /(?:\.\/|\/|~\/)[^\s]+/g);
|
|
317
|
+
this.entityPatterns.set('package_name', /(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*/g);
|
|
318
|
+
this.entityPatterns.set('command', /(?:wundr\s+)?(?:analyze|create|init|help|dashboard|batch|watch)\b/g);
|
|
319
|
+
this.entityPatterns.set('option', /--?[a-zA-Z][a-zA-Z0-9-]*/g);
|
|
320
|
+
this.entityPatterns.set('technology', /\b(?:react|angular|vue|nodejs|typescript|javascript|python|java|docker|kubernetes)\b/gi);
|
|
321
|
+
}
|
|
322
|
+
normalizeInput(input) {
|
|
323
|
+
return input
|
|
324
|
+
.trim()
|
|
325
|
+
.toLowerCase()
|
|
326
|
+
.replace(/[^\w\s\-\.\/]/g, ' ')
|
|
327
|
+
.replace(/\s+/g, ' ');
|
|
328
|
+
}
|
|
329
|
+
getCacheKey(input, commands, context) {
|
|
330
|
+
const contextKey = JSON.stringify({
|
|
331
|
+
projectType: context.projectType,
|
|
332
|
+
workingDirectory: context.workingDirectory,
|
|
333
|
+
recentCommands: context.recentCommands?.slice(0, 3), // Only recent commands for cache key
|
|
334
|
+
});
|
|
335
|
+
return `${input}:${commands.sort().join(',')}:${contextKey}`;
|
|
336
|
+
}
|
|
337
|
+
async patternMatching(input, availableCommands) {
|
|
338
|
+
let bestMatch = {
|
|
339
|
+
intent: 'unknown',
|
|
340
|
+
confidence: 0,
|
|
341
|
+
context: { entities: [], keywords: [], sentiment: 'neutral' },
|
|
342
|
+
};
|
|
343
|
+
for (const [intent, pattern] of this.commandPatterns) {
|
|
344
|
+
if (!availableCommands.includes(intent)) {
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
const confidence = this.calculatePatternScore(input, pattern);
|
|
348
|
+
if (confidence > bestMatch.confidence) {
|
|
349
|
+
bestMatch = {
|
|
350
|
+
intent,
|
|
351
|
+
confidence,
|
|
352
|
+
command: `wundr ${intent}`,
|
|
353
|
+
parameters: {},
|
|
354
|
+
reasoning: `Pattern match for "${intent}" command`,
|
|
355
|
+
context: { entities: [], keywords: [], sentiment: 'neutral' },
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return bestMatch;
|
|
360
|
+
}
|
|
361
|
+
calculatePatternScore(input, pattern) {
|
|
362
|
+
let score = 0;
|
|
363
|
+
let totalWeight = 0;
|
|
364
|
+
// Check pattern matches
|
|
365
|
+
for (const patternStr of pattern.patterns) {
|
|
366
|
+
const patternWords = patternStr.toLowerCase().split(/\s+/);
|
|
367
|
+
const inputWords = input.split(/\s+/);
|
|
368
|
+
let matchCount = 0;
|
|
369
|
+
for (const word of patternWords) {
|
|
370
|
+
if (word.startsWith('{') && word.endsWith('}')) {
|
|
371
|
+
continue;
|
|
372
|
+
} // Skip parameters
|
|
373
|
+
if (inputWords.includes(word)) {
|
|
374
|
+
matchCount++;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const patternScore = matchCount / patternWords.filter(w => !w.startsWith('{')).length;
|
|
378
|
+
score = Math.max(score, patternScore);
|
|
379
|
+
}
|
|
380
|
+
totalWeight += 0.6;
|
|
381
|
+
// Check examples
|
|
382
|
+
let exampleScore = 0;
|
|
383
|
+
for (const example of pattern.examples) {
|
|
384
|
+
const similarity = this.calculateStringSimilarity(input, example.toLowerCase());
|
|
385
|
+
exampleScore = Math.max(exampleScore, similarity);
|
|
386
|
+
}
|
|
387
|
+
score += exampleScore * 0.4;
|
|
388
|
+
totalWeight += 0.4;
|
|
389
|
+
return score / totalWeight;
|
|
390
|
+
}
|
|
391
|
+
calculateStringSimilarity(str1, str2) {
|
|
392
|
+
const words1 = str1.split(/\s+/);
|
|
393
|
+
const words2 = str2.split(/\s+/);
|
|
394
|
+
let matches = 0;
|
|
395
|
+
for (const word1 of words1) {
|
|
396
|
+
if (words2.includes(word1)) {
|
|
397
|
+
matches++;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return matches / Math.max(words1.length, words2.length);
|
|
401
|
+
}
|
|
402
|
+
async extractEntities(input) {
|
|
403
|
+
const entities = [];
|
|
404
|
+
for (const [type, pattern] of this.entityPatterns) {
|
|
405
|
+
const matches = Array.from(input.matchAll(pattern));
|
|
406
|
+
for (const match of matches) {
|
|
407
|
+
if (match.index !== undefined) {
|
|
408
|
+
entities.push({
|
|
409
|
+
text: match[0],
|
|
410
|
+
type: type,
|
|
411
|
+
confidence: 0.8, // Static confidence for regex patterns
|
|
412
|
+
startIndex: match.index,
|
|
413
|
+
endIndex: match.index + match[0].length,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return entities;
|
|
419
|
+
}
|
|
420
|
+
async aiIntentAnalysis(input, availableCommands, context, entities) {
|
|
421
|
+
const contextInfo = this.buildContextInfo(context);
|
|
422
|
+
const entityInfo = entities.length > 0
|
|
423
|
+
? `\nDetected entities: ${entities.map(e => `${e.text} (${e.type})`).join(', ')}`
|
|
424
|
+
: '';
|
|
425
|
+
const systemPrompt = `You are an expert CLI intent analyzer. Analyze user input and map it to appropriate commands.
|
|
426
|
+
|
|
427
|
+
Available commands: ${availableCommands.join(', ')}
|
|
428
|
+
${contextInfo}${entityInfo}
|
|
429
|
+
|
|
430
|
+
User input: "${input}"
|
|
431
|
+
|
|
432
|
+
Analyze and respond with JSON only:
|
|
433
|
+
{
|
|
434
|
+
"intent": "command_name",
|
|
435
|
+
"confidence": 0.95,
|
|
436
|
+
"command": "wundr analyze --path ./src",
|
|
437
|
+
"parameters": {"path": "./src"},
|
|
438
|
+
"alternatives": [
|
|
439
|
+
{"command": "wundr scan", "confidence": 0.7, "description": "Alternative interpretation"}
|
|
440
|
+
],
|
|
441
|
+
"reasoning": "User wants to analyze source code based on path mention",
|
|
442
|
+
"clarification": null
|
|
443
|
+
}`;
|
|
444
|
+
try {
|
|
445
|
+
const response = await this.claudeClient.sendMessage(input, systemPrompt, {
|
|
446
|
+
temperature: 0.1,
|
|
447
|
+
maxTokens: 1536,
|
|
448
|
+
});
|
|
449
|
+
const cleanResponse = response.trim();
|
|
450
|
+
const jsonMatch = cleanResponse.match(/\{[\s\S]*\}/);
|
|
451
|
+
if (!jsonMatch) {
|
|
452
|
+
throw new Error('No valid JSON in AI response');
|
|
453
|
+
}
|
|
454
|
+
const result = JSON.parse(jsonMatch[0]);
|
|
455
|
+
// Add context information
|
|
456
|
+
result.context = {
|
|
457
|
+
entities,
|
|
458
|
+
keywords: this.extractKeywords(input),
|
|
459
|
+
sentiment: this.analyzeSentiment(input),
|
|
460
|
+
};
|
|
461
|
+
return result;
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
logger_1.logger.error('AI intent analysis failed:', error);
|
|
465
|
+
throw error;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
buildContextInfo(context) {
|
|
469
|
+
const parts = [];
|
|
470
|
+
if (context.projectType) {
|
|
471
|
+
parts.push(`Project type: ${context.projectType}`);
|
|
472
|
+
}
|
|
473
|
+
if (context.recentCommands?.length) {
|
|
474
|
+
parts.push(`Recent commands: ${context.recentCommands.slice(0, 3).join(', ')}`);
|
|
475
|
+
}
|
|
476
|
+
if (context.workingDirectory) {
|
|
477
|
+
parts.push(`Working directory: ${context.workingDirectory}`);
|
|
478
|
+
}
|
|
479
|
+
return parts.length > 0 ? `\nContext: ${parts.join(', ')}` : '';
|
|
480
|
+
}
|
|
481
|
+
combineResults(patternResult, aiResult, entities) {
|
|
482
|
+
// Use AI result as base, but boost confidence if pattern matching agrees
|
|
483
|
+
let finalResult = { ...aiResult };
|
|
484
|
+
if (patternResult.intent === aiResult.intent) {
|
|
485
|
+
finalResult.confidence = Math.min(0.98, aiResult.confidence + 0.1);
|
|
486
|
+
finalResult.reasoning += ' (confirmed by pattern matching)';
|
|
487
|
+
}
|
|
488
|
+
else if (patternResult.confidence > 0.8) {
|
|
489
|
+
// High-confidence pattern match might override AI
|
|
490
|
+
if (patternResult.confidence > aiResult.confidence) {
|
|
491
|
+
finalResult = patternResult;
|
|
492
|
+
finalResult.reasoning +=
|
|
493
|
+
' (overridden by high-confidence pattern match)';
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
// Ensure entities are included
|
|
497
|
+
if (finalResult.context) {
|
|
498
|
+
finalResult.context.entities = entities;
|
|
499
|
+
}
|
|
500
|
+
return finalResult;
|
|
501
|
+
}
|
|
502
|
+
async validateAndEnrich(result, availableCommands, context) {
|
|
503
|
+
// Validate that the intent command is available
|
|
504
|
+
if (!availableCommands.includes(result.intent)) {
|
|
505
|
+
logger_1.logger.warn(`Intent "${result.intent}" not in available commands`);
|
|
506
|
+
result.confidence *= 0.5;
|
|
507
|
+
result.clarification = `The command "${result.intent}" is not available. Did you mean one of: ${availableCommands.join(', ')}?`;
|
|
508
|
+
}
|
|
509
|
+
// Add safety warnings for destructive commands
|
|
510
|
+
const commandPattern = this.commandPatterns.get(result.intent);
|
|
511
|
+
if (commandPattern?.destructive) {
|
|
512
|
+
result.clarification =
|
|
513
|
+
'This is a destructive operation. Are you sure you want to proceed?';
|
|
514
|
+
}
|
|
515
|
+
// Enrich with context-aware suggestions
|
|
516
|
+
if (result.confidence < this.config.confidenceThreshold) {
|
|
517
|
+
result.alternatives = await this.getContextualAlternatives(result, availableCommands, context);
|
|
518
|
+
}
|
|
519
|
+
return result;
|
|
520
|
+
}
|
|
521
|
+
async getContextualAlternatives(result, availableCommands, context) {
|
|
522
|
+
const alternatives = [];
|
|
523
|
+
// Add pattern-based alternatives
|
|
524
|
+
for (const command of availableCommands) {
|
|
525
|
+
if (command !== result.intent) {
|
|
526
|
+
const pattern = this.commandPatterns.get(command);
|
|
527
|
+
if (pattern) {
|
|
528
|
+
const confidence = this.calculatePatternScore(result.command || '', pattern);
|
|
529
|
+
if (confidence > 0.3) {
|
|
530
|
+
alternatives.push({
|
|
531
|
+
command: `wundr ${command}`,
|
|
532
|
+
confidence,
|
|
533
|
+
description: `Alternative: ${pattern.examples[0] || command}`,
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
// Sort and limit alternatives
|
|
540
|
+
alternatives.sort((a, b) => b.confidence - a.confidence);
|
|
541
|
+
return alternatives.slice(0, this.config.maxAlternatives);
|
|
542
|
+
}
|
|
543
|
+
fallbackIntentParsing(input, availableCommands, context) {
|
|
544
|
+
// Simple keyword matching as last resort
|
|
545
|
+
const keywords = input.split(/\s+/);
|
|
546
|
+
const bestMatch = 'help';
|
|
547
|
+
const bestScore = 0;
|
|
548
|
+
for (const command of availableCommands) {
|
|
549
|
+
if (keywords.includes(command)) {
|
|
550
|
+
return {
|
|
551
|
+
intent: command,
|
|
552
|
+
confidence: 0.6,
|
|
553
|
+
command: `wundr ${command}`,
|
|
554
|
+
parameters: {},
|
|
555
|
+
reasoning: 'Fallback keyword matching',
|
|
556
|
+
context: { entities: [], keywords, sentiment: 'neutral' },
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return {
|
|
561
|
+
intent: bestMatch,
|
|
562
|
+
confidence: 0.3,
|
|
563
|
+
command: `wundr ${bestMatch}`,
|
|
564
|
+
parameters: {},
|
|
565
|
+
clarification: `I couldn't understand "${input}". Type "help" to see available commands.`,
|
|
566
|
+
reasoning: 'Fallback to help command',
|
|
567
|
+
context: { entities: [], keywords, sentiment: 'neutral' },
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
fallbackParameterExtraction(input, pattern) {
|
|
571
|
+
const parameters = {};
|
|
572
|
+
const words = input.split(/\s+/);
|
|
573
|
+
// Simple heuristic parameter extraction
|
|
574
|
+
for (const param of pattern.parameters) {
|
|
575
|
+
if (param.type === 'path') {
|
|
576
|
+
const pathMatch = input.match(/(?:\.\/|\/|~\/)[^\s]+/);
|
|
577
|
+
if (pathMatch) {
|
|
578
|
+
parameters[param.name] = pathMatch[0];
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
else if (param.type === 'boolean') {
|
|
582
|
+
if (words.some(word => ['yes', 'true', 'on', 'enable'].includes(word.toLowerCase()))) {
|
|
583
|
+
parameters[param.name] = true;
|
|
584
|
+
}
|
|
585
|
+
else if (words.some(word => ['no', 'false', 'off', 'disable'].includes(word.toLowerCase()))) {
|
|
586
|
+
parameters[param.name] = false;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
// Apply default values
|
|
590
|
+
if (!parameters[param.name] && param.defaultValue !== undefined) {
|
|
591
|
+
parameters[param.name] = param.defaultValue;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return parameters;
|
|
595
|
+
}
|
|
596
|
+
getPatternSuggestions(partialInput, availableCommands) {
|
|
597
|
+
const suggestions = [];
|
|
598
|
+
for (const command of availableCommands) {
|
|
599
|
+
const pattern = this.commandPatterns.get(command);
|
|
600
|
+
if (!pattern) {
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
// Check if partial input matches command or examples
|
|
604
|
+
const confidence = Math.max(this.calculateStringSimilarity(partialInput, command), ...pattern.examples.map(ex => this.calculateStringSimilarity(partialInput, ex)));
|
|
605
|
+
if (confidence > 0.3) {
|
|
606
|
+
suggestions.push({
|
|
607
|
+
command: `wundr ${command}`,
|
|
608
|
+
description: pattern.examples[0] || `Run ${command} command`,
|
|
609
|
+
confidence,
|
|
610
|
+
completion: pattern.examples[0] || `wundr ${command}`,
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return suggestions;
|
|
615
|
+
}
|
|
616
|
+
async getAISuggestions(partialInput, availableCommands, context, limit) {
|
|
617
|
+
const systemPrompt = `You are a CLI auto-completion assistant. Based on partial user input, suggest the most likely command completions.
|
|
618
|
+
|
|
619
|
+
Available commands: ${availableCommands.join(', ')}
|
|
620
|
+
Partial input: "${partialInput}"
|
|
621
|
+
|
|
622
|
+
Provide ${limit} suggestions in JSON format:
|
|
623
|
+
{
|
|
624
|
+
"suggestions": [
|
|
625
|
+
{
|
|
626
|
+
"command": "wundr analyze",
|
|
627
|
+
"description": "Analyze the project for issues",
|
|
628
|
+
"confidence": 0.9,
|
|
629
|
+
"completion": "wundr analyze --path ."
|
|
630
|
+
}
|
|
631
|
+
]
|
|
632
|
+
}`;
|
|
633
|
+
try {
|
|
634
|
+
const response = await this.claudeClient.sendMessage('', systemPrompt, {
|
|
635
|
+
temperature: 0.3,
|
|
636
|
+
maxTokens: 1024,
|
|
637
|
+
});
|
|
638
|
+
const result = JSON.parse(response.trim());
|
|
639
|
+
return result.suggestions || [];
|
|
640
|
+
}
|
|
641
|
+
catch (error) {
|
|
642
|
+
logger_1.logger.error('AI suggestions failed:', error);
|
|
643
|
+
return [];
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
extractKeywords(input) {
|
|
647
|
+
// Simple keyword extraction
|
|
648
|
+
const stopWords = [
|
|
649
|
+
'the',
|
|
650
|
+
'and',
|
|
651
|
+
'or',
|
|
652
|
+
'but',
|
|
653
|
+
'in',
|
|
654
|
+
'on',
|
|
655
|
+
'at',
|
|
656
|
+
'to',
|
|
657
|
+
'for',
|
|
658
|
+
'of',
|
|
659
|
+
'with',
|
|
660
|
+
'by',
|
|
661
|
+
'is',
|
|
662
|
+
'are',
|
|
663
|
+
'was',
|
|
664
|
+
'were',
|
|
665
|
+
'be',
|
|
666
|
+
'been',
|
|
667
|
+
'have',
|
|
668
|
+
'has',
|
|
669
|
+
'had',
|
|
670
|
+
'do',
|
|
671
|
+
'does',
|
|
672
|
+
'did',
|
|
673
|
+
'will',
|
|
674
|
+
'would',
|
|
675
|
+
'could',
|
|
676
|
+
'should',
|
|
677
|
+
];
|
|
678
|
+
return input
|
|
679
|
+
.toLowerCase()
|
|
680
|
+
.split(/\s+/)
|
|
681
|
+
.filter(word => word.length > 2 && !stopWords.includes(word))
|
|
682
|
+
.slice(0, 10); // Limit to 10 keywords
|
|
683
|
+
}
|
|
684
|
+
analyzeSentiment(input) {
|
|
685
|
+
const positiveWords = [
|
|
686
|
+
'good',
|
|
687
|
+
'great',
|
|
688
|
+
'excellent',
|
|
689
|
+
'awesome',
|
|
690
|
+
'perfect',
|
|
691
|
+
'love',
|
|
692
|
+
'like',
|
|
693
|
+
'thanks',
|
|
694
|
+
'help',
|
|
695
|
+
'please',
|
|
696
|
+
];
|
|
697
|
+
const negativeWords = [
|
|
698
|
+
'bad',
|
|
699
|
+
'terrible',
|
|
700
|
+
'awful',
|
|
701
|
+
'hate',
|
|
702
|
+
'problem',
|
|
703
|
+
'error',
|
|
704
|
+
'issue',
|
|
705
|
+
'broken',
|
|
706
|
+
'fail',
|
|
707
|
+
'wrong',
|
|
708
|
+
];
|
|
709
|
+
const words = input.toLowerCase().split(/\s+/);
|
|
710
|
+
const positiveCount = words.filter(word => positiveWords.includes(word)).length;
|
|
711
|
+
const negativeCount = words.filter(word => negativeWords.includes(word)).length;
|
|
712
|
+
if (positiveCount > negativeCount) {
|
|
713
|
+
return 'positive';
|
|
714
|
+
}
|
|
715
|
+
if (negativeCount > positiveCount) {
|
|
716
|
+
return 'negative';
|
|
717
|
+
}
|
|
718
|
+
return 'neutral';
|
|
719
|
+
}
|
|
720
|
+
cacheResult(key, result) {
|
|
721
|
+
this.intentCache.set(key, {
|
|
722
|
+
result,
|
|
723
|
+
timestamp: Date.now(),
|
|
724
|
+
});
|
|
725
|
+
// Clean old entries periodically
|
|
726
|
+
if (this.intentCache.size % 100 === 0) {
|
|
727
|
+
this.cleanCache();
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
cleanCache() {
|
|
731
|
+
const now = Date.now();
|
|
732
|
+
const expiredKeys = [];
|
|
733
|
+
for (const [key, entry] of this.intentCache) {
|
|
734
|
+
if (now - entry.timestamp > this.config.cacheDuration) {
|
|
735
|
+
expiredKeys.push(key);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
expiredKeys.forEach(key => this.intentCache.delete(key));
|
|
739
|
+
if (expiredKeys.length > 0) {
|
|
740
|
+
logger_1.logger.debug(`Cleaned ${expiredKeys.length} expired cache entries`);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
exports.IntentParser = IntentParser;
|
|
745
|
+
exports.default = IntentParser;
|
|
746
|
+
//# sourceMappingURL=intent-parser.js.map
|