@iservu-inc/adf-cli 0.4.35 → 0.5.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/.project/chats/current/2025-10-05_MULTI-IDE-IMPROVEMENTS.md +415 -0
- package/.project/docs/ROADMAP.md +150 -17
- package/CHANGELOG.md +220 -0
- package/lib/analysis/answer-analyzer.js +304 -0
- package/lib/analysis/dynamic-pipeline.js +262 -0
- package/lib/analysis/knowledge-graph.js +227 -0
- package/lib/analysis/question-mapper.js +293 -0
- package/lib/commands/config.js +127 -4
- package/lib/frameworks/interviewer.js +59 -0
- package/lib/generators/cursor-generator.js +77 -6
- package/lib/generators/vscode-generator.js +75 -6
- package/package.json +1 -1
- package/tests/answer-analyzer.test.js +262 -0
- package/tests/dynamic-pipeline.test.js +332 -0
- package/tests/knowledge-graph.test.js +322 -0
- package/tests/question-mapper.test.js +342 -0
- /package/.project/chats/{current → complete}/2025-10-04_CRITICAL-MODEL-FETCHING-BUG.md +0 -0
- /package/.project/chats/{current → complete}/2025-10-04_PHASE-4-2-COMPLETION-AND-ROADMAP.md +0 -0
- /package/.project/chats/{current → complete}/2025-10-04_PHASE-4-2-LEARNING-SYSTEM.md +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,226 @@ All notable changes to `@iservu-inc/adf-cli` will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.5.0] - 2025-10-05
|
|
9
|
+
|
|
10
|
+
### 🧠 Intelligent Answer Analysis & Dynamic Question Pipeline
|
|
11
|
+
|
|
12
|
+
**MAJOR FEATURE:** AI-powered answer analysis that extracts multiple pieces of information from each answer and intelligently skips redundant questions.
|
|
13
|
+
|
|
14
|
+
#### What This Means for Users
|
|
15
|
+
|
|
16
|
+
**Before v0.5.0:**
|
|
17
|
+
```
|
|
18
|
+
Q: What are you building?
|
|
19
|
+
A: A React web app with PostgreSQL database for user management
|
|
20
|
+
|
|
21
|
+
Q: What tech stack will you use? ← Redundant!
|
|
22
|
+
A: [User has to repeat: React, PostgreSQL...]
|
|
23
|
+
|
|
24
|
+
Q: What platform? ← Also redundant!
|
|
25
|
+
A: [User repeats: Web...]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**After v0.5.0:**
|
|
29
|
+
```
|
|
30
|
+
Q: What are you building?
|
|
31
|
+
A: A React web app with PostgreSQL database for user management
|
|
32
|
+
|
|
33
|
+
📚 Learned: TECH STACK: 90% confidence, PLATFORM: 85% confidence
|
|
34
|
+
|
|
35
|
+
⏭️ Skipping: What tech stack will you use?
|
|
36
|
+
✓ Already have: tech stack (90% confidence)
|
|
37
|
+
|
|
38
|
+
⏭️ Skipping: What platform?
|
|
39
|
+
✓ Already have: platform (85% confidence)
|
|
40
|
+
|
|
41
|
+
📊 Time saved: ~3 minutes
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### Core Components Added
|
|
45
|
+
|
|
46
|
+
**1. Answer Analyzer (`lib/analysis/answer-analyzer.js`)**
|
|
47
|
+
- Extracts 12 information types from each answer:
|
|
48
|
+
- Tech Stack, Architecture, Project Goal, Target Users
|
|
49
|
+
- Features, Platform, Constraints, Timeline
|
|
50
|
+
- Team Size, Deployment, Security, Performance
|
|
51
|
+
- Dual extraction: Heuristic (fast, always works) + AI (accurate, context-aware)
|
|
52
|
+
- Confidence scoring (0-100) for each extracted piece
|
|
53
|
+
- Works with or without AI client (graceful degradation)
|
|
54
|
+
|
|
55
|
+
**2. Knowledge Graph (`lib/analysis/knowledge-graph.js`)**
|
|
56
|
+
- Tracks all extracted information across the interview
|
|
57
|
+
- Maintains confidence scores and sources for each piece
|
|
58
|
+
- Merges similar information automatically
|
|
59
|
+
- Persists to disk (`_knowledge_graph.json`) for resume capability
|
|
60
|
+
- Provides displayable summaries with icons
|
|
61
|
+
|
|
62
|
+
**3. Question Mapper (`lib/analysis/question-mapper.js`)**
|
|
63
|
+
- Maps each question to the information types it gathers
|
|
64
|
+
- Determines which questions can be skipped based on knowledge
|
|
65
|
+
- Reorders questions dynamically to prioritize missing information
|
|
66
|
+
- Calculates time saved estimates
|
|
67
|
+
- Priority-based question boosting (fundamental questions first)
|
|
68
|
+
|
|
69
|
+
**4. Dynamic Pipeline (`lib/analysis/dynamic-pipeline.js`)**
|
|
70
|
+
- Orchestrates the entire intelligent question system
|
|
71
|
+
- Processes answers after each response
|
|
72
|
+
- Checks skip eligibility before each question
|
|
73
|
+
- Displays knowledge summaries periodically
|
|
74
|
+
- Final statistics showing questions asked/skipped and time saved
|
|
75
|
+
|
|
76
|
+
#### Integration with Interviewer
|
|
77
|
+
|
|
78
|
+
**Modified Files:**
|
|
79
|
+
- `lib/frameworks/interviewer.js`:
|
|
80
|
+
- Initialize DynamicPipeline with AI client
|
|
81
|
+
- Process each answer for information extraction
|
|
82
|
+
- Check shouldSkipQuestion() before asking
|
|
83
|
+
- Display knowledge summary every 2 blocks
|
|
84
|
+
- Show final stats at interview completion
|
|
85
|
+
|
|
86
|
+
#### User Experience Enhancements
|
|
87
|
+
|
|
88
|
+
**During Interview:**
|
|
89
|
+
- Real-time learning display after each answer
|
|
90
|
+
- Clear skip messages with reasoning and confidence
|
|
91
|
+
- Block summaries showing answered vs skipped questions
|
|
92
|
+
- Periodic knowledge summaries (every 2 blocks)
|
|
93
|
+
|
|
94
|
+
**Final Statistics:**
|
|
95
|
+
```
|
|
96
|
+
📊 Intelligent Question System Stats:
|
|
97
|
+
|
|
98
|
+
Questions asked: 12
|
|
99
|
+
Questions skipped: 8
|
|
100
|
+
Information pieces extracted: 24
|
|
101
|
+
High-confidence knowledge: 18
|
|
102
|
+
Estimated time saved: ~12 minutes
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### Benefits
|
|
106
|
+
|
|
107
|
+
- **Reduced user pain:** No more answering the same question multiple times
|
|
108
|
+
- **Time savings:** 40-60% reduction in redundant questions for comprehensive answers
|
|
109
|
+
- **Better UX:** System learns as you type, adapts in real-time
|
|
110
|
+
- **Intelligent adaptation:** Questions reordered based on what's missing
|
|
111
|
+
- **Full transparency:** See what was learned and why questions were skipped
|
|
112
|
+
|
|
113
|
+
#### Testing
|
|
114
|
+
|
|
115
|
+
- **New Test Suites:** 4 comprehensive test files added
|
|
116
|
+
- `tests/answer-analyzer.test.js` (58 tests)
|
|
117
|
+
- `tests/knowledge-graph.test.js` (45 tests)
|
|
118
|
+
- `tests/question-mapper.test.js` (47 tests)
|
|
119
|
+
- `tests/dynamic-pipeline.test.js` (50 tests)
|
|
120
|
+
- **Total Tests:** 200 passing (was 120)
|
|
121
|
+
- **Coverage:** All new modules fully tested
|
|
122
|
+
|
|
123
|
+
#### Technical Details
|
|
124
|
+
|
|
125
|
+
**Information Extraction Patterns:**
|
|
126
|
+
- Heuristic: Regex patterns + keyword matching (fast)
|
|
127
|
+
- AI: Context-aware analysis with reasoning (accurate)
|
|
128
|
+
- Merged results: Highest confidence wins
|
|
129
|
+
|
|
130
|
+
**Skip Decision Logic:**
|
|
131
|
+
```javascript
|
|
132
|
+
canSkip = ALL required info types satisfied
|
|
133
|
+
AND confidence >= threshold (default 75%)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Question Reordering:**
|
|
137
|
+
```
|
|
138
|
+
Score = 100 if no knowledge exists
|
|
139
|
+
= 0 if all knowledge exists
|
|
140
|
+
= partial % if some knowledge exists
|
|
141
|
+
|
|
142
|
+
Score *= priority boost (1.3x for fundamental questions)
|
|
143
|
+
Sort by score descending
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### Configuration Options
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
new DynamicPipeline(sessionPath, aiClient, {
|
|
150
|
+
enabled: true, // Enable/disable system
|
|
151
|
+
minSkipConfidence: 75, // Minimum confidence to skip
|
|
152
|
+
showAnalysis: true, // Show what was learned
|
|
153
|
+
verbose: false // Debug output
|
|
154
|
+
})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
#### Backward Compatibility
|
|
158
|
+
|
|
159
|
+
- ✅ Fully backward compatible
|
|
160
|
+
- ✅ Works with or without AI client
|
|
161
|
+
- ✅ Can be disabled if needed
|
|
162
|
+
- ✅ Graceful degradation on errors
|
|
163
|
+
- ✅ All existing tests still pass
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## [0.4.36] - 2025-10-04
|
|
168
|
+
|
|
169
|
+
### ✨ Multi-IDE Improvements + Config Command Enhancement
|
|
170
|
+
|
|
171
|
+
**1. Added IDE Deployment to `adf config`**
|
|
172
|
+
- New category: "IDE Deployment"
|
|
173
|
+
- Deploy to multiple IDEs without re-running `adf init`
|
|
174
|
+
- Shows which IDEs are already deployed
|
|
175
|
+
- Pre-selects already deployed IDEs in checkbox
|
|
176
|
+
- Allows quick re-deployment or deployment to new IDEs
|
|
177
|
+
|
|
178
|
+
**New Config Menu:**
|
|
179
|
+
```
|
|
180
|
+
⚙️ ADF Configuration
|
|
181
|
+
|
|
182
|
+
? Select configuration category:
|
|
183
|
+
> AI Provider Setup - ✓ Configured (Openai)
|
|
184
|
+
IDE Deployment - ✓ Deployed (Windsurf, Cursor)
|
|
185
|
+
Learning System - ✓ Active (5 sessions, 12 patterns)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Usage:**
|
|
189
|
+
```bash
|
|
190
|
+
adf config
|
|
191
|
+
# Select "IDE Deployment"
|
|
192
|
+
# Choose IDEs to deploy to
|
|
193
|
+
# Done!
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**2. Improved Cursor Generator**
|
|
197
|
+
- Added `loadSessionAnswers()` - reads actual session data
|
|
198
|
+
- Added `extractTechStackFromAnswers()` - detects tech in answers
|
|
199
|
+
- Added `extractWhatBuildingFromAnswers()` - finds project goals
|
|
200
|
+
- Falls back to session answers when PRP sections empty
|
|
201
|
+
- Better content instead of "See PRP for details"
|
|
202
|
+
|
|
203
|
+
**3. Improved VSCode/Copilot Generator**
|
|
204
|
+
- Same answer extraction improvements as Cursor
|
|
205
|
+
- Better Copilot instructions with real content
|
|
206
|
+
- Falls back to session answers
|
|
207
|
+
- Improved tech stack detection
|
|
208
|
+
|
|
209
|
+
**Code Changes:**
|
|
210
|
+
- config.js:18-27 - Added IDE_DEPLOYMENT category
|
|
211
|
+
- config.js:221-331 - IDE deployment configuration logic
|
|
212
|
+
- cursor-generator.js:41-51 - Made generateRules async
|
|
213
|
+
- cursor-generator.js:53-129 - Enhanced generateRulesPRP with answer extraction
|
|
214
|
+
- cursor-generator.js:373-424 - Added helper methods
|
|
215
|
+
- vscode-generator.js:40-50 - Made generateCopilotInstructions async
|
|
216
|
+
- vscode-generator.js:52-124 - Enhanced generateCopilotPRP with answer extraction
|
|
217
|
+
- vscode-generator.js:402-451 - Added helper methods
|
|
218
|
+
|
|
219
|
+
**Impact:**
|
|
220
|
+
- ✅ `adf config` now lets you deploy to IDEs
|
|
221
|
+
- ✅ Cursor files now have real content
|
|
222
|
+
- ✅ VSCode Copilot instructions have real content
|
|
223
|
+
- ✅ All generators use session answers as fallback
|
|
224
|
+
- ✅ No more "See PRP for details" placeholders
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
8
228
|
## [0.4.35] - 2025-10-04
|
|
9
229
|
|
|
10
230
|
### 🔧 MAJOR FIX: Windsurf Configuration - Activation Modes & Content Generation
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AI-Powered Answer Analyzer
|
|
5
|
+
*
|
|
6
|
+
* Analyzes user answers to extract multiple pieces of information:
|
|
7
|
+
* - Tech stack (frameworks, languages, databases)
|
|
8
|
+
* - Architecture patterns (frontend/backend, microservices, etc.)
|
|
9
|
+
* - Project goals and purpose
|
|
10
|
+
* - User personas and target audience
|
|
11
|
+
* - Features and functionality
|
|
12
|
+
* - Constraints and requirements
|
|
13
|
+
* - Timeline and team information
|
|
14
|
+
*
|
|
15
|
+
* Each extracted piece has a confidence score (0-100)
|
|
16
|
+
*/
|
|
17
|
+
class AnswerAnalyzer {
|
|
18
|
+
constructor(aiClient) {
|
|
19
|
+
this.aiClient = aiClient;
|
|
20
|
+
|
|
21
|
+
// Information types we can extract from answers
|
|
22
|
+
this.informationTypes = {
|
|
23
|
+
TECH_STACK: 'tech_stack',
|
|
24
|
+
ARCHITECTURE: 'architecture',
|
|
25
|
+
PROJECT_GOAL: 'project_goal',
|
|
26
|
+
TARGET_USERS: 'target_users',
|
|
27
|
+
FEATURES: 'features',
|
|
28
|
+
CONSTRAINTS: 'constraints',
|
|
29
|
+
TIMELINE: 'timeline',
|
|
30
|
+
TEAM_SIZE: 'team_size',
|
|
31
|
+
PLATFORM: 'platform',
|
|
32
|
+
DEPLOYMENT: 'deployment',
|
|
33
|
+
SECURITY: 'security',
|
|
34
|
+
PERFORMANCE: 'performance'
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Analyze an answer for multiple information types
|
|
40
|
+
*
|
|
41
|
+
* @param {string} questionText - The question that was asked
|
|
42
|
+
* @param {string} answer - User's answer
|
|
43
|
+
* @param {string} questionId - Question ID for context
|
|
44
|
+
* @returns {Promise<Array<{type: string, content: string, confidence: number, source: string}>>}
|
|
45
|
+
*/
|
|
46
|
+
async analyzeAnswer(questionText, answer, questionId) {
|
|
47
|
+
const extracted = [];
|
|
48
|
+
|
|
49
|
+
// First, try heuristic extraction (fast, always works)
|
|
50
|
+
const heuristicResults = this.heuristicExtraction(answer, questionId);
|
|
51
|
+
extracted.push(...heuristicResults);
|
|
52
|
+
|
|
53
|
+
// Then, if AI is available, use AI for deeper analysis
|
|
54
|
+
if (this.aiClient) {
|
|
55
|
+
try {
|
|
56
|
+
const aiResults = await this.aiExtraction(questionText, answer, questionId);
|
|
57
|
+
|
|
58
|
+
// Merge AI results with heuristic results
|
|
59
|
+
// If AI found something with higher confidence, use that
|
|
60
|
+
aiResults.forEach(aiResult => {
|
|
61
|
+
const existingIndex = extracted.findIndex(e => e.type === aiResult.type);
|
|
62
|
+
|
|
63
|
+
if (existingIndex >= 0) {
|
|
64
|
+
// Compare confidence scores
|
|
65
|
+
if (aiResult.confidence > extracted[existingIndex].confidence) {
|
|
66
|
+
extracted[existingIndex] = aiResult;
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
extracted.push(aiResult);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
} catch (error) {
|
|
73
|
+
// AI failed, heuristic results are still valid
|
|
74
|
+
console.log(chalk.gray(' (Using heuristic analysis only)'));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return extracted;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Heuristic-based extraction (pattern matching)
|
|
83
|
+
* Fast, works without AI, decent accuracy
|
|
84
|
+
*/
|
|
85
|
+
heuristicExtraction(answer, questionId) {
|
|
86
|
+
const extracted = [];
|
|
87
|
+
const lower = answer.toLowerCase();
|
|
88
|
+
|
|
89
|
+
// Tech Stack Detection
|
|
90
|
+
const techPatterns = {
|
|
91
|
+
frameworks: ['react', 'vue', 'angular', 'svelte', 'next.js', 'nuxt', 'gatsby'],
|
|
92
|
+
backend: ['node', 'express', 'django', 'flask', 'fastapi', 'spring', 'rails', 'laravel', '.net'],
|
|
93
|
+
databases: ['postgres', 'postgresql', 'mysql', 'mongodb', 'mongo', 'redis', 'sqlite', 'dynamodb'],
|
|
94
|
+
languages: ['javascript', 'typescript', 'python', 'java', 'c#', 'go', 'rust', 'php', 'ruby'],
|
|
95
|
+
cloud: ['aws', 'azure', 'gcp', 'google cloud', 'heroku', 'vercel', 'netlify', 'digital ocean']
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const foundTech = [];
|
|
99
|
+
Object.entries(techPatterns).forEach(([category, patterns]) => {
|
|
100
|
+
patterns.forEach(pattern => {
|
|
101
|
+
if (lower.includes(pattern)) {
|
|
102
|
+
foundTech.push(pattern);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (foundTech.length > 0) {
|
|
108
|
+
extracted.push({
|
|
109
|
+
type: this.informationTypes.TECH_STACK,
|
|
110
|
+
content: answer,
|
|
111
|
+
confidence: Math.min(85, 50 + (foundTech.length * 10)), // More mentions = higher confidence
|
|
112
|
+
source: questionId,
|
|
113
|
+
extractedTerms: foundTech
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Architecture Pattern Detection
|
|
118
|
+
const archPatterns = [
|
|
119
|
+
{ pattern: /frontend.*backend|backend.*frontend|separate.*backend|api.*frontend/i, value: 'frontend-backend-separation', confidence: 80 },
|
|
120
|
+
{ pattern: /microservice/i, value: 'microservices', confidence: 90 },
|
|
121
|
+
{ pattern: /monolith/i, value: 'monolithic', confidence: 90 },
|
|
122
|
+
{ pattern: /serverless|lambda/i, value: 'serverless', confidence: 85 },
|
|
123
|
+
{ pattern: /spa|single.*page.*application/i, value: 'spa', confidence: 75 },
|
|
124
|
+
{ pattern: /ssr|server.*side.*rendering/i, value: 'ssr', confidence: 75 },
|
|
125
|
+
{ pattern: /rest.*api|restful/i, value: 'rest-api', confidence: 70 },
|
|
126
|
+
{ pattern: /graphql/i, value: 'graphql', confidence: 90 }
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
archPatterns.forEach(({ pattern, value, confidence }) => {
|
|
130
|
+
if (pattern.test(answer)) {
|
|
131
|
+
extracted.push({
|
|
132
|
+
type: this.informationTypes.ARCHITECTURE,
|
|
133
|
+
content: answer,
|
|
134
|
+
confidence,
|
|
135
|
+
source: questionId,
|
|
136
|
+
pattern: value
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Platform Detection
|
|
142
|
+
const platformPatterns = [
|
|
143
|
+
{ pattern: /\bweb\b/i, value: 'web', confidence: 70 },
|
|
144
|
+
{ pattern: /mobile|ios|android|react native|flutter/i, value: 'mobile', confidence: 85 },
|
|
145
|
+
{ pattern: /desktop|electron/i, value: 'desktop', confidence: 85 },
|
|
146
|
+
{ pattern: /\bapi\b|rest.*api/i, value: 'api', confidence: 75 },
|
|
147
|
+
{ pattern: /cli|command.*line/i, value: 'cli', confidence: 80 }
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
platformPatterns.forEach(({ pattern, value, confidence }) => {
|
|
151
|
+
if (pattern.test(answer)) {
|
|
152
|
+
extracted.push({
|
|
153
|
+
type: this.informationTypes.PLATFORM,
|
|
154
|
+
content: answer,
|
|
155
|
+
confidence,
|
|
156
|
+
source: questionId,
|
|
157
|
+
platform: value
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Goal/Purpose Detection (if answer is substantial)
|
|
163
|
+
if (questionId.toLowerCase().includes('goal') ||
|
|
164
|
+
questionId.toLowerCase().includes('building') ||
|
|
165
|
+
questionId.toLowerCase().includes('purpose')) {
|
|
166
|
+
if (answer.length > 20) {
|
|
167
|
+
extracted.push({
|
|
168
|
+
type: this.informationTypes.PROJECT_GOAL,
|
|
169
|
+
content: answer,
|
|
170
|
+
confidence: 95, // Direct answer to goal question = high confidence
|
|
171
|
+
source: questionId
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Target Users Detection
|
|
177
|
+
const userPatterns = ['users', 'customers', 'audience', 'developers', 'businesses', 'consumers'];
|
|
178
|
+
if (userPatterns.some(pattern => lower.includes(pattern)) && answer.length > 15) {
|
|
179
|
+
extracted.push({
|
|
180
|
+
type: this.informationTypes.TARGET_USERS,
|
|
181
|
+
content: answer,
|
|
182
|
+
confidence: 70,
|
|
183
|
+
source: questionId
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Timeline Detection
|
|
188
|
+
const timePatterns = [
|
|
189
|
+
{ pattern: /\d+\s*(week|month|day)/i, confidence: 85 },
|
|
190
|
+
{ pattern: /asap|urgent|immediately/i, confidence: 70 },
|
|
191
|
+
{ pattern: /no.*rush|flexible|whenever/i, confidence: 65 }
|
|
192
|
+
];
|
|
193
|
+
|
|
194
|
+
timePatterns.forEach(({ pattern, confidence }) => {
|
|
195
|
+
if (pattern.test(answer)) {
|
|
196
|
+
extracted.push({
|
|
197
|
+
type: this.informationTypes.TIMELINE,
|
|
198
|
+
content: answer,
|
|
199
|
+
confidence,
|
|
200
|
+
source: questionId
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
return extracted;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* AI-powered extraction (more accurate, understands context)
|
|
210
|
+
*/
|
|
211
|
+
async aiExtraction(questionText, answer, questionId) {
|
|
212
|
+
if (!this.aiClient) return [];
|
|
213
|
+
|
|
214
|
+
const prompt = `Analyze this Q&A and extract ALL pieces of information mentioned:
|
|
215
|
+
|
|
216
|
+
Question: ${questionText}
|
|
217
|
+
Answer: ${answer}
|
|
218
|
+
|
|
219
|
+
Extract the following information types if mentioned (even if not the main topic):
|
|
220
|
+
1. Tech Stack: Frameworks, languages, databases, tools
|
|
221
|
+
2. Architecture: System design patterns, structure
|
|
222
|
+
3. Project Goal: What they're building and why
|
|
223
|
+
4. Target Users: Who will use this
|
|
224
|
+
5. Features: Specific functionality mentioned
|
|
225
|
+
6. Platform: Web, mobile, desktop, API, etc.
|
|
226
|
+
7. Constraints: Limitations, requirements
|
|
227
|
+
8. Timeline: Deadlines, timeframes
|
|
228
|
+
9. Team Size: How many people
|
|
229
|
+
10. Deployment: Hosting, infrastructure
|
|
230
|
+
11. Security: Security requirements
|
|
231
|
+
12. Performance: Performance needs
|
|
232
|
+
|
|
233
|
+
For EACH piece of information found, provide:
|
|
234
|
+
- type: One of the types above (lowercase with underscores)
|
|
235
|
+
- content: The relevant excerpt from the answer
|
|
236
|
+
- confidence: 0-100 (how sure are you this information is present and accurate)
|
|
237
|
+
- reasoning: Why you extracted this
|
|
238
|
+
|
|
239
|
+
Return as JSON array. Example:
|
|
240
|
+
[
|
|
241
|
+
{
|
|
242
|
+
"type": "tech_stack",
|
|
243
|
+
"content": "Next.js frontend with PostgreSQL database",
|
|
244
|
+
"confidence": 95,
|
|
245
|
+
"reasoning": "Explicitly mentioned Next.js and PostgreSQL"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"type": "architecture",
|
|
249
|
+
"content": "separate backend API",
|
|
250
|
+
"confidence": 85,
|
|
251
|
+
"reasoning": "Implies frontend-backend separation"
|
|
252
|
+
}
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
IMPORTANT: Only extract information that is ACTUALLY PRESENT in the answer. Don't infer or assume.`;
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
const response = await this.aiClient.sendMessage(prompt);
|
|
259
|
+
|
|
260
|
+
// Parse JSON response
|
|
261
|
+
const jsonMatch = response.match(/\[[\s\S]*\]/);
|
|
262
|
+
if (jsonMatch) {
|
|
263
|
+
const extracted = JSON.parse(jsonMatch[0]);
|
|
264
|
+
|
|
265
|
+
// Add source to each extraction
|
|
266
|
+
return extracted.map(item => ({
|
|
267
|
+
...item,
|
|
268
|
+
source: questionId,
|
|
269
|
+
method: 'ai'
|
|
270
|
+
}));
|
|
271
|
+
}
|
|
272
|
+
} catch (error) {
|
|
273
|
+
// Parsing failed or AI error
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Get a human-readable summary of extracted information
|
|
282
|
+
*/
|
|
283
|
+
getSummary(extractedInfo) {
|
|
284
|
+
const grouped = {};
|
|
285
|
+
|
|
286
|
+
extractedInfo.forEach(item => {
|
|
287
|
+
if (!grouped[item.type]) {
|
|
288
|
+
grouped[item.type] = [];
|
|
289
|
+
}
|
|
290
|
+
grouped[item.type].push(item);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
const lines = [];
|
|
294
|
+
Object.entries(grouped).forEach(([type, items]) => {
|
|
295
|
+
const highestConfidence = Math.max(...items.map(i => i.confidence));
|
|
296
|
+
const typeLabel = type.replace(/_/g, ' ').toUpperCase();
|
|
297
|
+
lines.push(`${typeLabel}: ${highestConfidence}% confidence`);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
return lines;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
module.exports = AnswerAnalyzer;
|