clavix 2.8.2 ā 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -6
- package/dist/cli/commands/deep.d.ts +3 -4
- package/dist/cli/commands/deep.js +162 -261
- package/dist/cli/commands/fast.d.ts +3 -4
- package/dist/cli/commands/fast.js +126 -303
- package/dist/cli/commands/init.js +184 -22
- package/dist/cli/commands/prd.d.ts +7 -6
- package/dist/cli/commands/prd.js +113 -132
- package/dist/cli/commands/summarize.d.ts +1 -12
- package/dist/cli/commands/summarize.js +63 -131
- package/dist/core/intelligence/index.d.ts +10 -0
- package/dist/core/intelligence/index.js +13 -0
- package/dist/core/intelligence/intent-detector.d.ts +33 -0
- package/dist/core/intelligence/intent-detector.js +311 -0
- package/dist/core/intelligence/pattern-library.d.ts +44 -0
- package/dist/core/intelligence/pattern-library.js +103 -0
- package/dist/core/intelligence/patterns/actionability-enhancer.d.ts +27 -0
- package/dist/core/intelligence/patterns/actionability-enhancer.js +162 -0
- package/dist/core/intelligence/patterns/base-pattern.d.ts +31 -0
- package/dist/core/intelligence/patterns/base-pattern.js +39 -0
- package/dist/core/intelligence/patterns/completeness-validator.d.ts +27 -0
- package/dist/core/intelligence/patterns/completeness-validator.js +135 -0
- package/dist/core/intelligence/patterns/conciseness-filter.d.ts +12 -0
- package/dist/core/intelligence/patterns/conciseness-filter.js +61 -0
- package/dist/core/intelligence/patterns/objective-clarifier.d.ts +14 -0
- package/dist/core/intelligence/patterns/objective-clarifier.js +97 -0
- package/dist/core/intelligence/patterns/structure-organizer.d.ts +31 -0
- package/dist/core/intelligence/patterns/structure-organizer.js +185 -0
- package/dist/core/intelligence/patterns/technical-context-enricher.d.ts +16 -0
- package/dist/core/intelligence/patterns/technical-context-enricher.js +132 -0
- package/dist/core/intelligence/quality-assessor.d.ts +42 -0
- package/dist/core/intelligence/quality-assessor.js +296 -0
- package/dist/core/intelligence/types.d.ts +81 -0
- package/dist/core/intelligence/types.js +3 -0
- package/dist/core/intelligence/universal-optimizer.d.ts +31 -0
- package/dist/core/intelligence/universal-optimizer.js +118 -0
- package/dist/core/prd-generator.d.ts +2 -2
- package/dist/core/task-manager.js +18 -5
- package/dist/templates/agents/agents.md +2 -2
- package/dist/templates/agents/copilot-instructions.md +15 -15
- package/dist/templates/agents/octo.md +35 -30
- package/dist/templates/agents/warp.md +3 -3
- package/dist/templates/full-prd-template.hbs +1 -1
- package/dist/templates/prd-questions.md +1 -1
- package/dist/templates/quick-prd-template.hbs +1 -1
- package/dist/templates/slash-commands/_canonical/deep.md +261 -122
- package/dist/templates/slash-commands/_canonical/fast.md +101 -69
- package/dist/templates/slash-commands/_canonical/implement.md +1 -1
- package/dist/templates/slash-commands/_canonical/plan.md +12 -12
- package/dist/templates/slash-commands/_canonical/prd.md +34 -24
- package/dist/templates/slash-commands/_canonical/start.md +13 -12
- package/dist/templates/slash-commands/_canonical/summarize.md +42 -25
- package/dist/utils/error-utils.d.ts +7 -0
- package/dist/utils/error-utils.js +17 -0
- package/package.json +21 -12
|
@@ -4,9 +4,9 @@ import * as path from 'path';
|
|
|
4
4
|
import { SessionManager } from '../../core/session-manager.js';
|
|
5
5
|
import { ConversationAnalyzer } from '../../core/conversation-analyzer.js';
|
|
6
6
|
import { FileSystem } from '../../utils/file-system.js';
|
|
7
|
-
import {
|
|
7
|
+
import { UniversalOptimizer } from '../../core/intelligence/index.js';
|
|
8
8
|
export default class Summarize extends Command {
|
|
9
|
-
static description = 'Analyze a conversation session and extract structured requirements';
|
|
9
|
+
static description = 'Analyze a conversation session and extract structured requirements with automatic optimization';
|
|
10
10
|
static examples = [
|
|
11
11
|
'<%= config.bin %> <%= command.id %>',
|
|
12
12
|
'<%= config.bin %> <%= command.id %> <session-id>',
|
|
@@ -28,14 +28,10 @@ export default class Summarize extends Command {
|
|
|
28
28
|
char: 'o',
|
|
29
29
|
description: 'Output directory (defaults to .clavix/outputs/[session-name])',
|
|
30
30
|
}),
|
|
31
|
-
'skip-clear': Flags.boolean({
|
|
32
|
-
description: 'Skip CLEAR framework optimization of extracted prompt',
|
|
33
|
-
default: false,
|
|
34
|
-
}),
|
|
35
31
|
};
|
|
36
32
|
async run() {
|
|
37
33
|
const { args, flags } = await this.parse(Summarize);
|
|
38
|
-
console.log(chalk.bold.cyan('\
|
|
34
|
+
console.log(chalk.bold.cyan('\nš Conversation Summarizer\n'));
|
|
39
35
|
try {
|
|
40
36
|
const manager = new SessionManager();
|
|
41
37
|
const analyzer = new ConversationAnalyzer();
|
|
@@ -91,35 +87,27 @@ export default class Summarize extends Command {
|
|
|
91
87
|
const miniPrdContent = analyzer.generateMiniPrd(session, analysis);
|
|
92
88
|
const miniPrdPath = path.join(outputDir, 'mini-prd.md');
|
|
93
89
|
await FileSystem.writeFileAtomic(miniPrdPath, miniPrdContent);
|
|
94
|
-
// Generate optimized prompt
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
90
|
+
// Generate optimized prompt (initial extraction)
|
|
91
|
+
const rawPromptContent = analyzer.generateOptimizedPrompt(session, analysis);
|
|
92
|
+
// Save original extracted version
|
|
93
|
+
const originalPromptPath = path.join(outputDir, 'original-prompt.md');
|
|
94
|
+
await FileSystem.writeFileAtomic(originalPromptPath, rawPromptContent);
|
|
95
|
+
// Always apply optimization with Universal Optimizer
|
|
96
|
+
await this.applyOptimization(rawPromptContent, outputDir);
|
|
102
97
|
// Display success
|
|
103
|
-
console.log(chalk.bold.green('Analysis complete!\n'));
|
|
98
|
+
console.log(chalk.bold.green('\nā Analysis complete!\n'));
|
|
104
99
|
console.log(chalk.bold('Generated files:'));
|
|
105
100
|
console.log(chalk.gray(' ⢠') + chalk.cyan('mini-prd.md') + chalk.dim(' - Structured requirements document'));
|
|
106
|
-
console.log(chalk.gray(' ⢠') + chalk.cyan('
|
|
107
|
-
|
|
108
|
-
console.log(chalk.gray(' ⢠') + chalk.cyan('clear-optimized-prompt.md') + chalk.dim(' - CLEAR-enhanced version (C, L, E)'));
|
|
109
|
-
}
|
|
101
|
+
console.log(chalk.gray(' ⢠') + chalk.cyan('original-prompt.md') + chalk.dim(' - Raw extracted prompt'));
|
|
102
|
+
console.log(chalk.gray(' ⢠') + chalk.cyan('optimized-prompt.md') + chalk.dim(' - Enhanced AI-ready prompt'));
|
|
110
103
|
console.log();
|
|
111
104
|
console.log(chalk.bold('Output location:'));
|
|
112
105
|
console.log(chalk.dim(` ${outputDir}`));
|
|
113
106
|
console.log();
|
|
114
|
-
console.log(chalk.bold('Next steps:'));
|
|
115
|
-
|
|
116
|
-
console.log(chalk.gray(' ⢠Use ') + chalk.cyan('clear-optimized-prompt.md') + chalk.gray(' for best AI results (CLEAR-optimized)'));
|
|
117
|
-
console.log(chalk.gray(' ⢠Or use ') + chalk.cyan('optimized-prompt.md') + chalk.gray(' for the original extracted version'));
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
console.log(chalk.gray(' ⢠Use ') + chalk.cyan('optimized-prompt.md') + chalk.gray(' as input for your AI agent'));
|
|
121
|
-
}
|
|
107
|
+
console.log(chalk.bold('š” Next steps:'));
|
|
108
|
+
console.log(chalk.gray(' ⢠Use ') + chalk.cyan('optimized-prompt.md') + chalk.gray(' for best AI results'));
|
|
122
109
|
console.log(chalk.gray(' ⢠Share ') + chalk.cyan('mini-prd.md') + chalk.gray(' with your team for alignment'));
|
|
110
|
+
console.log(chalk.gray(' ⢠Run ') + chalk.cyan('clavix implement') + chalk.gray(' to start development'));
|
|
123
111
|
console.log();
|
|
124
112
|
}
|
|
125
113
|
catch (error) {
|
|
@@ -127,129 +115,73 @@ export default class Summarize extends Command {
|
|
|
127
115
|
this.error(errorMessage);
|
|
128
116
|
}
|
|
129
117
|
}
|
|
130
|
-
/**
|
|
131
|
-
* Display analysis summary
|
|
132
|
-
*/
|
|
133
118
|
displayAnalysisSummary(analysis) {
|
|
134
|
-
console.log(chalk.bold('Analysis Summary
|
|
135
|
-
console.log();
|
|
119
|
+
console.log(chalk.bold.cyan('Analysis Summary:\n'));
|
|
136
120
|
if (analysis.keyRequirements.length > 0) {
|
|
137
|
-
console.log(chalk.bold
|
|
138
|
-
analysis.keyRequirements.forEach((req) => {
|
|
139
|
-
console.log(chalk.gray(
|
|
121
|
+
console.log(chalk.bold('Key Requirements:'));
|
|
122
|
+
analysis.keyRequirements.slice(0, 5).forEach((req, i) => {
|
|
123
|
+
console.log(chalk.gray(` ${i + 1}. ${req}`));
|
|
140
124
|
});
|
|
125
|
+
if (analysis.keyRequirements.length > 5) {
|
|
126
|
+
console.log(chalk.dim(` ... and ${analysis.keyRequirements.length - 5} more`));
|
|
127
|
+
}
|
|
141
128
|
console.log();
|
|
142
129
|
}
|
|
143
130
|
if (analysis.technicalConstraints.length > 0) {
|
|
144
|
-
console.log(chalk.bold
|
|
145
|
-
analysis.technicalConstraints.forEach(
|
|
146
|
-
console.log(chalk.gray(
|
|
131
|
+
console.log(chalk.bold('Technical Constraints:'));
|
|
132
|
+
analysis.technicalConstraints.slice(0, 3).forEach(constraint => {
|
|
133
|
+
console.log(chalk.gray(` ⢠${constraint}`));
|
|
147
134
|
});
|
|
135
|
+
if (analysis.technicalConstraints.length > 3) {
|
|
136
|
+
console.log(chalk.dim(` ... and ${analysis.technicalConstraints.length - 3} more`));
|
|
137
|
+
}
|
|
148
138
|
console.log();
|
|
149
139
|
}
|
|
150
140
|
if (analysis.successCriteria.length > 0) {
|
|
151
|
-
console.log(chalk.bold
|
|
152
|
-
analysis.successCriteria.forEach(
|
|
153
|
-
console.log(chalk.gray(
|
|
154
|
-
});
|
|
155
|
-
console.log();
|
|
156
|
-
}
|
|
157
|
-
if (analysis.outOfScope.length > 0) {
|
|
158
|
-
console.log(chalk.bold.yellow('Out of Scope:'));
|
|
159
|
-
analysis.outOfScope.forEach((item) => {
|
|
160
|
-
console.log(chalk.gray(' ⢠') + item);
|
|
141
|
+
console.log(chalk.bold('Success Criteria:'));
|
|
142
|
+
analysis.successCriteria.slice(0, 3).forEach(criterion => {
|
|
143
|
+
console.log(chalk.gray(` ā ${criterion}`));
|
|
161
144
|
});
|
|
145
|
+
if (analysis.successCriteria.length > 3) {
|
|
146
|
+
console.log(chalk.dim(` ... and ${analysis.successCriteria.length - 3} more`));
|
|
147
|
+
}
|
|
162
148
|
console.log();
|
|
163
149
|
}
|
|
164
150
|
}
|
|
165
|
-
|
|
166
|
-
* Sanitize project name for directory name
|
|
167
|
-
*/
|
|
168
|
-
sanitizeProjectName(name) {
|
|
169
|
-
return name
|
|
170
|
-
.toLowerCase()
|
|
171
|
-
.replace(/[^a-z0-9-]/g, '-')
|
|
172
|
-
.replace(/-+/g, '-')
|
|
173
|
-
.replace(/^-|-$/g, '')
|
|
174
|
-
.substring(0, 50);
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Apply CLEAR framework optimization to extracted prompt
|
|
178
|
-
* Shows both raw extraction and CLEAR-enhanced version
|
|
179
|
-
*/
|
|
180
|
-
async applyClearOptimization(rawPrompt, outputDir) {
|
|
151
|
+
async applyOptimization(rawPrompt, outputDir) {
|
|
181
152
|
try {
|
|
182
|
-
console.log(chalk.
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return chalk.yellow;
|
|
192
|
-
return chalk.red;
|
|
193
|
-
};
|
|
194
|
-
// Display comparison
|
|
195
|
-
console.log(chalk.bold('CLEAR Analysis of Extracted Prompt:\n'));
|
|
196
|
-
// Conciseness
|
|
197
|
-
const cColor = getScoreColor(clearScore.conciseness);
|
|
198
|
-
console.log(cColor(` [C] Concise: ${clearScore.conciseness.toFixed(0)}%`));
|
|
199
|
-
if (clearResult.conciseness.suggestions.length > 0) {
|
|
200
|
-
console.log(cColor(` ${clearResult.conciseness.suggestions[0]}`));
|
|
201
|
-
}
|
|
202
|
-
console.log();
|
|
203
|
-
// Logic
|
|
204
|
-
const lColor = getScoreColor(clearScore.logic);
|
|
205
|
-
console.log(lColor(` [L] Logical: ${clearScore.logic.toFixed(0)}%`));
|
|
206
|
-
if (clearResult.logic.suggestions.length > 0) {
|
|
207
|
-
console.log(lColor(` ${clearResult.logic.suggestions[0]}`));
|
|
208
|
-
}
|
|
209
|
-
console.log();
|
|
210
|
-
// Explicitness
|
|
211
|
-
const eColor = getScoreColor(clearScore.explicitness);
|
|
212
|
-
console.log(eColor(` [E] Explicit: ${clearScore.explicitness.toFixed(0)}%`));
|
|
213
|
-
if (clearResult.explicitness.suggestions.length > 0) {
|
|
214
|
-
console.log(eColor(` ${clearResult.explicitness.suggestions[0]}`));
|
|
153
|
+
console.log(chalk.dim('Optimizing extracted prompt...\n'));
|
|
154
|
+
const optimizer = new UniversalOptimizer();
|
|
155
|
+
const result = await optimizer.optimize(rawPrompt, 'fast');
|
|
156
|
+
// Display optimization results
|
|
157
|
+
console.log(chalk.bold('⨠Optimization Results:\n'));
|
|
158
|
+
console.log(chalk.cyan(` Intent: ${result.intent.primaryIntent}`));
|
|
159
|
+
console.log(chalk.cyan(` Quality: ${result.quality.overall.toFixed(0)}%`));
|
|
160
|
+
if (result.improvements.length > 0) {
|
|
161
|
+
console.log(chalk.cyan(` Improvements: ${result.improvements.length} applied\n`));
|
|
215
162
|
}
|
|
216
|
-
|
|
217
|
-
// Overall
|
|
218
|
-
const overallColor = getScoreColor(clearScore.overall);
|
|
219
|
-
console.log(overallColor(` Overall: ${clearScore.overall.toFixed(0)}% (${clearScore.rating})\n`));
|
|
220
|
-
// Display CLEAR changes made
|
|
221
|
-
if (clearResult.changesSummary && clearResult.changesSummary.length > 0) {
|
|
222
|
-
console.log(chalk.bold.magenta('CLEAR Improvements Applied:\n'));
|
|
223
|
-
clearResult.changesSummary.slice(0, 3).forEach((change) => {
|
|
224
|
-
console.log(chalk.magenta(` [${change.component}] ${change.change}`));
|
|
225
|
-
});
|
|
163
|
+
else {
|
|
226
164
|
console.log();
|
|
227
165
|
}
|
|
228
|
-
// Save
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
${clearResult.improvedPrompt}
|
|
233
|
-
|
|
234
|
-
---
|
|
235
|
-
|
|
236
|
-
## CLEAR Framework Assessment
|
|
237
|
-
|
|
238
|
-
- **[C] Concise**: ${clearScore.conciseness.toFixed(0)}% - ${clearResult.conciseness.suggestions[0] || 'Good'}
|
|
239
|
-
- **[L] Logical**: ${clearScore.logic.toFixed(0)}% - ${clearResult.logic.suggestions[0] || 'Good'}
|
|
240
|
-
- **[E] Explicit**: ${clearScore.explicitness.toFixed(0)}% - ${clearResult.explicitness.suggestions[0] || 'Good'}
|
|
241
|
-
- **Overall**: ${clearScore.overall.toFixed(0)}% (${clearScore.rating})
|
|
242
|
-
|
|
243
|
-
## Changes Applied
|
|
244
|
-
|
|
245
|
-
${clearResult.changesSummary.map((c) => `- **[${c.component}]** ${c.change}`).join('\n')}
|
|
246
|
-
`;
|
|
247
|
-
await FileSystem.writeFileAtomic(clearOptimizedPath, clearOptimizedContent);
|
|
248
|
-
console.log(chalk.green('ā CLEAR-optimized version saved\n'));
|
|
166
|
+
// Save optimized version
|
|
167
|
+
const optimizedPath = path.join(outputDir, 'optimized-prompt.md');
|
|
168
|
+
await FileSystem.writeFileAtomic(optimizedPath, result.enhanced);
|
|
249
169
|
}
|
|
250
|
-
catch {
|
|
251
|
-
console.log(chalk.yellow('
|
|
170
|
+
catch (error) {
|
|
171
|
+
console.log(chalk.yellow('ā ļø Could not optimize prompt'));
|
|
172
|
+
console.log(chalk.gray('Using original extracted version...\n'));
|
|
173
|
+
// Fallback: copy original to optimized
|
|
174
|
+
const originalPath = path.join(outputDir, 'original-prompt.md');
|
|
175
|
+
const optimizedPath = path.join(outputDir, 'optimized-prompt.md');
|
|
176
|
+
await FileSystem.writeFileAtomic(optimizedPath, rawPrompt);
|
|
252
177
|
}
|
|
253
178
|
}
|
|
179
|
+
sanitizeProjectName(name) {
|
|
180
|
+
return name
|
|
181
|
+
.toLowerCase()
|
|
182
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
183
|
+
.replace(/-+/g, '-')
|
|
184
|
+
.replace(/^-|-$/g, '') || 'unnamed-project';
|
|
185
|
+
}
|
|
254
186
|
}
|
|
255
187
|
//# sourceMappingURL=summarize.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { UniversalOptimizer } from './universal-optimizer.js';
|
|
2
|
+
export { IntentDetector } from './intent-detector.js';
|
|
3
|
+
export { PatternLibrary } from './pattern-library.js';
|
|
4
|
+
export { QualityAssessor } from './quality-assessor.js';
|
|
5
|
+
export * from './types.js';
|
|
6
|
+
export { BasePattern } from './patterns/base-pattern.js';
|
|
7
|
+
export { ConcisenessFilter } from './patterns/conciseness-filter.js';
|
|
8
|
+
export { ObjectiveClarifier } from './patterns/objective-clarifier.js';
|
|
9
|
+
export { TechnicalContextEnricher } from './patterns/technical-context-enricher.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Main exports for the universal prompt intelligence system
|
|
2
|
+
export { UniversalOptimizer } from './universal-optimizer.js';
|
|
3
|
+
export { IntentDetector } from './intent-detector.js';
|
|
4
|
+
export { PatternLibrary } from './pattern-library.js';
|
|
5
|
+
export { QualityAssessor } from './quality-assessor.js';
|
|
6
|
+
// Type exports
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
// Pattern exports
|
|
9
|
+
export { BasePattern } from './patterns/base-pattern.js';
|
|
10
|
+
export { ConcisenessFilter } from './patterns/conciseness-filter.js';
|
|
11
|
+
export { ObjectiveClarifier } from './patterns/objective-clarifier.js';
|
|
12
|
+
export { TechnicalContextEnricher } from './patterns/technical-context-enricher.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { IntentAnalysis } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Enhanced Intent Detector with weighted scoring and phrase-based detection
|
|
4
|
+
* Target Accuracy: 95%+
|
|
5
|
+
*/
|
|
6
|
+
export declare class IntentDetector {
|
|
7
|
+
private readonly STRONG_CODE_KEYWORDS;
|
|
8
|
+
private readonly STRONG_PLANNING_KEYWORDS;
|
|
9
|
+
private readonly STRONG_DEBUGGING_KEYWORDS;
|
|
10
|
+
private readonly STRONG_DOCUMENTATION_KEYWORDS;
|
|
11
|
+
private readonly STRONG_REFINEMENT_KEYWORDS;
|
|
12
|
+
private readonly CODE_KEYWORDS;
|
|
13
|
+
private readonly PLANNING_KEYWORDS;
|
|
14
|
+
private readonly REFINEMENT_KEYWORDS;
|
|
15
|
+
private readonly DEBUGGING_KEYWORDS;
|
|
16
|
+
private readonly DOCUMENTATION_KEYWORDS;
|
|
17
|
+
private readonly WEAK_CODE_KEYWORDS;
|
|
18
|
+
private readonly NEGATION_WORDS;
|
|
19
|
+
analyze(prompt: string): IntentAnalysis;
|
|
20
|
+
private calculateIntentScore;
|
|
21
|
+
private getKeywordsForIntent;
|
|
22
|
+
private applyNegation;
|
|
23
|
+
private getContextBonus;
|
|
24
|
+
private selectPrimaryIntent;
|
|
25
|
+
private calculateConfidence;
|
|
26
|
+
private hasCodeContext;
|
|
27
|
+
private hasTechnicalTerms;
|
|
28
|
+
private hasPerformanceTerms;
|
|
29
|
+
private isOpenEnded;
|
|
30
|
+
private needsStructure;
|
|
31
|
+
private suggestMode;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=intent-detector.d.ts.map
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Intent Detector with weighted scoring and phrase-based detection
|
|
3
|
+
* Target Accuracy: 95%+
|
|
4
|
+
*/
|
|
5
|
+
export class IntentDetector {
|
|
6
|
+
// Strong indicators (20 points)
|
|
7
|
+
STRONG_CODE_KEYWORDS = [
|
|
8
|
+
'create function', 'build component', 'implement feature', 'add endpoint',
|
|
9
|
+
'write class', 'develop api', 'generate code'
|
|
10
|
+
];
|
|
11
|
+
STRONG_PLANNING_KEYWORDS = [
|
|
12
|
+
'how should i', 'what\'s the best way', 'pros and cons', 'architecture for',
|
|
13
|
+
'design pattern', 'system design', 'should i use', 'help me choose',
|
|
14
|
+
'design the database', 'plan the', 'requirements document'
|
|
15
|
+
];
|
|
16
|
+
STRONG_DEBUGGING_KEYWORDS = [
|
|
17
|
+
'fix error', 'debug issue', 'doesn\'t work', 'throws error', 'not working',
|
|
18
|
+
'returns null', 'undefined error', 'stack trace', 'error message',
|
|
19
|
+
'causing this bug', 'how do i fix', 'fix this error', 'resolve the', 'memory leak',
|
|
20
|
+
'not rendering', 'why is my'
|
|
21
|
+
];
|
|
22
|
+
STRONG_DOCUMENTATION_KEYWORDS = [
|
|
23
|
+
'explain how', 'walk me through', 'how does this work', 'show me how',
|
|
24
|
+
'document this', 'describe how', 'what does this do', 'write documentation',
|
|
25
|
+
'create documentation', 'add documentation', 'api documentation', 'add comments'
|
|
26
|
+
];
|
|
27
|
+
STRONG_REFINEMENT_KEYWORDS = [
|
|
28
|
+
'make it faster', 'speed up', 'reduce time', 'optimize performance',
|
|
29
|
+
'clean up code', 'refactor this', 'improve efficiency', 'make this component',
|
|
30
|
+
'make it more', 'enhance the', 'update the styling', 'more reusable', 'more modern'
|
|
31
|
+
];
|
|
32
|
+
// Medium indicators (10 points)
|
|
33
|
+
CODE_KEYWORDS = [
|
|
34
|
+
'function', 'class', 'component', 'api', 'endpoint', 'database',
|
|
35
|
+
'implement', 'build', 'create', 'write', 'code', 'develop'
|
|
36
|
+
];
|
|
37
|
+
PLANNING_KEYWORDS = [
|
|
38
|
+
'plan', 'design', 'architect', 'strategy', 'approach', 'structure',
|
|
39
|
+
'organize', 'layout', 'workflow'
|
|
40
|
+
];
|
|
41
|
+
REFINEMENT_KEYWORDS = [
|
|
42
|
+
'improve', 'optimize', 'refactor', 'enhance', 'better', 'faster',
|
|
43
|
+
'cleaner', 'simplify', 'reduce', 'increase'
|
|
44
|
+
];
|
|
45
|
+
DEBUGGING_KEYWORDS = [
|
|
46
|
+
'fix', 'debug', 'error', 'bug', 'issue', 'problem', 'failing',
|
|
47
|
+
'broken', 'crash', 'exception', 'incorrect', 'wrong'
|
|
48
|
+
];
|
|
49
|
+
DOCUMENTATION_KEYWORDS = [
|
|
50
|
+
'explain', 'document', 'describe', 'understand',
|
|
51
|
+
'clarify', 'comment', 'documentation', 'guide', 'tutorial'
|
|
52
|
+
];
|
|
53
|
+
// Weak indicators (5 points)
|
|
54
|
+
WEAK_CODE_KEYWORDS = [
|
|
55
|
+
'react', 'vue', 'angular', 'python', 'javascript', 'typescript',
|
|
56
|
+
'java', 'rust', 'go', 'php', 'ruby', 'swift', 'kotlin', 'system', 'feature'
|
|
57
|
+
];
|
|
58
|
+
// Negation words (reduces score by 50%)
|
|
59
|
+
NEGATION_WORDS = [
|
|
60
|
+
'don\'t', 'dont', 'not', 'avoid', 'without', 'never', 'no'
|
|
61
|
+
];
|
|
62
|
+
analyze(prompt) {
|
|
63
|
+
const lowerPrompt = prompt.toLowerCase();
|
|
64
|
+
const words = lowerPrompt.split(/\s+/);
|
|
65
|
+
// Calculate weighted scores for each intent
|
|
66
|
+
const scores = {
|
|
67
|
+
'code-generation': this.calculateIntentScore(lowerPrompt, words, 'code-generation'),
|
|
68
|
+
'planning': this.calculateIntentScore(lowerPrompt, words, 'planning'),
|
|
69
|
+
'refinement': this.calculateIntentScore(lowerPrompt, words, 'refinement'),
|
|
70
|
+
'debugging': this.calculateIntentScore(lowerPrompt, words, 'debugging'),
|
|
71
|
+
'documentation': this.calculateIntentScore(lowerPrompt, words, 'documentation'),
|
|
72
|
+
'prd-generation': 0 // PRD is explicit command, not inferred
|
|
73
|
+
};
|
|
74
|
+
// Apply intent priority rules
|
|
75
|
+
const primaryIntent = this.selectPrimaryIntent(scores, lowerPrompt);
|
|
76
|
+
// Calculate confidence
|
|
77
|
+
const confidence = this.calculateConfidence(scores, primaryIntent);
|
|
78
|
+
// Analyze characteristics
|
|
79
|
+
const characteristics = {
|
|
80
|
+
hasCodeContext: this.hasCodeContext(prompt),
|
|
81
|
+
hasTechnicalTerms: this.hasTechnicalTerms(lowerPrompt),
|
|
82
|
+
isOpenEnded: this.isOpenEnded(prompt),
|
|
83
|
+
needsStructure: this.needsStructure(prompt, primaryIntent)
|
|
84
|
+
};
|
|
85
|
+
// Suggest mode
|
|
86
|
+
const suggestedMode = this.suggestMode(primaryIntent, characteristics, prompt.length, confidence);
|
|
87
|
+
return {
|
|
88
|
+
primaryIntent,
|
|
89
|
+
confidence,
|
|
90
|
+
characteristics,
|
|
91
|
+
suggestedMode
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
calculateIntentScore(prompt, words, intent) {
|
|
95
|
+
let score = 0;
|
|
96
|
+
// Get keywords for this intent
|
|
97
|
+
const { strong, medium, weak } = this.getKeywordsForIntent(intent);
|
|
98
|
+
// Check strong indicators (phrases) - 20 points each
|
|
99
|
+
for (const phrase of strong) {
|
|
100
|
+
if (prompt.includes(phrase)) {
|
|
101
|
+
score += this.applyNegation(phrase, prompt, 20);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Check medium indicators - 10 points each
|
|
105
|
+
for (const keyword of medium) {
|
|
106
|
+
if (words.includes(keyword) || prompt.includes(keyword)) {
|
|
107
|
+
score += this.applyNegation(keyword, prompt, 10);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Check weak indicators - 5 points each
|
|
111
|
+
for (const keyword of weak) {
|
|
112
|
+
if (words.includes(keyword)) {
|
|
113
|
+
score += 5;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Context bonus
|
|
117
|
+
score += this.getContextBonus(prompt, intent);
|
|
118
|
+
return score;
|
|
119
|
+
}
|
|
120
|
+
getKeywordsForIntent(intent) {
|
|
121
|
+
switch (intent) {
|
|
122
|
+
case 'code-generation':
|
|
123
|
+
return {
|
|
124
|
+
strong: this.STRONG_CODE_KEYWORDS,
|
|
125
|
+
medium: this.CODE_KEYWORDS,
|
|
126
|
+
weak: this.WEAK_CODE_KEYWORDS
|
|
127
|
+
};
|
|
128
|
+
case 'planning':
|
|
129
|
+
return {
|
|
130
|
+
strong: this.STRONG_PLANNING_KEYWORDS,
|
|
131
|
+
medium: this.PLANNING_KEYWORDS,
|
|
132
|
+
weak: []
|
|
133
|
+
};
|
|
134
|
+
case 'debugging':
|
|
135
|
+
return {
|
|
136
|
+
strong: this.STRONG_DEBUGGING_KEYWORDS,
|
|
137
|
+
medium: this.DEBUGGING_KEYWORDS,
|
|
138
|
+
weak: []
|
|
139
|
+
};
|
|
140
|
+
case 'documentation':
|
|
141
|
+
return {
|
|
142
|
+
strong: this.STRONG_DOCUMENTATION_KEYWORDS,
|
|
143
|
+
medium: this.DOCUMENTATION_KEYWORDS,
|
|
144
|
+
weak: []
|
|
145
|
+
};
|
|
146
|
+
case 'refinement':
|
|
147
|
+
return {
|
|
148
|
+
strong: this.STRONG_REFINEMENT_KEYWORDS,
|
|
149
|
+
medium: this.REFINEMENT_KEYWORDS,
|
|
150
|
+
weak: []
|
|
151
|
+
};
|
|
152
|
+
default:
|
|
153
|
+
return { strong: [], medium: [], weak: [] };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
applyNegation(keyword, prompt, baseScore) {
|
|
157
|
+
// Find keyword position
|
|
158
|
+
const keywordIndex = prompt.indexOf(keyword);
|
|
159
|
+
if (keywordIndex === -1)
|
|
160
|
+
return baseScore;
|
|
161
|
+
// Check 2 words before keyword for negation
|
|
162
|
+
const before = prompt.substring(Math.max(0, keywordIndex - 20), keywordIndex);
|
|
163
|
+
for (const negation of this.NEGATION_WORDS) {
|
|
164
|
+
if (before.includes(negation)) {
|
|
165
|
+
return Math.round(baseScore * 0.5); // Reduce by 50%
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return baseScore;
|
|
169
|
+
}
|
|
170
|
+
getContextBonus(prompt, intent) {
|
|
171
|
+
let bonus = 0;
|
|
172
|
+
// Code snippet bonus for debugging/refinement
|
|
173
|
+
if ((intent === 'debugging' || intent === 'refinement') && this.hasCodeContext(prompt)) {
|
|
174
|
+
bonus += 15;
|
|
175
|
+
}
|
|
176
|
+
// Question mark bonus for planning/documentation
|
|
177
|
+
if ((intent === 'planning' || intent === 'documentation') && prompt.includes('?')) {
|
|
178
|
+
bonus += 10;
|
|
179
|
+
}
|
|
180
|
+
// Technical terms bonus for code-generation
|
|
181
|
+
if (intent === 'code-generation' && this.hasTechnicalTerms(prompt)) {
|
|
182
|
+
bonus += 5;
|
|
183
|
+
}
|
|
184
|
+
// Performance terms bonus for refinement
|
|
185
|
+
if (intent === 'refinement' && this.hasPerformanceTerms(prompt)) {
|
|
186
|
+
bonus += 10;
|
|
187
|
+
}
|
|
188
|
+
return bonus;
|
|
189
|
+
}
|
|
190
|
+
selectPrimaryIntent(scores, prompt) {
|
|
191
|
+
// Priority 1: Debugging (if strong indicators present)
|
|
192
|
+
if (scores.debugging >= 20 && (prompt.includes('error') || prompt.includes('bug') || prompt.includes('fix') ||
|
|
193
|
+
prompt.includes('debug') || prompt.includes('issue') || prompt.includes('resolve'))) {
|
|
194
|
+
return 'debugging';
|
|
195
|
+
}
|
|
196
|
+
// Priority 2: Documentation (if explanation requested or write documentation)
|
|
197
|
+
if (scores.documentation >= 20 && (prompt.includes('explain') || prompt.includes('how does') ||
|
|
198
|
+
prompt.includes('documentation') || (prompt.includes('write') && prompt.includes('document')))) {
|
|
199
|
+
return 'documentation';
|
|
200
|
+
}
|
|
201
|
+
// Priority 3: Planning (if architecture/design question)
|
|
202
|
+
if (scores.planning >= 20 && (prompt.includes('how should') || prompt.includes('architecture') ||
|
|
203
|
+
prompt.includes('what is the best'))) {
|
|
204
|
+
return 'planning';
|
|
205
|
+
}
|
|
206
|
+
// Priority 4: Refinement (if improvement requested)
|
|
207
|
+
if (scores.refinement >= 15 && (prompt.includes('improve') || prompt.includes('optimize') ||
|
|
208
|
+
prompt.includes('enhance') || prompt.includes('make') || prompt.includes('refactor'))) {
|
|
209
|
+
return 'refinement';
|
|
210
|
+
}
|
|
211
|
+
// Default: Highest score
|
|
212
|
+
const entries = Object.entries(scores);
|
|
213
|
+
const [primaryIntent] = entries.reduce((max, current) => current[1] > max[1] ? current : max);
|
|
214
|
+
return primaryIntent;
|
|
215
|
+
}
|
|
216
|
+
calculateConfidence(scores, primaryIntent) {
|
|
217
|
+
const primaryScore = scores[primaryIntent];
|
|
218
|
+
const totalScore = Object.values(scores).reduce((sum, score) => sum + score, 0);
|
|
219
|
+
if (totalScore === 0) {
|
|
220
|
+
return 50; // Low confidence if no keywords matched
|
|
221
|
+
}
|
|
222
|
+
// Calculate confidence as percentage of primary vs total
|
|
223
|
+
let confidence = Math.min(100, Math.round((primaryScore / totalScore) * 100));
|
|
224
|
+
// Check if secondary intent is close
|
|
225
|
+
const sortedScores = Object.entries(scores)
|
|
226
|
+
.filter(([intent]) => intent !== primaryIntent)
|
|
227
|
+
.sort(([, a], [, b]) => b - a);
|
|
228
|
+
if (sortedScores.length > 0) {
|
|
229
|
+
const secondaryScore = sortedScores[0][1];
|
|
230
|
+
const difference = primaryScore - secondaryScore;
|
|
231
|
+
// If top 2 are within 15%, reduce confidence
|
|
232
|
+
if (difference < primaryScore * 0.15) {
|
|
233
|
+
confidence = Math.max(60, confidence - 15);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return confidence;
|
|
237
|
+
}
|
|
238
|
+
hasCodeContext(prompt) {
|
|
239
|
+
// Check for code blocks
|
|
240
|
+
if (prompt.includes('```') || prompt.includes('`')) {
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
// Check for code patterns
|
|
244
|
+
const codePatterns = [
|
|
245
|
+
/function\s+\w+\s*\(/,
|
|
246
|
+
/class\s+\w+/,
|
|
247
|
+
/const\s+\w+\s*=/,
|
|
248
|
+
/let\s+\w+\s*=/,
|
|
249
|
+
/var\s+\w+\s*=/,
|
|
250
|
+
/def\s+\w+\s*\(/,
|
|
251
|
+
/import\s+/,
|
|
252
|
+
/<\w+>/,
|
|
253
|
+
/\w+\.\w+\(/
|
|
254
|
+
];
|
|
255
|
+
return codePatterns.some(pattern => pattern.test(prompt));
|
|
256
|
+
}
|
|
257
|
+
hasTechnicalTerms(prompt) {
|
|
258
|
+
const terms = [
|
|
259
|
+
'api', 'database', 'sql', 'rest', 'graphql', 'jwt',
|
|
260
|
+
'authentication', 'middleware', 'framework', 'library',
|
|
261
|
+
'npm', 'docker', 'aws', 'frontend', 'backend', 'microservice'
|
|
262
|
+
];
|
|
263
|
+
return terms.some(term => prompt.includes(term));
|
|
264
|
+
}
|
|
265
|
+
hasPerformanceTerms(prompt) {
|
|
266
|
+
const terms = [
|
|
267
|
+
'performance', 'speed', 'fast', 'slow', 'optimize', 'latency',
|
|
268
|
+
'throughput', 'memory', 'cpu', 'load time', 'response time'
|
|
269
|
+
];
|
|
270
|
+
return terms.some(term => prompt.includes(term));
|
|
271
|
+
}
|
|
272
|
+
isOpenEnded(prompt) {
|
|
273
|
+
const questionWords = ['how', 'what', 'why', 'when', 'where', 'which', 'should'];
|
|
274
|
+
const lowerPrompt = prompt.toLowerCase();
|
|
275
|
+
const hasQuestionWord = questionWords.some(word => lowerPrompt.startsWith(word));
|
|
276
|
+
const hasQuestionMark = prompt.includes('?');
|
|
277
|
+
const vaguePatterns = ['help me', 'i need', 'not sure', 'maybe', 'somehow'];
|
|
278
|
+
const hasVague = vaguePatterns.some(pattern => lowerPrompt.includes(pattern));
|
|
279
|
+
return hasQuestionWord || hasQuestionMark || hasVague;
|
|
280
|
+
}
|
|
281
|
+
needsStructure(prompt, intent) {
|
|
282
|
+
if (intent === 'planning')
|
|
283
|
+
return true;
|
|
284
|
+
const hasObjective = /objective|goal|purpose|need to|want to/i.test(prompt);
|
|
285
|
+
const hasRequirements = /requirement|must|should|need|expect/i.test(prompt);
|
|
286
|
+
const hasConstraints = /constraint|limit|within|must not|cannot/i.test(prompt);
|
|
287
|
+
const structureScore = [hasObjective, hasRequirements, hasConstraints]
|
|
288
|
+
.filter(Boolean).length;
|
|
289
|
+
return structureScore < 2;
|
|
290
|
+
}
|
|
291
|
+
suggestMode(intent, characteristics, promptLength, confidence) {
|
|
292
|
+
// Low confidence suggests deep mode
|
|
293
|
+
if (confidence < 60) {
|
|
294
|
+
return 'deep';
|
|
295
|
+
}
|
|
296
|
+
// Planning always benefits from deep mode
|
|
297
|
+
if (intent === 'planning') {
|
|
298
|
+
return 'deep';
|
|
299
|
+
}
|
|
300
|
+
// Open-ended without code context suggests deep mode
|
|
301
|
+
if (characteristics.isOpenEnded && !characteristics.hasCodeContext) {
|
|
302
|
+
return 'deep';
|
|
303
|
+
}
|
|
304
|
+
// Very short prompts needing structure suggest deep mode
|
|
305
|
+
if (promptLength < 50 && characteristics.needsStructure) {
|
|
306
|
+
return 'deep';
|
|
307
|
+
}
|
|
308
|
+
return 'fast';
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=intent-detector.js.map
|