@peopl-health/nexus 2.4.7 → 2.4.8
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/examples/assistants/DoctorScheduleAssistant.js +3 -2
- package/lib/adapters/BaileysProvider.js +5 -4
- package/lib/adapters/TwilioProvider.js +20 -19
- package/lib/assistants/BaseAssistant.js +7 -6
- package/lib/config/awsConfig.js +14 -12
- package/lib/config/llmConfig.js +3 -2
- package/lib/config/mongoAuthConfig.js +5 -5
- package/lib/controllers/assistantController.js +12 -11
- package/lib/controllers/bugReportController.js +6 -5
- package/lib/controllers/conversationController.js +72 -71
- package/lib/controllers/interactionController.js +7 -6
- package/lib/controllers/mediaController.js +15 -13
- package/lib/controllers/messageController.js +7 -6
- package/lib/controllers/patientController.js +2 -1
- package/lib/controllers/qualityMessageController.js +5 -4
- package/lib/controllers/templateController.js +11 -9
- package/lib/controllers/uploadController.js +3 -1
- package/lib/core/NexusMessaging.js +18 -18
- package/lib/helpers/assistantHelper.js +8 -9
- package/lib/helpers/baileysHelper.js +4 -3
- package/lib/helpers/filesHelper.js +9 -8
- package/lib/helpers/llmsHelper.js +5 -4
- package/lib/helpers/mediaHelper.js +3 -2
- package/lib/helpers/messageHelper.js +12 -11
- package/lib/helpers/processHelper.js +1 -1
- package/lib/helpers/qrHelper.js +2 -1
- package/lib/helpers/twilioMediaProcessor.js +19 -29
- package/lib/helpers/whatsappHelper.js +3 -2
- package/lib/index.js +11 -14
- package/lib/interactive/index.js +11 -11
- package/lib/middleware/requestId.js +9 -14
- package/lib/models/messageModel.js +5 -4
- package/lib/providers/OpenAIAssistantsProvider.js +10 -9
- package/lib/providers/OpenAIResponsesProvider.js +18 -17
- package/lib/providers/OpenAIResponsesProviderTools.js +3 -5
- package/lib/providers/createProvider.js +2 -1
- package/lib/services/airtableService.js +6 -5
- package/lib/services/assistantService.js +20 -20
- package/lib/services/conversationService.js +16 -16
- package/lib/services/preprocessingHooks.js +3 -1
- package/lib/storage/MongoStorage.js +14 -14
- package/lib/utils/errorHandler.js +3 -1
- package/lib/utils/logger.js +35 -3
- package/lib/utils/sanitizer.js +0 -6
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { BaseAssistant } = require('../../lib/assistants/BaseAssistant');
|
|
2
|
+
const { logger } = require('../../lib/utils/logger');
|
|
2
3
|
|
|
3
4
|
class DoctorScheduleAssistant extends BaseAssistant {
|
|
4
5
|
constructor(thread) {
|
|
@@ -38,7 +39,7 @@ class DoctorScheduleAssistant extends BaseAssistant {
|
|
|
38
39
|
}
|
|
39
40
|
},
|
|
40
41
|
handler: async (payload = {}) => {
|
|
41
|
-
|
|
42
|
+
logger.info('[DoctorScheduleAssistant] storePatientAppointment', payload);
|
|
42
43
|
|
|
43
44
|
if (!payload.contact_number || !payload.appointment_type) {
|
|
44
45
|
return JSON.stringify({
|
|
@@ -58,7 +59,7 @@ class DoctorScheduleAssistant extends BaseAssistant {
|
|
|
58
59
|
notes: payload.notes || null
|
|
59
60
|
};
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
logger.info('[DoctorScheduleAssistant] Appointment captured', appointment);
|
|
62
63
|
|
|
63
64
|
return JSON.stringify({ success: true, appointment });
|
|
64
65
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { MessageProvider } = require('../core/MessageProvider');
|
|
2
|
+
const { logger } = require('../utils/logger');
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Baileys WhatsApp messaging provider
|
|
@@ -155,7 +156,7 @@ class BaileysProvider extends MessageProvider {
|
|
|
155
156
|
? __nexusSend
|
|
156
157
|
: async (payload) => await this.sendMessage(payload);
|
|
157
158
|
|
|
158
|
-
|
|
159
|
+
logger.info('[BaileysProvider] Scheduled message created', {
|
|
159
160
|
code: scheduledMessage.code,
|
|
160
161
|
delay,
|
|
161
162
|
hasMedia: Boolean(scheduledMessage.fileUrl)
|
|
@@ -165,15 +166,15 @@ class BaileysProvider extends MessageProvider {
|
|
|
165
166
|
try {
|
|
166
167
|
const payload = { ...scheduledMessage };
|
|
167
168
|
delete payload.__nexusSend;
|
|
168
|
-
|
|
169
|
+
logger.info('[BaileysProvider] Timer fired', {
|
|
169
170
|
code: payload.to || payload.code,
|
|
170
171
|
hasMessage: Boolean(payload.message || payload.body),
|
|
171
172
|
hasMedia: Boolean(payload.fileUrl)
|
|
172
173
|
});
|
|
173
174
|
await sender(payload);
|
|
174
|
-
|
|
175
|
+
logger.info('Scheduled message sent successfully');
|
|
175
176
|
} catch (error) {
|
|
176
|
-
|
|
177
|
+
logger.error(`Scheduled message failed: ${error.message}`);
|
|
177
178
|
}
|
|
178
179
|
}, delay);
|
|
179
180
|
|
|
@@ -5,6 +5,7 @@ const { uploadMediaToS3, getFileExtension } = require('../helpers/mediaHelper');
|
|
|
5
5
|
const { sanitizeMediaFilename } = require('../utils/sanitizer');
|
|
6
6
|
const { generatePresignedUrl } = require('../config/awsConfig');
|
|
7
7
|
const { validateMedia, getMediaType } = require('../utils/mediaValidator');
|
|
8
|
+
const { logger } = require('../utils/logger');
|
|
8
9
|
const { v4: uuidv4 } = require('uuid');
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -90,7 +91,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
90
91
|
delete messageParams.body;
|
|
91
92
|
}
|
|
92
93
|
if (mediaPrep.uploaded) {
|
|
93
|
-
|
|
94
|
+
logger.info('[TwilioProvider] Outbound media uploaded to S3', {
|
|
94
95
|
code: formattedCode,
|
|
95
96
|
bucket: mediaPrep.bucketName,
|
|
96
97
|
key: mediaPrep.key
|
|
@@ -103,7 +104,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
103
104
|
throw new Error('Message must have body, media URL, or content SID');
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
|
|
107
|
+
logger.info('[TwilioProvider] Sending message', messageParams);
|
|
107
108
|
|
|
108
109
|
try {
|
|
109
110
|
const result = await this.twilioClient.messages.create(messageParams);
|
|
@@ -119,9 +120,9 @@ class TwilioProvider extends MessageProvider {
|
|
|
119
120
|
fromMe: true,
|
|
120
121
|
processed: false
|
|
121
122
|
});
|
|
122
|
-
|
|
123
|
+
logger.info('[TwilioProvider] Message persisted successfully', { messageId: result.sid });
|
|
123
124
|
} catch (storageError) {
|
|
124
|
-
|
|
125
|
+
logger.error('TwilioProvider storage failed:', storageError);
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
return {
|
|
@@ -143,7 +144,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
143
144
|
? __nexusSend
|
|
144
145
|
: async (payload) => await this.sendMessage(payload);
|
|
145
146
|
|
|
146
|
-
|
|
147
|
+
logger.info('[TwilioProvider] Scheduled message created', {
|
|
147
148
|
code: scheduledMessage.code,
|
|
148
149
|
delay,
|
|
149
150
|
hasContentSid: Boolean(scheduledMessage.contentSid)
|
|
@@ -178,7 +179,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
178
179
|
})();
|
|
179
180
|
|
|
180
181
|
if (!ScheduledMessageModel) {
|
|
181
|
-
|
|
182
|
+
logger.warn('[TwilioProvider] Scheduled message model unavailable for status update');
|
|
182
183
|
return;
|
|
183
184
|
}
|
|
184
185
|
|
|
@@ -190,7 +191,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
190
191
|
})();
|
|
191
192
|
|
|
192
193
|
if (!query) {
|
|
193
|
-
|
|
194
|
+
logger.warn('[TwilioProvider] Scheduled message status update skipped: no identifier', {
|
|
194
195
|
hasId: Boolean(scheduledMessage._id),
|
|
195
196
|
messageId,
|
|
196
197
|
existingWaId: scheduledMessage.wa_id
|
|
@@ -204,7 +205,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
204
205
|
$push: { statusHistory: statusEntry }
|
|
205
206
|
});
|
|
206
207
|
} catch (statusErr) {
|
|
207
|
-
|
|
208
|
+
logger.warn('[TwilioProvider] Failed to update scheduled message status', statusErr?.message || statusErr);
|
|
208
209
|
}
|
|
209
210
|
};
|
|
210
211
|
|
|
@@ -218,7 +219,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
218
219
|
if (payload.message && !payload.body) {
|
|
219
220
|
payload.body = payload.message;
|
|
220
221
|
}
|
|
221
|
-
|
|
222
|
+
logger.info('[TwilioProvider] Timer fired', {
|
|
222
223
|
code: payload.code,
|
|
223
224
|
hasMessage: Boolean(payload.message || payload.body),
|
|
224
225
|
hasMedia: Boolean(payload.fileUrl)
|
|
@@ -228,7 +229,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
228
229
|
await updateStatus('sent', messageId);
|
|
229
230
|
} catch (error) {
|
|
230
231
|
await updateStatus('failed', null, error);
|
|
231
|
-
|
|
232
|
+
logger.error(`Scheduled message failed: ${error.message}`);
|
|
232
233
|
}
|
|
233
234
|
}, delay);
|
|
234
235
|
|
|
@@ -248,7 +249,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
248
249
|
}
|
|
249
250
|
|
|
250
251
|
if (!bucketName) {
|
|
251
|
-
|
|
252
|
+
logger.warn('[TwilioProvider] AWS_S3_BUCKET_NAME not configured. Skipping media upload for outbound message.');
|
|
252
253
|
return { mediaUrl: fileUrl, uploaded: false };
|
|
253
254
|
}
|
|
254
255
|
|
|
@@ -283,7 +284,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
283
284
|
const mediaType = validation.valid ? validation.mediaType : (declaredType || getMediaType(contentType));
|
|
284
285
|
|
|
285
286
|
if (!validation.valid) {
|
|
286
|
-
|
|
287
|
+
logger.warn('[TwilioProvider] Outbound media validation warning', {
|
|
287
288
|
code: formattedCode,
|
|
288
289
|
message: validation.message
|
|
289
290
|
});
|
|
@@ -332,7 +333,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
332
333
|
key
|
|
333
334
|
};
|
|
334
335
|
} catch (error) {
|
|
335
|
-
|
|
336
|
+
logger.error('[TwilioProvider] Failed to upload outbound media to S3. Using original URL.', {
|
|
336
337
|
code: formattedCode,
|
|
337
338
|
error: error?.message || error
|
|
338
339
|
});
|
|
@@ -395,7 +396,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
395
396
|
const template = await this.getTemplate(contentSid);
|
|
396
397
|
|
|
397
398
|
if (!template || !template.types) {
|
|
398
|
-
|
|
399
|
+
logger.warn('[TwilioProvider] Template not found or has no types:', contentSid);
|
|
399
400
|
return null;
|
|
400
401
|
}
|
|
401
402
|
|
|
@@ -403,7 +404,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
403
404
|
let textContent = this.extractTextFromTemplate(template);
|
|
404
405
|
|
|
405
406
|
if (!textContent) {
|
|
406
|
-
|
|
407
|
+
logger.warn('[TwilioProvider] No text content found in template:', contentSid);
|
|
407
408
|
return null;
|
|
408
409
|
}
|
|
409
410
|
|
|
@@ -414,7 +415,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
414
415
|
|
|
415
416
|
return textContent.trim();
|
|
416
417
|
} catch (error) {
|
|
417
|
-
|
|
418
|
+
logger.error('[TwilioProvider] Error rendering template:', error.message);
|
|
418
419
|
return null;
|
|
419
420
|
}
|
|
420
421
|
}
|
|
@@ -541,7 +542,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
541
542
|
|
|
542
543
|
return rendered.trim();
|
|
543
544
|
} catch (error) {
|
|
544
|
-
|
|
545
|
+
logger.warn('[TwilioProvider] Error rendering template variables:', error.message);
|
|
545
546
|
return templateBody; // Return original template if rendering fails
|
|
546
547
|
}
|
|
547
548
|
}
|
|
@@ -598,7 +599,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
598
599
|
}
|
|
599
600
|
}
|
|
600
601
|
} catch (approvalError) {
|
|
601
|
-
|
|
602
|
+
logger.warn('Approval request fetch failed:', approvalError?.message || approvalError);
|
|
602
603
|
}
|
|
603
604
|
|
|
604
605
|
return {
|
|
@@ -606,7 +607,7 @@ class TwilioProvider extends MessageProvider {
|
|
|
606
607
|
approvalRequest: processedApprovalRequest
|
|
607
608
|
};
|
|
608
609
|
} catch (error) {
|
|
609
|
-
|
|
610
|
+
logger.error('Error checking approval status:', error);
|
|
610
611
|
throw error;
|
|
611
612
|
}
|
|
612
613
|
}
|
|
@@ -3,6 +3,7 @@ const { Thread } = require('../models/threadModel');
|
|
|
3
3
|
const { Message } = require('../models/messageModel');
|
|
4
4
|
const { formatMessage } = require('../helpers/messageHelper');
|
|
5
5
|
const { createProvider } = require('../providers/createProvider');
|
|
6
|
+
const { logger } = require('../utils/logger');
|
|
6
7
|
|
|
7
8
|
const DEFAULT_MAX_HISTORICAL_MESSAGES = parseInt(process.env.MAX_HISTORICAL_MESSAGES || '50', 10);
|
|
8
9
|
|
|
@@ -38,7 +39,7 @@ class BaseAssistant {
|
|
|
38
39
|
}
|
|
39
40
|
} catch (err) {
|
|
40
41
|
if (process.env.NODE_ENV !== 'production') {
|
|
41
|
-
|
|
42
|
+
logger.warn('[BaseAssistant] Failed to initialise OpenAIProvider from client:', err?.message || err);
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
}
|
|
@@ -53,7 +54,7 @@ class BaseAssistant {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
if (this.assistantId) {
|
|
56
|
-
|
|
57
|
+
logger.info(`Assistant ${this.assistantId} initialized.`);
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
|
|
@@ -75,7 +76,7 @@ class BaseAssistant {
|
|
|
75
76
|
llmConfig.setOpenAIProvider(provider);
|
|
76
77
|
}
|
|
77
78
|
} catch (error) {
|
|
78
|
-
|
|
79
|
+
logger.warn('[BaseAssistant] Failed to bootstrap provider:', error?.message || error);
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
}
|
|
@@ -215,11 +216,11 @@ class BaseAssistant {
|
|
|
215
216
|
})
|
|
216
217
|
.filter(message => message !== null);
|
|
217
218
|
|
|
218
|
-
|
|
219
|
+
logger.info(`[buildInitialMessages] Built ${formattedMessages.length} initial messages for ${code}`);
|
|
219
220
|
|
|
220
221
|
return formattedMessages;
|
|
221
222
|
} catch (error) {
|
|
222
|
-
|
|
223
|
+
logger.error('[buildInitialMessages] Error fetching messages:', error);
|
|
223
224
|
return [];
|
|
224
225
|
}
|
|
225
226
|
}
|
|
@@ -235,7 +236,7 @@ class BaseAssistant {
|
|
|
235
236
|
}
|
|
236
237
|
|
|
237
238
|
if (this.assistantId) {
|
|
238
|
-
|
|
239
|
+
logger.info(`Assistant ${this.assistantId} closed`);
|
|
239
240
|
}
|
|
240
241
|
|
|
241
242
|
return `Assistant ${this.assistantId || ''} successfully closed.`.trim();
|
package/lib/config/awsConfig.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const { logger } = require('../utils/logger');
|
|
2
|
+
|
|
1
3
|
const AWS = require('aws-sdk');
|
|
2
4
|
const fs = require('fs');
|
|
3
5
|
const path = require('path');
|
|
@@ -26,16 +28,16 @@ async function uploadBufferToS3(buffer, bucketName, key, contentType, isWhatsApp
|
|
|
26
28
|
|
|
27
29
|
try {
|
|
28
30
|
const data = await s3.upload(params).promise();
|
|
29
|
-
|
|
31
|
+
logger.info(`File uploaded successfully at ${data.Location}`);
|
|
30
32
|
return data.Location;
|
|
31
33
|
} catch (error) {
|
|
32
|
-
|
|
34
|
+
logger.error(`Error uploading file: ${error.message}`);
|
|
33
35
|
throw error;
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
async function downloadFileFromS3(bucketName, key, downloadPath) {
|
|
38
|
-
|
|
40
|
+
logger.info(`[S3] Attempting to download file from S3 - Bucket: ${bucketName}, Key: ${key}`);
|
|
39
41
|
|
|
40
42
|
const headParams = {
|
|
41
43
|
Bucket: bucketName,
|
|
@@ -44,11 +46,11 @@ async function downloadFileFromS3(bucketName, key, downloadPath) {
|
|
|
44
46
|
|
|
45
47
|
try {
|
|
46
48
|
await s3.headObject(headParams).promise();
|
|
47
|
-
|
|
49
|
+
logger.info(`[S3] Key exists in bucket: ${key}`);
|
|
48
50
|
} catch (headErr) {
|
|
49
|
-
|
|
51
|
+
logger.error(`[S3] Object check failed - Key: ${key}, Error: ${headErr.code} - ${headErr.message}`);
|
|
50
52
|
if (headErr.code === 'NotFound') {
|
|
51
|
-
|
|
53
|
+
logger.info(`[S3] Key does not exist in bucket: ${key}`);
|
|
52
54
|
}
|
|
53
55
|
throw headErr;
|
|
54
56
|
}
|
|
@@ -59,21 +61,21 @@ async function downloadFileFromS3(bucketName, key, downloadPath) {
|
|
|
59
61
|
};
|
|
60
62
|
|
|
61
63
|
try {
|
|
62
|
-
|
|
64
|
+
logger.info(`[S3] Downloading file data - Key: ${key}`);
|
|
63
65
|
const data = await s3.getObject(params).promise();
|
|
64
|
-
|
|
66
|
+
logger.info(`[S3] Successfully retrieved file - Key: ${key}, ContentType: ${data.ContentType}, Size: ${data.ContentLength} bytes`);
|
|
65
67
|
|
|
66
68
|
if (downloadPath) {
|
|
67
69
|
const directory = path.dirname(downloadPath);
|
|
68
70
|
fs.mkdirSync(directory, { recursive: true });
|
|
69
71
|
fs.writeFileSync(downloadPath, data.Body);
|
|
70
|
-
|
|
72
|
+
logger.info(`[S3] File saved to disk at: ${downloadPath}`);
|
|
71
73
|
return;
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
return data;
|
|
75
77
|
} catch (error) {
|
|
76
|
-
|
|
78
|
+
logger.error(`[S3] Error downloading file - Key: ${key}, Error: ${error.code} - ${error.message}`);
|
|
77
79
|
throw error;
|
|
78
80
|
}
|
|
79
81
|
}
|
|
@@ -87,10 +89,10 @@ async function generatePresignedUrl(bucketName, key, expiration = 3000) {
|
|
|
87
89
|
|
|
88
90
|
try {
|
|
89
91
|
const url = await s3.getSignedUrlPromise('getObject', params);
|
|
90
|
-
|
|
92
|
+
logger.info(`Presigned URL generated: ${url}`);
|
|
91
93
|
return url;
|
|
92
94
|
} catch (error) {
|
|
93
|
-
|
|
95
|
+
logger.error(`Error generating presigned URL: ${error.message}`);
|
|
94
96
|
throw error;
|
|
95
97
|
}
|
|
96
98
|
}
|
package/lib/config/llmConfig.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const runtimeConfig = require('./runtimeConfig');
|
|
2
|
+
const { logger } = require('../utils/logger');
|
|
2
3
|
const { createProvider } = require('../providers/createProvider');
|
|
3
4
|
|
|
4
5
|
let anthropicClient = null;
|
|
@@ -61,9 +62,9 @@ const resolveAnthropicClient = () => {
|
|
|
61
62
|
try {
|
|
62
63
|
const { Anthropic } = require('@anthropic-ai/sdk');
|
|
63
64
|
anthropicClient = new Anthropic({ apiKey });
|
|
64
|
-
|
|
65
|
+
logger.info('[llmConfig] Anthropic client initialised');
|
|
65
66
|
} catch (error) {
|
|
66
|
-
|
|
67
|
+
logger.warn('[llmConfig] Failed to initialise Anthropic client. Install @anthropic-ai/sdk if you plan to use vision features.', error?.message || error);
|
|
67
68
|
anthropicClient = null;
|
|
68
69
|
}
|
|
69
70
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
const { MongoClient } = require('mongodb');
|
|
2
|
-
|
|
3
2
|
const { proto, Curve, signedKeyPair, generateRegistrationId } = require('baileys');
|
|
4
3
|
const { randomBytes } = require('crypto');
|
|
4
|
+
const { logger } = require('../utils/logger');
|
|
5
5
|
|
|
6
6
|
async function connectToMongo(mongoClient) {
|
|
7
7
|
try {
|
|
8
8
|
await mongoClient.connect();
|
|
9
|
-
|
|
9
|
+
logger.info('Connected to Mongo database successfully.');
|
|
10
10
|
} catch (err) {
|
|
11
|
-
|
|
11
|
+
logger.error('Error connecting to Mongo database:', err.message);
|
|
12
12
|
throw err;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -87,7 +87,7 @@ async function useMongoDBAuthState(uri, dbName, sessionId) {
|
|
|
87
87
|
const data = JSON.stringify(await collection.findOne({ _id: `${sessionId}-${key}` }));
|
|
88
88
|
return JSON.parse(data, BufferJSON.reviver);
|
|
89
89
|
} catch (err) {
|
|
90
|
-
|
|
90
|
+
logger.error(err);
|
|
91
91
|
return null;
|
|
92
92
|
}
|
|
93
93
|
};
|
|
@@ -96,7 +96,7 @@ async function useMongoDBAuthState(uri, dbName, sessionId) {
|
|
|
96
96
|
try {
|
|
97
97
|
await collection.deleteOne({ _id: `${sessionId}-${key}` });
|
|
98
98
|
} catch (err) {
|
|
99
|
-
|
|
99
|
+
logger.error(err);
|
|
100
100
|
}
|
|
101
101
|
};
|
|
102
102
|
|
|
@@ -6,6 +6,7 @@ const { getRecordByFilter } = require('../services/airtableService');
|
|
|
6
6
|
const { createAssistant, addMsgAssistant, addInsAssistant } = require('../services/assistantService');
|
|
7
7
|
const { getThreadInfo, switchAssistant } = require('../services/assistantService');
|
|
8
8
|
const { sendMessage } = require('../core/NexusMessaging');
|
|
9
|
+
const { logger } = require('../utils/logger');
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
const activeAssistantController = async (req, res) => {
|
|
@@ -15,7 +16,7 @@ const activeAssistantController = async (req, res) => {
|
|
|
15
16
|
await Thread.updateOne({ code }, { $set: { active: !!active } });
|
|
16
17
|
return res.status(200).send({ message: 'Active assistant' });
|
|
17
18
|
} catch (error) {
|
|
18
|
-
|
|
19
|
+
logger.error(error);
|
|
19
20
|
return res.status(500).send({ message: 'Failed to active assistant', error });
|
|
20
21
|
}
|
|
21
22
|
};
|
|
@@ -31,7 +32,7 @@ const addInsAssistantController = async (req, res) => {
|
|
|
31
32
|
if (ans) await sendMessage({code, body: ans, fileType: 'text'});
|
|
32
33
|
return res.status(200).send({ message: 'Add instruction to the assistant' });
|
|
33
34
|
} catch (error) {
|
|
34
|
-
|
|
35
|
+
logger.error(error);
|
|
35
36
|
res.status(500).send({ message: 'Failed to add instruction to assistant', error });
|
|
36
37
|
}
|
|
37
38
|
};
|
|
@@ -44,7 +45,7 @@ const addMsgAssistantController = async (req, res) => {
|
|
|
44
45
|
if (ans) await sendMessage({code, body: ans, fileType: 'text'});
|
|
45
46
|
return res.status(200).send({ message: 'Add message to the assistant' });
|
|
46
47
|
} catch (error) {
|
|
47
|
-
|
|
48
|
+
logger.error(error);
|
|
48
49
|
res.status(500).send({ message: 'Failed to add message assistant', error });
|
|
49
50
|
}
|
|
50
51
|
};
|
|
@@ -58,18 +59,18 @@ const createAssistantController = async (req, res) => {
|
|
|
58
59
|
messages = Array.isArray(messages) ? messages : [];
|
|
59
60
|
|
|
60
61
|
try {
|
|
61
|
-
|
|
62
|
+
logger.info('[createAssistantController] codes', codes);
|
|
62
63
|
for (const code of codes) {
|
|
63
64
|
await createAssistant(code, assistant_id, [...instrucciones, ...messages], force);
|
|
64
|
-
|
|
65
|
+
logger.info('[createAssistantController] messages', messages);
|
|
65
66
|
for (const message of messages) {
|
|
66
|
-
|
|
67
|
+
logger.info('[createAssistantController] message', message);
|
|
67
68
|
await sendMessage({code, body: message, fileType: 'text'});
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
res.status(200).send({ message: 'Create the assistant' });
|
|
71
72
|
} catch (error) {
|
|
72
|
-
|
|
73
|
+
logger.error(error);
|
|
73
74
|
res.status(500).send({ message: 'Failed to create assistant', error });
|
|
74
75
|
}
|
|
75
76
|
};
|
|
@@ -81,7 +82,7 @@ const getInfoAssistantController = async (req, res) => {
|
|
|
81
82
|
let threadInfo = await getThreadInfo(code);
|
|
82
83
|
return res.status(200).send({ message: 'Send assistant info' , threadInfo});
|
|
83
84
|
} catch (error) {
|
|
84
|
-
|
|
85
|
+
logger.error(error);
|
|
85
86
|
res.status(500).send({ message: 'Failed to receive assistant info', error });
|
|
86
87
|
}
|
|
87
88
|
};
|
|
@@ -96,7 +97,7 @@ const listAssistantController = async (req, res) => {
|
|
|
96
97
|
const assistants = await getRecordByFilter(Config_ID, tableName, `status="${airtableStatus}"`);
|
|
97
98
|
return res.status(200).send({ message: 'List assistants' , assistants});
|
|
98
99
|
} catch (error) {
|
|
99
|
-
|
|
100
|
+
logger.error(error);
|
|
100
101
|
res.status(500).send({ message: 'Failed to list assistants', error });
|
|
101
102
|
}
|
|
102
103
|
};
|
|
@@ -108,7 +109,7 @@ const switchAssistantController = async (req, res) => {
|
|
|
108
109
|
await switchAssistant(code, assistant_id);
|
|
109
110
|
return res.status(200).send({ message: 'Switch assistant' });
|
|
110
111
|
} catch (error) {
|
|
111
|
-
|
|
112
|
+
logger.error(error);
|
|
112
113
|
res.status(500).send({ message: 'Failed to switch assistant', error });
|
|
113
114
|
}
|
|
114
115
|
};
|
|
@@ -120,7 +121,7 @@ const stopAssistantController = async (req, res) => {
|
|
|
120
121
|
await Thread.updateOne({ code }, { $set: { stopped: !!stop } });
|
|
121
122
|
return res.status(200).send({ message: 'Stop assistant' });
|
|
122
123
|
} catch (error) {
|
|
123
|
-
|
|
124
|
+
logger.error(error);
|
|
124
125
|
return res.status(500).send({ message: 'Failed to stop assistant', error });
|
|
125
126
|
}
|
|
126
127
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { Message } = require('../models/messageModel');
|
|
2
2
|
const { addRecord, getRecordByFilter } = require('../services/airtableService');
|
|
3
3
|
const { Logging_ID } = require('../config/airtableConfig');
|
|
4
|
+
const { logger } = require('../utils/logger');
|
|
4
5
|
|
|
5
6
|
async function logBugReportToAirtable(reporter, whatsapp_id, description, severity, messageIds = []) {
|
|
6
7
|
try {
|
|
@@ -21,7 +22,7 @@ async function logBugReportToAirtable(reporter, whatsapp_id, description, severi
|
|
|
21
22
|
patientId = patientRecords[0].record_logging_id;
|
|
22
23
|
}
|
|
23
24
|
} catch (err) {
|
|
24
|
-
|
|
25
|
+
logger.warn('Could not find patient in estado_general:', err.message);
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
const airtableData = {
|
|
@@ -33,9 +34,9 @@ async function logBugReportToAirtable(reporter, whatsapp_id, description, severi
|
|
|
33
34
|
};
|
|
34
35
|
|
|
35
36
|
await addRecord(Logging_ID, 'bug_reports', airtableData);
|
|
36
|
-
|
|
37
|
+
logger.info('Bug report logged to Airtable successfully');
|
|
37
38
|
} catch (error) {
|
|
38
|
-
|
|
39
|
+
logger.error('Error logging bug report to Airtable:', error);
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
|
|
@@ -50,12 +51,12 @@ const reportBugController = async (req, res) => {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
logBugReportToAirtable(reporter, whatsapp_id, description, severity, messages).catch(err =>
|
|
53
|
-
|
|
54
|
+
logger.error('Background bug report logging failed:', err)
|
|
54
55
|
);
|
|
55
56
|
|
|
56
57
|
res.status(201).json({ success: true, message: 'Bug report submitted successfully' });
|
|
57
58
|
} catch (error) {
|
|
58
|
-
|
|
59
|
+
logger.error('Error submitting bug report:', error);
|
|
59
60
|
res.status(500).json({ success: false, error: error.message });
|
|
60
61
|
}
|
|
61
62
|
};
|