myavana-bot-test-core 2.0.2 → 2.0.3

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/index.js CHANGED
@@ -1,54 +1,142 @@
1
- // Re-export all shared modules
2
- module.exports = {
1
+ // packages/core/index.js - Fixed exports with proper module loading
2
+ const path = require('path');
3
+
4
+ // Helper function to safely load modules
5
+ function safeRequire(modulePath, moduleName) {
6
+ try {
7
+ const module = require(modulePath);
8
+ console.log(`✅ Successfully loaded ${moduleName}`);
9
+ return module;
10
+ } catch (error) {
11
+ console.error(`❌ Failed to load ${moduleName}:`, error.message);
12
+ return null;
13
+ }
14
+ }
15
+
16
+ // Load all modules with error handling
17
+ const modules = {
3
18
  // Database and utilities (Enhanced)
4
- connectDatabases: require('./src/database').connectDatabases,
5
- pgClient: require('./src/database').pgClient,
6
- redisClient: require('./src/database').redisClient,
19
+ connectDatabases: safeRequire('./src/database', 'database').connectDatabases,
20
+ pgClient: safeRequire('./src/database', 'database').pgClient,
21
+ redisClient: safeRequire('./src/database', 'database').redisClient,
7
22
 
8
23
  // Enhanced database management
9
- DatabaseManager: require('./src/enhancedDatabase').DatabaseManager,
10
- createDatabaseManager: require('./src/enhancedDatabase').createDatabaseManager,
11
- getDatabaseManager: require('./src/enhancedDatabase').getDatabaseManager,
24
+ DatabaseManager: safeRequire('./src/enhancedDatabase', 'DatabaseManager')?.DatabaseManager,
25
+ createDatabaseManager: safeRequire('./src/enhancedDatabase', 'DatabaseManager')?.createDatabaseManager,
26
+ getDatabaseManager: safeRequire('./src/enhancedDatabase', 'DatabaseManager')?.getDatabaseManager,
12
27
 
13
28
  // AI and session management
14
- ai: require('./src/ai'),
15
- DatabaseSessionStore: require('./src/session'),
29
+ ai: safeRequire('./src/ai', 'ai'),
30
+ DatabaseSessionStore: safeRequire('./src/session', 'DatabaseSessionStore'),
16
31
 
17
32
  // User and conversation management
18
- getUserDetails: require('./src/user').getUserDetails,
19
- getAllConversationsSummary: require('./src/conversation').getAllConversationsSummary,
20
- getConversationHistory: require('./src/conversation').getConversationHistory,
21
- saveConversation: require('./src/conversation').saveConversation,
22
- generateConversationSummary: require('./src/conversation').generateConversationSummary,
33
+ getUserDetails: safeRequire('./src/user', 'user')?.getUserDetails,
34
+ getAllConversationsSummary: safeRequire('./src/conversation', 'conversation')?.getAllConversationsSummary,
35
+ getConversationHistory: safeRequire('./src/conversation', 'conversation')?.getConversationHistory,
36
+ saveConversation: safeRequire('./src/conversation', 'conversation')?.saveConversation,
37
+ generateConversationSummary: safeRequire('./src/conversation', 'conversation')?.generateConversationSummary,
23
38
 
24
39
  // Post-processing and hair issues
25
- postProcessConversation: require('./src/postResponseProcessing').postProcessConversation,
26
- postResponseProcessing: require('./src/postResponseProcessing').postResponseProcessing,
27
- updateUserProfile: require('./src/postResponseProcessing').updateUserProfile,
28
- saveHairIssue: require('./src/hairIssues').saveHairIssue,
29
- getHairIssuesForUser: require('./src/hairIssues').getHairIssuesForUser,
30
- postResponseProductCheck: require('./src/postResponseProcessing').postResponseProductCheck,
40
+ postProcessConversation: safeRequire('./src/postResponseProcessing', 'postResponseProcessing')?.postProcessConversation,
41
+ postResponseProcessing: safeRequire('./src/postResponseProcessing', 'postResponseProcessing')?.postResponseProcessing,
42
+ updateUserProfile: safeRequire('./src/postResponseProcessing', 'postResponseProcessing')?.updateUserProfile,
43
+ saveHairIssue: safeRequire('./src/hairIssues', 'hairIssues')?.saveHairIssue,
44
+ getHairIssuesForUser: safeRequire('./src/hairIssues', 'hairIssues')?.getHairIssuesForUser,
45
+ postResponseProductCheck: safeRequire('./src/postResponseProcessing', 'postResponseProcessing')?.postResponseProductCheck,
31
46
 
32
47
  // Utilities
33
- getAllProducts: require('./src/utils').getAllProducts,
34
- getAllFaqs: require('./src/utils').getAllFaqs,
35
- getAllYoutubeVideos: require('./src/utils').getAllYoutubeVideos,
36
- getAllTestimonials: require('./src/utils').getAllTestimonials,
37
- getAdditionalInstructions: require('./src/utils').getAdditionalInstructions,
38
-
39
- // Smart systems (Existing)
40
- SmartPromptManager: require('./src/smartPromptManager'),
41
- ResponseCache: require('./src/responseCache'),
42
- ConversationAnalytics: require('./src/conversationAnalytics'),
43
- ErrorRecoveryManager: require('./src/errorRecovery'),
44
- PersonalizationEngine: require('./src/personalizationEngine'),
45
-
46
- // New enhanced systems
47
- UnifiedChatHandler: require('./src/unifiedChatHandler'),
48
- Logger: require('./src/logger').Logger,
49
- createLogger: require('./src/logger').createLogger,
50
- getLogger: require('./src/logger').getLogger,
51
- Validator: require('./src/validation'),
52
- ErrorHandler: require('./src/errorHandler'),
53
- HealthMonitor: require('./src/healthMonitor')
54
- };
48
+ getAllProducts: safeRequire('./src/utils', 'utils')?.getAllProducts,
49
+ getAllFaqs: safeRequire('./src/utils', 'utils')?.getAllFaqs,
50
+ getAllYoutubeVideos: safeRequire('./src/utils', 'utils')?.getAllYoutubeVideos,
51
+ getAllTestimonials: safeRequire('./src/utils', 'utils')?.getAllTestimonials,
52
+ getAdditionalInstructions: safeRequire('./src/utils', 'utils')?.getAdditionalInstructions,
53
+ };
54
+
55
+ // Smart systems - Load with proper error handling and fallbacks
56
+ const smartModules = {
57
+ SmartPromptManager: null,
58
+ ResponseCache: null,
59
+ ConversationAnalytics: null,
60
+ ErrorRecoveryManager: null,
61
+ PersonalizationEngine: null,
62
+ UnifiedChatHandler: null
63
+ };
64
+
65
+ // Try to load smart modules
66
+ const smartModulePaths = {
67
+ SmartPromptManager: './src/smartPromptManager',
68
+ ResponseCache: './src/responseCache',
69
+ ConversationAnalytics: './src/conversationAnalytics',
70
+ ErrorRecoveryManager: './src/errorRecovery',
71
+ PersonalizationEngine: './src/personalizationEngine',
72
+ UnifiedChatHandler: './src/unifiedChatHandler'
73
+ };
74
+
75
+ // Load each smart module with fallback
76
+ for (const [moduleName, modulePath] of Object.entries(smartModulePaths)) {
77
+ try {
78
+ const loadedModule = require(modulePath);
79
+
80
+ // Check if it's a constructor or needs default export
81
+ if (typeof loadedModule === 'function') {
82
+ smartModules[moduleName] = loadedModule;
83
+ console.log(`✅ Loaded ${moduleName} as constructor`);
84
+ } else if (loadedModule.default && typeof loadedModule.default === 'function') {
85
+ smartModules[moduleName] = loadedModule.default;
86
+ console.log(`✅ Loaded ${moduleName} from default export`);
87
+ } else if (loadedModule[moduleName] && typeof loadedModule[moduleName] === 'function') {
88
+ smartModules[moduleName] = loadedModule[moduleName];
89
+ console.log(`✅ Loaded ${moduleName} from named export`);
90
+ } else {
91
+ throw new Error(`Module ${moduleName} is not a constructor`);
92
+ }
93
+ } catch (error) {
94
+ console.error(`❌ Failed to load ${moduleName}:`, error.message);
95
+
96
+ // Create fallback classes
97
+ switch (moduleName) {
98
+ case 'SmartPromptManager':
99
+ smartModules[moduleName] = require('./src/fallbacks/smartPromptManagerFallback');
100
+ break;
101
+ case 'ResponseCache':
102
+ smartModules[moduleName] = require('./src/fallbacks/responseCacheFallback');
103
+ break;
104
+ case 'ConversationAnalytics':
105
+ smartModules[moduleName] = require('./src/fallbacks/conversationAnalyticsFallback');
106
+ break;
107
+ case 'ErrorRecoveryManager':
108
+ smartModules[moduleName] = require('./src/fallbacks/errorRecoveryFallback');
109
+ break;
110
+ case 'PersonalizationEngine':
111
+ smartModules[moduleName] = require('./src/fallbacks/personalizationEngineFallback');
112
+ break;
113
+ case 'UnifiedChatHandler':
114
+ smartModules[moduleName] = require('./src/fallbacks/unifiedChatHandlerFallback');
115
+ break;
116
+ }
117
+ console.log(`⚠️ Using fallback for ${moduleName}`);
118
+ }
119
+ }
120
+
121
+ // Enhanced systems
122
+ const enhancedModules = {
123
+ Logger: safeRequire('./src/logger', 'Logger')?.Logger,
124
+ createLogger: safeRequire('./src/logger', 'Logger')?.createLogger,
125
+ getLogger: safeRequire('./src/logger', 'Logger')?.getLogger,
126
+ Validator: safeRequire('./src/validation', 'Validator'),
127
+ ErrorHandler: safeRequire('./src/errorHandler', 'ErrorHandler'),
128
+ HealthMonitor: safeRequire('./src/healthMonitor', 'HealthMonitor')
129
+ };
130
+
131
+ // Export all modules
132
+ module.exports = {
133
+ ...modules,
134
+ ...smartModules,
135
+ ...enhancedModules
136
+ };
137
+
138
+ // Log export summary
139
+ console.log('📦 Core module exports summary:');
140
+ console.log(`- Basic modules: ${Object.keys(modules).filter(k => modules[k] !== null).length}/${Object.keys(modules).length}`);
141
+ console.log(`- Smart modules: ${Object.keys(smartModules).filter(k => smartModules[k] !== null).length}/${Object.keys(smartModules).length}`);
142
+ console.log(`- Enhanced modules: ${Object.keys(enhancedModules).filter(k => enhancedModules[k] !== null).length}/${Object.keys(enhancedModules).length}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myavana-bot-test-core",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "Shared bot functionality with enhanced features",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,105 @@
1
+ // conversationAnalyticsFallback.js - Minimal analytics tracking
2
+ class ConversationAnalyticsFallback {
3
+ constructor() {
4
+ console.log('⚠️ Using ConversationAnalytics fallback implementation');
5
+ this.events = [];
6
+ }
7
+
8
+ async trackWelcomeEvent(userId) {
9
+ this.logEvent('welcome', userId, { timestamp: new Date() });
10
+ }
11
+
12
+ async trackUserMessage(userId, conversationId, message, contextAnalysis) {
13
+ this.logEvent('user_message', userId, {
14
+ conversationId,
15
+ messageLength: message.length,
16
+ timestamp: new Date()
17
+ });
18
+ }
19
+
20
+ async trackAIResponse(userId, conversationId, response, model, responseTime, cached) {
21
+ this.logEvent('ai_response', userId, {
22
+ conversationId,
23
+ model,
24
+ responseTime,
25
+ cached,
26
+ timestamp: new Date()
27
+ });
28
+
29
+ // Log warnings for xAI usage
30
+ if (model.includes('xai')) {
31
+ console.warn('⚠️ xAI model used - this should be rare!');
32
+ }
33
+ }
34
+
35
+ async trackImageAnalysis(userId, conversationId, imageUrl, result, processingTime) {
36
+ this.logEvent('image_analysis', userId, {
37
+ conversationId,
38
+ processingTime,
39
+ success: !!result,
40
+ timestamp: new Date()
41
+ });
42
+ }
43
+
44
+ async trackConversionEvent(userId, conversationId, eventType, data) {
45
+ this.logEvent('conversion', userId, {
46
+ conversationId,
47
+ eventType,
48
+ ...data,
49
+ timestamp: new Date()
50
+ });
51
+ }
52
+
53
+ async trackUserSatisfaction(userId, conversationId, score, feedback) {
54
+ this.logEvent('satisfaction', userId, {
55
+ conversationId,
56
+ score,
57
+ feedback,
58
+ timestamp: new Date()
59
+ });
60
+ }
61
+
62
+ async trackModelFailure(model, error, responseTime) {
63
+ console.error(`🚨 Model failure: ${model} - ${error.message}`);
64
+ this.logEvent('model_failure', 'system', {
65
+ model,
66
+ error: error.message,
67
+ responseTime,
68
+ timestamp: new Date()
69
+ });
70
+ }
71
+
72
+ logEvent(type, userId, data) {
73
+ const event = { type, userId, data, timestamp: new Date() };
74
+ this.events.push(event);
75
+
76
+ // Keep only last 1000 events in memory
77
+ if (this.events.length > 1000) {
78
+ this.events = this.events.slice(-1000);
79
+ }
80
+
81
+ console.log(`📊 Event tracked (fallback): ${type}`);
82
+ }
83
+
84
+ async getUserAnalytics(userId, days = 30) {
85
+ const relevantEvents = this.events.filter(e => e.userId === userId);
86
+ return {
87
+ totalEvents: relevantEvents.length,
88
+ eventTypes: [...new Set(relevantEvents.map(e => e.type))]
89
+ };
90
+ }
91
+
92
+ detectHairJourneyStage(message) {
93
+ // Simple stage detection
94
+ const content = message.toLowerCase();
95
+ if (content.includes('new') || content.includes('starting')) return 'Stage 1: Something New';
96
+ if (content.includes('love') || content.includes('happy')) return 'Stage 2: I\'m Rocking This!';
97
+ if (content.includes('experiment') || content.includes('try')) return 'Stage 3: Experimenting';
98
+ if (content.includes('bored')) return 'Stage 4: Boredom';
99
+ if (content.includes('desperate') || content.includes('help')) return 'Stage 5: Desperation';
100
+ if (content.includes('damage') || content.includes('repair')) return 'Stage 6: Damage or Protection';
101
+ return 'Unknown';
102
+ }
103
+ }
104
+
105
+ module.exports = ConversationAnalyticsFallback;
@@ -0,0 +1,154 @@
1
+ // errorRecoveryFallback.js - Critical error recovery fallback
2
+ class ErrorRecoveryManagerFallback {
3
+ constructor() {
4
+ console.log('⚠️ Using ErrorRecoveryManager fallback implementation');
5
+
6
+ this.modelFailures = {
7
+ 'gemini20FlashExp': 0,
8
+ 'gemini15Flash': 0,
9
+ 'gemini15Pro': 0,
10
+ 'xai-grok-3-mini-fast': 0
11
+ };
12
+
13
+ this.failureThreshold = 3;
14
+ this.resetInterval = 300000; // 5 minutes
15
+
16
+ // Reset failure counts periodically
17
+ setInterval(() => this.resetFailureCounts(), this.resetInterval);
18
+ }
19
+
20
+ classifyError(error) {
21
+ const message = (error.message || '').toLowerCase();
22
+
23
+ if (message.includes('rate limit') || message.includes('quota')) {
24
+ return 'rate_limit';
25
+ }
26
+ if (message.includes('timeout')) {
27
+ return 'timeout';
28
+ }
29
+ if (message.includes('context') || message.includes('token')) {
30
+ return 'context_too_large';
31
+ }
32
+ if (message.includes('json') || message.includes('parse')) {
33
+ return 'parsing_error';
34
+ }
35
+ return 'unknown';
36
+ }
37
+
38
+ canMakeRequest(modelName) {
39
+ return this.modelFailures[modelName] < this.failureThreshold;
40
+ }
41
+
42
+ recordSuccess(modelName) {
43
+ if (this.modelFailures[modelName] > 0) {
44
+ this.modelFailures[modelName]--;
45
+ console.log(`✅ ${modelName} success recorded, failures: ${this.modelFailures[modelName]}`);
46
+ }
47
+ }
48
+
49
+ recordFailure(modelName) {
50
+ this.modelFailures[modelName]++;
51
+ console.warn(`❌ ${modelName} failure recorded, total: ${this.modelFailures[modelName]}`);
52
+
53
+ if (this.modelFailures[modelName] >= this.failureThreshold) {
54
+ console.error(`🚨 ${modelName} has reached failure threshold!`);
55
+ }
56
+ }
57
+
58
+ async attemptRecovery(error, operation, modelName, attempt = 1) {
59
+ const errorType = this.classifyError(error);
60
+ console.log(`🔄 Recovery attempt ${attempt} for ${errorType} error on ${modelName}`);
61
+
62
+ this.recordFailure(modelName);
63
+
64
+ // Simple retry logic
65
+ if (attempt > 2) {
66
+ console.error(`Max retries exceeded for ${modelName}`);
67
+ return null;
68
+ }
69
+
70
+ // Wait before retry based on error type
71
+ const delays = {
72
+ rate_limit: 60000,
73
+ timeout: 5000,
74
+ context_too_large: 0,
75
+ parsing_error: 1000,
76
+ unknown: 2000
77
+ };
78
+
79
+ const delay = delays[errorType] || 2000;
80
+
81
+ if (delay > 0) {
82
+ console.log(`⏳ Waiting ${delay}ms before retry...`);
83
+ await new Promise(resolve => setTimeout(resolve, delay));
84
+ }
85
+
86
+ return null; // Let caller handle retry
87
+ }
88
+
89
+ getEmergencyResponse() {
90
+ return {
91
+ messageType: 'html',
92
+ message: '<html><head><style>body{font-family:\'Archivo\',sans-serif;background-color:#f5f5f7;color:#222323;font-size:15px;line-height:1.5;}.highlight{font-family:\'Archivo Expanded Black\',sans-serif;font-size:14px;text-transform:uppercase;background-color:#fce5d7;color:#222323;padding:2px 6px;border-radius:4px;}</style></head><body><p>I\'m experiencing some technical difficulties. Let me connect you with a MYAVANA expert!</p><p>Try our <span class="highlight">HairAI™</span> analysis or book a consultation.</p></body></html>',
93
+ metadata: {
94
+ contentType: '300',
95
+ templateId: '12',
96
+ payload: [
97
+ { title: 'Connect to expert', message: 'Connect me to a human expert' },
98
+ { title: 'Learn about HairAI™', message: 'Tell me about HairAI™' },
99
+ { title: 'Book consultation', message: 'I want to book a consultation' }
100
+ ]
101
+ },
102
+ emergency: true
103
+ };
104
+ }
105
+
106
+ getReducedContext(chatHistory, maxMessages = 3) {
107
+ if (!chatHistory || chatHistory.length <= maxMessages) {
108
+ return chatHistory;
109
+ }
110
+ return chatHistory.slice(-maxMessages);
111
+ }
112
+
113
+ getSimplifiedPrompt(prompt) {
114
+ // Extract essential parts only
115
+ const lines = prompt.split('\n');
116
+ const essential = lines.filter(line => {
117
+ const lower = line.toLowerCase();
118
+ return lower.includes('you are mya') ||
119
+ lower.includes('critical') ||
120
+ lower.includes('json') ||
121
+ lower.includes('user:');
122
+ });
123
+ return essential.join('\n');
124
+ }
125
+
126
+ getAvailableModels() {
127
+ return Object.entries(this.modelFailures)
128
+ .filter(([model, failures]) => failures < this.failureThreshold)
129
+ .map(([model]) => model);
130
+ }
131
+
132
+ resetFailureCounts() {
133
+ for (const model in this.modelFailures) {
134
+ if (this.modelFailures[model] > 0) {
135
+ this.modelFailures[model] = Math.max(0, this.modelFailures[model] - 1);
136
+ }
137
+ }
138
+ console.log('🔄 Model failure counts decremented');
139
+ }
140
+
141
+ getHealthStatus() {
142
+ const status = {};
143
+ for (const [model, failures] of Object.entries(this.modelFailures)) {
144
+ status[model] = {
145
+ available: failures < this.failureThreshold,
146
+ failures,
147
+ health: failures === 0 ? 'healthy' : failures < this.failureThreshold ? 'degraded' : 'unhealthy'
148
+ };
149
+ }
150
+ return status;
151
+ }
152
+ }
153
+
154
+ module.exports = ErrorRecoveryManagerFallback;
@@ -0,0 +1,149 @@
1
+ // personalizationEngineFallback.js - Basic personalization fallback
2
+ class PersonalizationEngineFallback {
3
+ constructor() {
4
+ console.log('⚠️ Using PersonalizationEngine fallback implementation');
5
+ this.userProfiles = new Map();
6
+ }
7
+
8
+ async analyzeUserPersona(userId) {
9
+ // Simple persona detection based on recent interactions
10
+ const profile = this.userProfiles.get(userId) || {
11
+ messageCount: 0,
12
+ topics: [],
13
+ persona: 'hair_journey_beginner'
14
+ };
15
+
16
+ // Basic persona assignment
17
+ if (profile.messageCount > 20) {
18
+ profile.persona = 'hair_enthusiast';
19
+ } else if (profile.topics.includes('quick') || profile.topics.includes('simple')) {
20
+ profile.persona = 'busy_professional';
21
+ } else if (profile.topics.includes('problem') || profile.topics.includes('issue')) {
22
+ profile.persona = 'problem_solver';
23
+ }
24
+
25
+ return {
26
+ persona: profile.persona,
27
+ confidence: 0.7,
28
+ details: this.getPersonaDetails(profile.persona)
29
+ };
30
+ }
31
+
32
+ getPersonaDetails(persona) {
33
+ const personas = {
34
+ 'hair_enthusiast': {
35
+ name: 'Hair Enthusiast',
36
+ response_style: 'detailed_technical'
37
+ },
38
+ 'busy_professional': {
39
+ name: 'Busy Professional',
40
+ response_style: 'concise_actionable'
41
+ },
42
+ 'hair_journey_beginner': {
43
+ name: 'Hair Journey Beginner',
44
+ response_style: 'educational_supportive'
45
+ },
46
+ 'problem_solver': {
47
+ name: 'Problem Solver',
48
+ response_style: 'problem_solution_focused'
49
+ }
50
+ };
51
+
52
+ return personas[persona] || personas['hair_journey_beginner'];
53
+ }
54
+
55
+ async getPersonalizedResponse(userId, query, baseResponse, context = {}) {
56
+ try {
57
+ // Track user interaction
58
+ const profile = this.userProfiles.get(userId) || {
59
+ messageCount: 0,
60
+ topics: [],
61
+ persona: 'hair_journey_beginner'
62
+ };
63
+
64
+ profile.messageCount++;
65
+
66
+ // Simple topic tracking
67
+ const queryLower = query.toLowerCase();
68
+ if (queryLower.includes('product')) profile.topics.push('product');
69
+ if (queryLower.includes('routine')) profile.topics.push('routine');
70
+ if (queryLower.includes('problem')) profile.topics.push('problem');
71
+
72
+ this.userProfiles.set(userId, profile);
73
+
74
+ // For fallback, just return the base response
75
+ // Real personalization would modify the response based on persona
76
+ return baseResponse;
77
+
78
+ } catch (error) {
79
+ console.error('Personalization fallback error:', error);
80
+ return baseResponse;
81
+ }
82
+ }
83
+
84
+ async getPersonalizationContext(userId) {
85
+ const profile = this.userProfiles.get(userId) || {
86
+ messageCount: 0,
87
+ topics: [],
88
+ persona: 'hair_journey_beginner',
89
+ lastActive: new Date()
90
+ };
91
+
92
+ return {
93
+ messageCount: profile.messageCount,
94
+ topicsDiscussed: profile.topics,
95
+ persona: profile.persona,
96
+ isNewUser: profile.messageCount < 5
97
+ };
98
+ }
99
+
100
+ async trackPersonalizationMetrics(userId, persona, query, response) {
101
+ console.log(`📊 Personalization tracked (fallback): ${persona} for user ${userId}`);
102
+ }
103
+
104
+ // Helper methods for basic personalization
105
+ shouldUseDetailedResponse(persona) {
106
+ return persona === 'hair_enthusiast';
107
+ }
108
+
109
+ shouldUseConciseResponse(persona) {
110
+ return persona === 'busy_professional';
111
+ }
112
+
113
+ shouldIncludeEducation(persona) {
114
+ return persona === 'hair_journey_beginner';
115
+ }
116
+
117
+ getRecommendedSuggestions(persona) {
118
+ const suggestions = {
119
+ 'hair_enthusiast': [
120
+ { title: 'Latest hair science', message: 'Tell me about the latest hair science' },
121
+ { title: 'Ingredient analysis', message: 'Analyze ingredients in my products' },
122
+ { title: 'Advanced techniques', message: 'What are advanced hair care techniques?' }
123
+ ],
124
+ 'busy_professional': [
125
+ { title: 'Quick routine', message: 'Give me a 5-minute hair routine' },
126
+ { title: 'Time-saving tips', message: 'What are time-saving hair tips?' },
127
+ { title: 'Low maintenance', message: 'Suggest low maintenance styles' }
128
+ ],
129
+ 'hair_journey_beginner': [
130
+ { title: 'Hair type', message: 'What\'s my hair type?' },
131
+ { title: 'Basic routine', message: 'Help me create a basic hair routine' },
132
+ { title: 'Learn about HairAI™', message: 'What is HairAI™?' }
133
+ ],
134
+ 'problem_solver': [
135
+ { title: 'Diagnose issue', message: 'Help diagnose my hair problem' },
136
+ { title: 'Treatment options', message: 'What treatments do you recommend?' },
137
+ { title: 'Expert consultation', message: 'Should I book a consultation?' }
138
+ ]
139
+ };
140
+
141
+ return suggestions[persona] || suggestions['hair_journey_beginner'];
142
+ }
143
+
144
+ clearUserProfile(userId) {
145
+ this.userProfiles.delete(userId);
146
+ }
147
+ }
148
+
149
+ module.exports = PersonalizationEngineFallback;
@@ -0,0 +1,48 @@
1
+ // responseCacheFallback.js - Minimal fallback for ResponseCache
2
+ class ResponseCacheFallback {
3
+ constructor() {
4
+ console.log('⚠️ Using ResponseCache fallback implementation');
5
+ this.cache = new Map();
6
+ this.maxCacheSize = 100;
7
+ this.ttl = 300000; // 5 minutes
8
+ }
9
+
10
+ async getCachedResponse(userId, query) {
11
+ const key = `${userId}:${query.toLowerCase().trim()}`;
12
+ const cached = this.cache.get(key);
13
+
14
+ if (cached && Date.now() - cached.timestamp < this.ttl) {
15
+ console.log('📦 Cache hit (fallback)');
16
+ return cached.response;
17
+ }
18
+
19
+ return null;
20
+ }
21
+
22
+ async cacheResponse(userId, query, response) {
23
+ // Don't cache emergency responses or errors
24
+ if (response.emergency || response.error) return;
25
+
26
+ const key = `${userId}:${query.toLowerCase().trim()}`;
27
+
28
+ // Simple LRU - remove oldest if at capacity
29
+ if (this.cache.size >= this.maxCacheSize) {
30
+ const firstKey = this.cache.keys().next().value;
31
+ this.cache.delete(firstKey);
32
+ }
33
+
34
+ this.cache.set(key, {
35
+ response,
36
+ timestamp: Date.now()
37
+ });
38
+
39
+ console.log('💾 Response cached (fallback)');
40
+ }
41
+
42
+ clearCache() {
43
+ this.cache.clear();
44
+ console.log('🧹 Cache cleared (fallback)');
45
+ }
46
+ }
47
+
48
+ module.exports = ResponseCacheFallback;