clavix 2.7.0 → 2.8.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 +22 -8
- package/bin/clavix.js +12 -5
- package/dist/cli/commands/archive.d.ts +5 -4
- package/dist/cli/commands/archive.js +135 -161
- package/dist/cli/commands/config.d.ts +4 -4
- package/dist/cli/commands/config.js +66 -105
- package/dist/cli/commands/deep.d.ts +3 -3
- package/dist/cli/commands/deep.js +97 -103
- package/dist/cli/commands/execute.d.ts +4 -4
- package/dist/cli/commands/execute.js +57 -63
- package/dist/cli/commands/fast.d.ts +3 -3
- package/dist/cli/commands/fast.js +122 -128
- package/dist/cli/commands/implement.d.ts +4 -4
- package/dist/cli/commands/implement.js +84 -148
- package/dist/cli/commands/init.js +87 -126
- package/dist/cli/commands/list.d.ts +5 -5
- package/dist/cli/commands/list.js +72 -111
- package/dist/cli/commands/plan.d.ts +7 -7
- package/dist/cli/commands/plan.js +92 -131
- package/dist/cli/commands/prd.d.ts +4 -4
- package/dist/cli/commands/prd.js +76 -111
- package/dist/cli/commands/prompts/clear.d.ts +6 -6
- package/dist/cli/commands/prompts/clear.js +70 -76
- package/dist/cli/commands/prompts/list.js +37 -43
- package/dist/cli/commands/show.d.ts +4 -4
- package/dist/cli/commands/show.js +72 -111
- package/dist/cli/commands/start.d.ts +3 -3
- package/dist/cli/commands/start.js +63 -101
- package/dist/cli/commands/summarize.d.ts +4 -4
- package/dist/cli/commands/summarize.js +81 -120
- package/dist/cli/commands/task-complete.d.ts +4 -4
- package/dist/cli/commands/task-complete.js +86 -123
- package/dist/cli/commands/update.d.ts +3 -3
- package/dist/cli/commands/update.js +97 -130
- package/dist/cli/commands/version.js +13 -48
- package/dist/core/adapters/agents-md-generator.js +17 -50
- package/dist/core/adapters/amp-adapter.d.ts +1 -1
- package/dist/core/adapters/amp-adapter.js +13 -21
- package/dist/core/adapters/augment-adapter.d.ts +2 -2
- package/dist/core/adapters/augment-adapter.js +16 -56
- package/dist/core/adapters/base-adapter.d.ts +1 -1
- package/dist/core/adapters/base-adapter.js +11 -47
- package/dist/core/adapters/claude-code-adapter.d.ts +2 -2
- package/dist/core/adapters/claude-code-adapter.js +19 -60
- package/dist/core/adapters/cline-adapter.d.ts +1 -1
- package/dist/core/adapters/cline-adapter.js +13 -21
- package/dist/core/adapters/codebuddy-adapter.d.ts +2 -2
- package/dist/core/adapters/codebuddy-adapter.js +17 -57
- package/dist/core/adapters/codex-adapter.d.ts +2 -2
- package/dist/core/adapters/codex-adapter.js +16 -56
- package/dist/core/adapters/copilot-instructions-generator.js +18 -51
- package/dist/core/adapters/crush-adapter.d.ts +2 -2
- package/dist/core/adapters/crush-adapter.js +13 -20
- package/dist/core/adapters/cursor-adapter.d.ts +1 -1
- package/dist/core/adapters/cursor-adapter.js +12 -20
- package/dist/core/adapters/droid-adapter.d.ts +2 -2
- package/dist/core/adapters/droid-adapter.js +14 -21
- package/dist/core/adapters/gemini-adapter.d.ts +2 -2
- package/dist/core/adapters/gemini-adapter.js +16 -52
- package/dist/core/adapters/kilocode-adapter.d.ts +1 -1
- package/dist/core/adapters/kilocode-adapter.js +12 -20
- package/dist/core/adapters/octo-md-generator.js +17 -50
- package/dist/core/adapters/opencode-adapter.d.ts +2 -2
- package/dist/core/adapters/opencode-adapter.js +14 -21
- package/dist/core/adapters/qwen-adapter.d.ts +2 -2
- package/dist/core/adapters/qwen-adapter.js +16 -52
- package/dist/core/adapters/roocode-adapter.d.ts +2 -2
- package/dist/core/adapters/roocode-adapter.js +12 -19
- package/dist/core/adapters/warp-md-generator.js +17 -50
- package/dist/core/adapters/windsurf-adapter.d.ts +1 -1
- package/dist/core/adapters/windsurf-adapter.js +12 -20
- package/dist/core/agent-manager.d.ts +1 -1
- package/dist/core/agent-manager.js +34 -38
- package/dist/core/archive-manager.js +10 -46
- package/dist/core/config-manager.d.ts +2 -2
- package/dist/core/config-manager.js +3 -40
- package/dist/core/conversation-analyzer.d.ts +1 -1
- package/dist/core/conversation-analyzer.js +1 -5
- package/dist/core/doc-injector.js +23 -60
- package/dist/core/git-manager.js +11 -48
- package/dist/core/prd-generator.js +16 -51
- package/dist/core/prompt-manager.js +6 -42
- package/dist/core/prompt-optimizer.js +1 -5
- package/dist/core/question-engine.js +6 -45
- package/dist/core/session-manager.d.ts +1 -1
- package/dist/core/session-manager.js +11 -49
- package/dist/core/task-manager.d.ts +26 -0
- package/dist/core/task-manager.js +243 -101
- package/dist/index.d.ts +2 -1
- package/dist/index.js +8 -12
- package/dist/templates/agents/agents.md +31 -2
- package/dist/templates/agents/copilot-instructions.md +1 -1
- package/dist/templates/agents/octo.md +20 -1
- package/dist/templates/agents/warp.md +1 -1
- package/dist/templates/slash-commands/_canonical/implement.md +33 -11
- package/dist/types/agent.js +1 -2
- package/dist/types/config.js +3 -8
- package/dist/types/errors.js +7 -13
- package/dist/types/session.js +1 -2
- package/dist/utils/agent-error-messages.js +1 -5
- package/dist/utils/error-utils.js +5 -12
- package/dist/utils/file-system.js +20 -57
- package/dist/utils/legacy-command-cleanup.d.ts +1 -1
- package/dist/utils/legacy-command-cleanup.js +9 -45
- package/dist/utils/template-loader.d.ts +1 -1
- package/dist/utils/template-loader.js +9 -41
- package/dist/utils/toml-templates.js +1 -4
- package/package.json +12 -7
- package/dist/core/adapters 2/agents-md-generator.d.ts +0 -26
- package/dist/core/adapters 2/agents-md-generator.js +0 -102
- package/dist/core/adapters 2/amp-adapter.d.ts +0 -27
- package/dist/core/adapters 2/amp-adapter.js +0 -42
- package/dist/core/adapters 2/augment-adapter.d.ts +0 -22
- package/dist/core/adapters 2/augment-adapter.js +0 -77
- package/dist/core/adapters 2/base-adapter.d.ts +0 -45
- package/dist/core/adapters 2/base-adapter.js +0 -142
- package/dist/core/adapters 2/claude-code-adapter.d.ts +0 -32
- package/dist/core/adapters 2/claude-code-adapter.js +0 -116
- package/dist/core/adapters 2/cline-adapter.d.ts +0 -34
- package/dist/core/adapters 2/cline-adapter.js +0 -52
- package/dist/core/adapters 2/codebuddy-adapter.d.ts +0 -24
- package/dist/core/adapters 2/codebuddy-adapter.js +0 -82
- package/dist/core/adapters 2/codex-adapter.d.ts +0 -24
- package/dist/core/adapters 2/codex-adapter.js +0 -79
- package/dist/core/adapters 2/copilot-instructions-generator.d.ts +0 -26
- package/dist/core/adapters 2/copilot-instructions-generator.js +0 -104
- package/dist/core/adapters 2/crush-adapter.d.ts +0 -35
- package/dist/core/adapters 2/crush-adapter.js +0 -49
- package/dist/core/adapters 2/cursor-adapter.d.ts +0 -25
- package/dist/core/adapters 2/cursor-adapter.js +0 -40
- package/dist/core/adapters 2/droid-adapter.d.ts +0 -33
- package/dist/core/adapters 2/droid-adapter.js +0 -57
- package/dist/core/adapters 2/gemini-adapter.d.ts +0 -27
- package/dist/core/adapters 2/gemini-adapter.js +0 -90
- package/dist/core/adapters 2/kilocode-adapter.d.ts +0 -34
- package/dist/core/adapters 2/kilocode-adapter.js +0 -49
- package/dist/core/adapters 2/octo-md-generator.d.ts +0 -26
- package/dist/core/adapters 2/octo-md-generator.js +0 -102
- package/dist/core/adapters 2/opencode-adapter.d.ts +0 -33
- package/dist/core/adapters 2/opencode-adapter.js +0 -56
- package/dist/core/adapters 2/qwen-adapter.d.ts +0 -27
- package/dist/core/adapters 2/qwen-adapter.js +0 -90
- package/dist/core/adapters 2/roocode-adapter.d.ts +0 -40
- package/dist/core/adapters 2/roocode-adapter.js +0 -68
- package/dist/core/adapters 2/warp-md-generator.d.ts +0 -17
- package/dist/core/adapters 2/warp-md-generator.js +0 -88
- package/dist/core/adapters 2/windsurf-adapter.d.ts +0 -34
- package/dist/core/adapters 2/windsurf-adapter.js +0 -49
- package/dist/core/agent-manager 2.js +0 -126
- package/dist/core/agent-manager.d 2.ts +0 -51
- package/dist/core/archive-manager 2.js +0 -338
- package/dist/core/archive-manager.d 2.ts +0 -100
- package/dist/core/conversation-analyzer.d 2.ts +0 -86
- package/dist/core/doc-injector 2.js +0 -236
- package/dist/core/doc-injector.d 2.ts +0 -51
- package/dist/core/git-manager 2.js +0 -214
- package/dist/core/git-manager.d 2.ts +0 -100
- package/dist/core/prompt-optimizer 2.js +0 -963
- package/dist/core/prompt-optimizer.d 2.ts +0 -268
- package/dist/core/question-engine 2.js +0 -395
- package/dist/core/question-engine.d 2.ts +0 -167
- package/dist/core/session-manager 2.js +0 -403
- package/dist/core/session-manager.d 2.ts +0 -139
- package/dist/core/task-manager 2.js +0 -689
- package/dist/core/task-manager.d 2.ts +0 -155
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PromptOptimizer - Analyzes and improves prompts using the CLEAR Framework
|
|
3
|
-
* CLEAR Framework: Concise, Logical, Explicit, Adaptive, Reflective
|
|
4
|
-
* Developed by Dr. Leo Lo, University of New Mexico
|
|
5
|
-
* Reference: https://guides.library.tamucc.edu/prompt-engineering/clear
|
|
6
|
-
*/
|
|
7
|
-
export type OptimizerMode = 'fast' | 'deep';
|
|
8
|
-
export interface PromptAnalysis {
|
|
9
|
-
gaps: string[];
|
|
10
|
-
ambiguities: string[];
|
|
11
|
-
strengths: string[];
|
|
12
|
-
suggestions: string[];
|
|
13
|
-
}
|
|
14
|
-
export interface ConciseAnalysis {
|
|
15
|
-
score: number;
|
|
16
|
-
verbosityCount: number;
|
|
17
|
-
pleasantriesCount: number;
|
|
18
|
-
signalToNoiseRatio: number;
|
|
19
|
-
issues: string[];
|
|
20
|
-
suggestions: string[];
|
|
21
|
-
}
|
|
22
|
-
export interface LogicAnalysis {
|
|
23
|
-
score: number;
|
|
24
|
-
hasCoherentFlow: boolean;
|
|
25
|
-
sequencingIssues: string[];
|
|
26
|
-
suggestedOrder: string[];
|
|
27
|
-
issues: string[];
|
|
28
|
-
suggestions: string[];
|
|
29
|
-
}
|
|
30
|
-
export interface ExplicitAnalysis {
|
|
31
|
-
score: number;
|
|
32
|
-
hasPersona: boolean;
|
|
33
|
-
hasOutputFormat: boolean;
|
|
34
|
-
hasToneStyle: boolean;
|
|
35
|
-
hasSuccessCriteria: boolean;
|
|
36
|
-
hasExamples: boolean;
|
|
37
|
-
issues: string[];
|
|
38
|
-
suggestions: string[];
|
|
39
|
-
}
|
|
40
|
-
export interface AdaptiveAnalysis {
|
|
41
|
-
score: number;
|
|
42
|
-
alternativePhrasings: string[];
|
|
43
|
-
alternativeStructures: Array<{
|
|
44
|
-
name: string;
|
|
45
|
-
structure: string;
|
|
46
|
-
benefits: string;
|
|
47
|
-
}>;
|
|
48
|
-
temperatureRecommendation: number;
|
|
49
|
-
issues: string[];
|
|
50
|
-
suggestions: string[];
|
|
51
|
-
}
|
|
52
|
-
export interface ReflectiveAnalysis {
|
|
53
|
-
score: number;
|
|
54
|
-
validationChecklist: string[];
|
|
55
|
-
edgeCases: string[];
|
|
56
|
-
potentialIssues: string[];
|
|
57
|
-
factCheckingSteps: string[];
|
|
58
|
-
qualityCriteria: string[];
|
|
59
|
-
issues: string[];
|
|
60
|
-
suggestions: string[];
|
|
61
|
-
}
|
|
62
|
-
export interface CLEARResult {
|
|
63
|
-
conciseness: ConciseAnalysis;
|
|
64
|
-
logic: LogicAnalysis;
|
|
65
|
-
explicitness: ExplicitAnalysis;
|
|
66
|
-
adaptiveness?: AdaptiveAnalysis;
|
|
67
|
-
reflectiveness?: ReflectiveAnalysis;
|
|
68
|
-
overallScore: number;
|
|
69
|
-
improvedPrompt: string;
|
|
70
|
-
changesSummary: Array<{
|
|
71
|
-
component: 'C' | 'L' | 'E' | 'A' | 'R';
|
|
72
|
-
change: string;
|
|
73
|
-
}>;
|
|
74
|
-
}
|
|
75
|
-
export interface CLEARScore {
|
|
76
|
-
overall: number;
|
|
77
|
-
conciseness: number;
|
|
78
|
-
logic: number;
|
|
79
|
-
explicitness: number;
|
|
80
|
-
adaptiveness?: number;
|
|
81
|
-
reflectiveness?: number;
|
|
82
|
-
rating: 'excellent' | 'good' | 'needs-improvement' | 'poor';
|
|
83
|
-
}
|
|
84
|
-
export interface TriageResult {
|
|
85
|
-
needsDeepAnalysis: boolean;
|
|
86
|
-
reasons: string[];
|
|
87
|
-
}
|
|
88
|
-
export interface QualityAssessment {
|
|
89
|
-
isAlreadyGood: boolean;
|
|
90
|
-
criteriaMetCount: number;
|
|
91
|
-
totalCriteria: number;
|
|
92
|
-
criteriaResults: {
|
|
93
|
-
clearGoal: boolean;
|
|
94
|
-
sufficientContext: boolean;
|
|
95
|
-
actionableLanguage: boolean;
|
|
96
|
-
reasonableScope: boolean;
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
export interface ChangesSummary {
|
|
100
|
-
changes: string[];
|
|
101
|
-
}
|
|
102
|
-
export interface ImprovedPrompt {
|
|
103
|
-
original: string;
|
|
104
|
-
analysis: PromptAnalysis;
|
|
105
|
-
improved: string;
|
|
106
|
-
changesSummary?: ChangesSummary;
|
|
107
|
-
triageResult?: TriageResult;
|
|
108
|
-
qualityAssessment?: QualityAssessment;
|
|
109
|
-
alternativePhrasings?: string[];
|
|
110
|
-
edgeCases?: string[];
|
|
111
|
-
implementationExamples?: {
|
|
112
|
-
good: string[];
|
|
113
|
-
bad: string[];
|
|
114
|
-
};
|
|
115
|
-
alternativeStructures?: Array<{
|
|
116
|
-
structure: string;
|
|
117
|
-
benefits: string;
|
|
118
|
-
}>;
|
|
119
|
-
potentialIssues?: string[];
|
|
120
|
-
}
|
|
121
|
-
export declare class PromptOptimizer {
|
|
122
|
-
/**
|
|
123
|
-
* Analyze a prompt and identify issues
|
|
124
|
-
*/
|
|
125
|
-
analyze(prompt: string): PromptAnalysis;
|
|
126
|
-
/**
|
|
127
|
-
* Perform smart triage to determine if deep analysis is recommended
|
|
128
|
-
*/
|
|
129
|
-
performTriage(prompt: string): TriageResult;
|
|
130
|
-
/**
|
|
131
|
-
* Assess prompt quality
|
|
132
|
-
*/
|
|
133
|
-
assessQuality(prompt: string): QualityAssessment;
|
|
134
|
-
/**
|
|
135
|
-
* Generate an improved version of the prompt
|
|
136
|
-
*/
|
|
137
|
-
improve(prompt: string, mode?: OptimizerMode): ImprovedPrompt;
|
|
138
|
-
/**
|
|
139
|
-
* Apply CLEAR Framework analysis to a prompt
|
|
140
|
-
* C = Concise, L = Logical, E = Explicit, A = Adaptive (deep only), R = Reflective (deep only)
|
|
141
|
-
*/
|
|
142
|
-
applyCLEARFramework(prompt: string, mode?: OptimizerMode): CLEARResult;
|
|
143
|
-
/**
|
|
144
|
-
* Analyze Conciseness (C): Brevity and clarity
|
|
145
|
-
*/
|
|
146
|
-
analyzeConciseness(prompt: string): ConciseAnalysis;
|
|
147
|
-
/**
|
|
148
|
-
* Analyze Logic (L): Structured and coherent prompts
|
|
149
|
-
*/
|
|
150
|
-
analyzeLogic(prompt: string): LogicAnalysis;
|
|
151
|
-
/**
|
|
152
|
-
* Analyze Explicitness (E): Clear output specifications
|
|
153
|
-
*/
|
|
154
|
-
analyzeExplicitness(prompt: string): ExplicitAnalysis;
|
|
155
|
-
/**
|
|
156
|
-
* Analyze Adaptiveness (A): Flexibility and customization
|
|
157
|
-
*/
|
|
158
|
-
analyzeAdaptiveness(prompt: string): AdaptiveAnalysis;
|
|
159
|
-
/**
|
|
160
|
-
* Analyze Reflectiveness (R): Continuous evaluation and improvement
|
|
161
|
-
*/
|
|
162
|
-
analyzeReflectiveness(prompt: string): ReflectiveAnalysis;
|
|
163
|
-
/**
|
|
164
|
-
* Calculate overall CLEAR score with weighted components
|
|
165
|
-
*/
|
|
166
|
-
calculateCLEARScore(analysis: {
|
|
167
|
-
conciseness: ConciseAnalysis;
|
|
168
|
-
logic: LogicAnalysis;
|
|
169
|
-
explicitness: ExplicitAnalysis;
|
|
170
|
-
adaptiveness?: AdaptiveAnalysis;
|
|
171
|
-
reflectiveness?: ReflectiveAnalysis;
|
|
172
|
-
}): CLEARScore;
|
|
173
|
-
/**
|
|
174
|
-
* Generate improved prompt using CLEAR framework insights
|
|
175
|
-
*/
|
|
176
|
-
private generateCLEARImprovedPrompt;
|
|
177
|
-
/**
|
|
178
|
-
* Generate CLEAR-labeled changes summary
|
|
179
|
-
*/
|
|
180
|
-
private generateCLEARChangesSummary;
|
|
181
|
-
/**
|
|
182
|
-
* Map CLEAR result to legacy PromptAnalysis format for backward compatibility
|
|
183
|
-
*/
|
|
184
|
-
mapCLEARToLegacy(clearResult: CLEARResult): PromptAnalysis;
|
|
185
|
-
/**
|
|
186
|
-
* Extract strengths from CLEAR analysis
|
|
187
|
-
*/
|
|
188
|
-
private extractCLEARStrengths;
|
|
189
|
-
/**
|
|
190
|
-
* Find gaps in the prompt
|
|
191
|
-
*/
|
|
192
|
-
private findGaps;
|
|
193
|
-
/**
|
|
194
|
-
* Find ambiguities in the prompt
|
|
195
|
-
*/
|
|
196
|
-
private findAmbiguities;
|
|
197
|
-
/**
|
|
198
|
-
* Find strengths in the prompt
|
|
199
|
-
*/
|
|
200
|
-
private findStrengths;
|
|
201
|
-
/**
|
|
202
|
-
* Generate improvement suggestions
|
|
203
|
-
*/
|
|
204
|
-
private generateSuggestions;
|
|
205
|
-
/**
|
|
206
|
-
* Generate improved prompt with structure
|
|
207
|
-
*/
|
|
208
|
-
private generateImprovedPrompt;
|
|
209
|
-
private hasContext;
|
|
210
|
-
private hasSuccessCriteria;
|
|
211
|
-
private hasTechnicalDetails;
|
|
212
|
-
private hasUserNeeds;
|
|
213
|
-
private hasExpectedOutput;
|
|
214
|
-
private extractOrInferObjective;
|
|
215
|
-
private extractOrInferRequirements;
|
|
216
|
-
private extractOrInferTechnical;
|
|
217
|
-
private extractOrInferOutput;
|
|
218
|
-
private extractOrInferSuccess;
|
|
219
|
-
/**
|
|
220
|
-
* Count missing critical elements
|
|
221
|
-
*/
|
|
222
|
-
private countMissingCriticalElements;
|
|
223
|
-
/**
|
|
224
|
-
* Check for vague scope words without sufficient context
|
|
225
|
-
*/
|
|
226
|
-
private hasVagueScopeWithoutContext;
|
|
227
|
-
/**
|
|
228
|
-
* Check if prompt has a clear goal
|
|
229
|
-
*/
|
|
230
|
-
private hasClearGoal;
|
|
231
|
-
/**
|
|
232
|
-
* Check if prompt uses actionable language
|
|
233
|
-
*/
|
|
234
|
-
private hasActionableLanguage;
|
|
235
|
-
/**
|
|
236
|
-
* Check if prompt has reasonable scope
|
|
237
|
-
*/
|
|
238
|
-
private hasReasonableScope;
|
|
239
|
-
/**
|
|
240
|
-
* Generate changes summary
|
|
241
|
-
*/
|
|
242
|
-
private generateChangesSummary;
|
|
243
|
-
/**
|
|
244
|
-
* Generate alternative phrasings (deep mode)
|
|
245
|
-
*/
|
|
246
|
-
private generateAlternativePhrasings;
|
|
247
|
-
/**
|
|
248
|
-
* Identify edge cases in requirements (deep mode)
|
|
249
|
-
*/
|
|
250
|
-
private identifyEdgeCases;
|
|
251
|
-
/**
|
|
252
|
-
* Generate implementation examples (deep mode)
|
|
253
|
-
*/
|
|
254
|
-
private generateImplementationExamples;
|
|
255
|
-
/**
|
|
256
|
-
* Suggest alternative prompt structures (deep mode)
|
|
257
|
-
*/
|
|
258
|
-
private suggestAlternativeStructures;
|
|
259
|
-
/**
|
|
260
|
-
* Identify potential issues with the prompt (deep mode)
|
|
261
|
-
*/
|
|
262
|
-
private identifyPotentialIssues;
|
|
263
|
-
/**
|
|
264
|
-
* Extract core requirement from prompt
|
|
265
|
-
*/
|
|
266
|
-
private extractCoreRequirement;
|
|
267
|
-
}
|
|
268
|
-
//# sourceMappingURL=prompt-optimizer.d.ts.map
|
|
@@ -1,395 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* QuestionEngine - Manages Socratic questioning flows for PRD generation
|
|
4
|
-
*
|
|
5
|
-
* This class handles:
|
|
6
|
-
* - Loading question templates
|
|
7
|
-
* - Sequential and conditional question flows
|
|
8
|
-
* - Answer collection and validation
|
|
9
|
-
* - Progress tracking
|
|
10
|
-
*/
|
|
11
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
-
if (k2 === undefined) k2 = k;
|
|
13
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
-
}
|
|
17
|
-
Object.defineProperty(o, k2, desc);
|
|
18
|
-
}) : (function(o, m, k, k2) {
|
|
19
|
-
if (k2 === undefined) k2 = k;
|
|
20
|
-
o[k2] = m[k];
|
|
21
|
-
}));
|
|
22
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
-
}) : function(o, v) {
|
|
25
|
-
o["default"] = v;
|
|
26
|
-
});
|
|
27
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
-
var ownKeys = function(o) {
|
|
29
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
-
var ar = [];
|
|
31
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
-
return ar;
|
|
33
|
-
};
|
|
34
|
-
return ownKeys(o);
|
|
35
|
-
};
|
|
36
|
-
return function (mod) {
|
|
37
|
-
if (mod && mod.__esModule) return mod;
|
|
38
|
-
var result = {};
|
|
39
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
-
__setModuleDefault(result, mod);
|
|
41
|
-
return result;
|
|
42
|
-
};
|
|
43
|
-
})();
|
|
44
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.QuestionEngine = void 0;
|
|
46
|
-
const fs = __importStar(require("fs-extra"));
|
|
47
|
-
const path = __importStar(require("path"));
|
|
48
|
-
/**
|
|
49
|
-
* QuestionEngine class
|
|
50
|
-
*
|
|
51
|
-
* Manages the flow of questions, answer collection, and validation
|
|
52
|
-
*/
|
|
53
|
-
class QuestionEngine {
|
|
54
|
-
constructor() {
|
|
55
|
-
this.currentFlow = null;
|
|
56
|
-
this.answers = {};
|
|
57
|
-
this.currentQuestionIndex = 0;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Load a question flow from a template file
|
|
61
|
-
*
|
|
62
|
-
* @param templatePath - Path to the question template
|
|
63
|
-
* @returns The loaded question flow
|
|
64
|
-
*/
|
|
65
|
-
async loadFlow(templatePath) {
|
|
66
|
-
const fullPath = path.resolve(templatePath);
|
|
67
|
-
if (!await fs.pathExists(fullPath)) {
|
|
68
|
-
throw new Error(`Question template not found: ${templatePath}`);
|
|
69
|
-
}
|
|
70
|
-
const content = await fs.readFile(fullPath, 'utf-8');
|
|
71
|
-
const flow = this.parseTemplate(content);
|
|
72
|
-
this.currentFlow = flow;
|
|
73
|
-
this.answers = {};
|
|
74
|
-
this.currentQuestionIndex = 0;
|
|
75
|
-
return flow;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Parse a question template into a QuestionFlow
|
|
79
|
-
*
|
|
80
|
-
* Template format:
|
|
81
|
-
* ```markdown
|
|
82
|
-
* # Flow Name
|
|
83
|
-
*
|
|
84
|
-
* Flow description
|
|
85
|
-
*
|
|
86
|
-
* ## Question 1
|
|
87
|
-
*
|
|
88
|
-
* **text:** What problem are you solving?
|
|
89
|
-
* **type:** text
|
|
90
|
-
* **required:** true
|
|
91
|
-
* **validation:** minLength:10
|
|
92
|
-
*
|
|
93
|
-
* ## Question 2
|
|
94
|
-
*
|
|
95
|
-
* **text:** Select your technology stack
|
|
96
|
-
* **type:** list
|
|
97
|
-
* **choices:** React, Vue, Angular, Other
|
|
98
|
-
* ```
|
|
99
|
-
*
|
|
100
|
-
* @param template - Template content
|
|
101
|
-
* @returns Parsed QuestionFlow
|
|
102
|
-
*/
|
|
103
|
-
parseTemplate(template) {
|
|
104
|
-
const lines = template.split('\n');
|
|
105
|
-
const questions = [];
|
|
106
|
-
let name = 'Default Flow';
|
|
107
|
-
let description = '';
|
|
108
|
-
let currentQuestion = null;
|
|
109
|
-
for (let i = 0; i < lines.length; i++) {
|
|
110
|
-
const line = lines[i].trim();
|
|
111
|
-
// Skip empty lines
|
|
112
|
-
if (!line) {
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
// Extract flow name from first h1
|
|
116
|
-
if (line.startsWith('# ') && name === 'Default Flow') {
|
|
117
|
-
name = line.substring(2).trim();
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
// Extract description (first non-heading paragraph)
|
|
121
|
-
if (line && !line.startsWith('#') && !line.startsWith('**') && !description) {
|
|
122
|
-
description = line;
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
// Start new question on h2
|
|
126
|
-
if (line.startsWith('## ')) {
|
|
127
|
-
// Save previous question if exists
|
|
128
|
-
if (currentQuestion && currentQuestion.text) {
|
|
129
|
-
questions.push(this.finalizeQuestion(currentQuestion, questions.length));
|
|
130
|
-
}
|
|
131
|
-
// Start new question
|
|
132
|
-
currentQuestion = {};
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
// Parse question metadata: **key:** value
|
|
136
|
-
const metadataMatch = line.match(/^\*\*(\w+):\*\*\s*(.+)$/);
|
|
137
|
-
if (metadataMatch && currentQuestion) {
|
|
138
|
-
const [, key, value] = metadataMatch;
|
|
139
|
-
this.parseQuestionMetadata(currentQuestion, key, value);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
// Save last question
|
|
143
|
-
if (currentQuestion && currentQuestion.text) {
|
|
144
|
-
questions.push(this.finalizeQuestion(currentQuestion, questions.length));
|
|
145
|
-
}
|
|
146
|
-
return { name, description, questions };
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Parse a single metadata field for a question
|
|
150
|
-
*/
|
|
151
|
-
parseQuestionMetadata(question, key, value) {
|
|
152
|
-
switch (key.toLowerCase()) {
|
|
153
|
-
case 'text':
|
|
154
|
-
question.text = value;
|
|
155
|
-
break;
|
|
156
|
-
case 'type':
|
|
157
|
-
if (value === 'text' || value === 'list' || value === 'confirm') {
|
|
158
|
-
question.type = value;
|
|
159
|
-
}
|
|
160
|
-
break;
|
|
161
|
-
case 'required':
|
|
162
|
-
question.required = value.toLowerCase() === 'true';
|
|
163
|
-
break;
|
|
164
|
-
case 'choices':
|
|
165
|
-
question.choices = value.split(',').map((c) => c.trim());
|
|
166
|
-
break;
|
|
167
|
-
case 'default':
|
|
168
|
-
if (question.type === 'confirm') {
|
|
169
|
-
question.default = value.toLowerCase() === 'true';
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
question.default = value;
|
|
173
|
-
}
|
|
174
|
-
break;
|
|
175
|
-
case 'validation':
|
|
176
|
-
question.validate = this.createValidator(value);
|
|
177
|
-
break;
|
|
178
|
-
case 'condition':
|
|
179
|
-
question.condition = this.createCondition(value);
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Finalize a question by setting defaults and generating ID
|
|
185
|
-
*/
|
|
186
|
-
finalizeQuestion(partial, index) {
|
|
187
|
-
return {
|
|
188
|
-
id: `q${index + 1}`,
|
|
189
|
-
text: partial.text || '',
|
|
190
|
-
type: partial.type || 'text',
|
|
191
|
-
required: partial.required !== undefined ? partial.required : true,
|
|
192
|
-
choices: partial.choices,
|
|
193
|
-
default: partial.default,
|
|
194
|
-
validate: partial.validate,
|
|
195
|
-
condition: partial.condition,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Create a validation function from a validation string
|
|
200
|
-
*
|
|
201
|
-
* Supported formats:
|
|
202
|
-
* - minLength:10 - Minimum length
|
|
203
|
-
* - maxLength:100 - Maximum length
|
|
204
|
-
* - pattern:^[a-z]+$ - Regex pattern
|
|
205
|
-
* - email - Email validation
|
|
206
|
-
* - url - URL validation
|
|
207
|
-
*/
|
|
208
|
-
createValidator(validationStr) {
|
|
209
|
-
const parts = validationStr.split(':');
|
|
210
|
-
const type = parts[0].toLowerCase();
|
|
211
|
-
const param = parts[1];
|
|
212
|
-
return (answer) => {
|
|
213
|
-
switch (type) {
|
|
214
|
-
case 'minlength':
|
|
215
|
-
if (answer.length < parseInt(param, 10)) {
|
|
216
|
-
return `Minimum length is ${param} characters`;
|
|
217
|
-
}
|
|
218
|
-
break;
|
|
219
|
-
case 'maxlength':
|
|
220
|
-
if (answer.length > parseInt(param, 10)) {
|
|
221
|
-
return `Maximum length is ${param} characters`;
|
|
222
|
-
}
|
|
223
|
-
break;
|
|
224
|
-
case 'pattern':
|
|
225
|
-
if (!new RegExp(param).test(answer)) {
|
|
226
|
-
return 'Answer does not match required format';
|
|
227
|
-
}
|
|
228
|
-
break;
|
|
229
|
-
case 'email':
|
|
230
|
-
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(answer)) {
|
|
231
|
-
return 'Please enter a valid email address';
|
|
232
|
-
}
|
|
233
|
-
break;
|
|
234
|
-
case 'url':
|
|
235
|
-
try {
|
|
236
|
-
new URL(answer);
|
|
237
|
-
}
|
|
238
|
-
catch {
|
|
239
|
-
return 'Please enter a valid URL';
|
|
240
|
-
}
|
|
241
|
-
break;
|
|
242
|
-
}
|
|
243
|
-
return true;
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* Create a condition function from a condition string
|
|
248
|
-
*
|
|
249
|
-
* Supported formats:
|
|
250
|
-
* - q1=true - Question 1 answer equals true
|
|
251
|
-
* - q2=JWT - Question 2 answer equals "JWT"
|
|
252
|
-
* - q3!=None - Question 3 answer not equals "None"
|
|
253
|
-
*/
|
|
254
|
-
createCondition(conditionStr) {
|
|
255
|
-
const match = conditionStr.match(/^(\w+)\s*(=|!=)\s*(.+)$/);
|
|
256
|
-
if (!match) {
|
|
257
|
-
return () => true;
|
|
258
|
-
}
|
|
259
|
-
const [, questionId, operator, expectedValue] = match;
|
|
260
|
-
return (answers) => {
|
|
261
|
-
const actualValue = answers[questionId];
|
|
262
|
-
// Convert expected value to proper type
|
|
263
|
-
let expected = expectedValue;
|
|
264
|
-
if (expectedValue.toLowerCase() === 'true') {
|
|
265
|
-
expected = true;
|
|
266
|
-
}
|
|
267
|
-
else if (expectedValue.toLowerCase() === 'false') {
|
|
268
|
-
expected = false;
|
|
269
|
-
}
|
|
270
|
-
if (operator === '=') {
|
|
271
|
-
return actualValue === expected;
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
return actualValue !== expected;
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Get the next question in the flow
|
|
280
|
-
*
|
|
281
|
-
* @returns The next question, or null if flow is complete
|
|
282
|
-
*/
|
|
283
|
-
getNextQuestion() {
|
|
284
|
-
if (!this.currentFlow) {
|
|
285
|
-
throw new Error('No question flow loaded');
|
|
286
|
-
}
|
|
287
|
-
// Find the next unanswered question that meets its condition
|
|
288
|
-
while (this.currentQuestionIndex < this.currentFlow.questions.length) {
|
|
289
|
-
const question = this.currentFlow.questions[this.currentQuestionIndex];
|
|
290
|
-
// Skip if already answered
|
|
291
|
-
if (question.id in this.answers) {
|
|
292
|
-
this.currentQuestionIndex++;
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
// Check if question condition is met (if it has one)
|
|
296
|
-
if (question.condition && !question.condition(this.answers)) {
|
|
297
|
-
this.currentQuestionIndex++;
|
|
298
|
-
continue;
|
|
299
|
-
}
|
|
300
|
-
return question;
|
|
301
|
-
}
|
|
302
|
-
return null;
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Submit an answer to the current question
|
|
306
|
-
*
|
|
307
|
-
* @param questionId - ID of the question being answered
|
|
308
|
-
* @param answer - The answer
|
|
309
|
-
* @returns Validation result (true if valid, error message if invalid)
|
|
310
|
-
*/
|
|
311
|
-
submitAnswer(questionId, answer) {
|
|
312
|
-
if (!this.currentFlow) {
|
|
313
|
-
throw new Error('No question flow loaded');
|
|
314
|
-
}
|
|
315
|
-
const question = this.currentFlow.questions.find((q) => q.id === questionId);
|
|
316
|
-
if (!question) {
|
|
317
|
-
throw new Error(`Question not found: ${questionId}`);
|
|
318
|
-
}
|
|
319
|
-
// Validate required fields (but allow false for boolean answers)
|
|
320
|
-
if (question.required && (answer === '' || answer === null || answer === undefined)) {
|
|
321
|
-
return 'This question is required';
|
|
322
|
-
}
|
|
323
|
-
// Run custom validation if provided
|
|
324
|
-
if (question.validate) {
|
|
325
|
-
const validationResult = question.validate(String(answer));
|
|
326
|
-
if (validationResult !== true) {
|
|
327
|
-
return validationResult;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
// Store the answer
|
|
331
|
-
this.answers[questionId] = answer;
|
|
332
|
-
this.currentQuestionIndex++;
|
|
333
|
-
return true;
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Get all collected answers
|
|
337
|
-
*
|
|
338
|
-
* @returns All answers collected so far
|
|
339
|
-
*/
|
|
340
|
-
getAnswers() {
|
|
341
|
-
return { ...this.answers };
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Get current progress through the question flow
|
|
345
|
-
*
|
|
346
|
-
* @returns Progress information
|
|
347
|
-
*/
|
|
348
|
-
getProgress() {
|
|
349
|
-
if (!this.currentFlow) {
|
|
350
|
-
return { current: 0, total: 0, percentage: 0 };
|
|
351
|
-
}
|
|
352
|
-
const total = this.currentFlow.questions.length;
|
|
353
|
-
const current = Object.keys(this.answers).length;
|
|
354
|
-
const percentage = total > 0 ? Math.round((current / total) * 100) : 0;
|
|
355
|
-
return { current, total, percentage };
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* Check if the question flow is complete
|
|
359
|
-
*
|
|
360
|
-
* @returns True if all required questions are answered
|
|
361
|
-
*/
|
|
362
|
-
isComplete() {
|
|
363
|
-
if (!this.currentFlow) {
|
|
364
|
-
return false;
|
|
365
|
-
}
|
|
366
|
-
// Check if all required questions have answers
|
|
367
|
-
for (const question of this.currentFlow.questions) {
|
|
368
|
-
// Skip if condition not met
|
|
369
|
-
if (question.condition && !question.condition(this.answers)) {
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
if (question.required && !(question.id in this.answers)) {
|
|
373
|
-
return false;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
return true;
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Reset the question flow
|
|
380
|
-
*/
|
|
381
|
-
reset() {
|
|
382
|
-
this.answers = {};
|
|
383
|
-
this.currentQuestionIndex = 0;
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Get the current question flow
|
|
387
|
-
*
|
|
388
|
-
* @returns The loaded question flow, or null if none loaded
|
|
389
|
-
*/
|
|
390
|
-
getCurrentFlow() {
|
|
391
|
-
return this.currentFlow;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
exports.QuestionEngine = QuestionEngine;
|
|
395
|
-
//# sourceMappingURL=question-engine.js.map
|