@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
|
@@ -15,7 +15,7 @@ const { withTracing } = require('../utils/tracingDecorator.js');
|
|
|
15
15
|
const { processThreadMessage } = require('../helpers/processHelper.js');
|
|
16
16
|
const { getLastMessages, updateMessageRecord } = require('../helpers/messageHelper.js');
|
|
17
17
|
const { combineImagesToPDF, cleanupFiles } = require('../helpers/filesHelper.js');
|
|
18
|
-
const { logger } = require('../
|
|
18
|
+
const { logger } = require('../utils/logger');
|
|
19
19
|
|
|
20
20
|
const DEFAULT_MAX_RETRIES = parseInt(process.env.MAX_RETRIES || '30', 10);
|
|
21
21
|
|
|
@@ -136,9 +136,9 @@ const getAssistantById = (assistant_id, thread) => {
|
|
|
136
136
|
|
|
137
137
|
const createAssistant = async (code, assistant_id, messages=[], force=false) => {
|
|
138
138
|
const findThread = await Thread.findOne({ code: code });
|
|
139
|
-
|
|
139
|
+
logger.info('[createAssistant] findThread', findThread);
|
|
140
140
|
if (findThread && findThread.getConversationId()) {
|
|
141
|
-
|
|
141
|
+
logger.info('[createAssistant] Thread already exists');
|
|
142
142
|
const updateFields = { active: true, stopped: false };
|
|
143
143
|
Thread.setAssistantId(updateFields, assistant_id);
|
|
144
144
|
await Thread.updateOne({ code: code }, { $set: updateFields });
|
|
@@ -146,7 +146,7 @@ const createAssistant = async (code, assistant_id, messages=[], force=false) =>
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
const curRow = await getCurRow(Historial_Clinico_ID, code);
|
|
149
|
-
|
|
149
|
+
logger.info('[createAssistant] curRow', curRow[0]);
|
|
150
150
|
const nombre = curRow?.[0]?.['name'] || null;
|
|
151
151
|
const patientId = curRow?.[0]?.['record_id'] || null;
|
|
152
152
|
|
|
@@ -175,7 +175,7 @@ const createAssistant = async (code, assistant_id, messages=[], force=false) =>
|
|
|
175
175
|
const condition = { $or: [{ code: code }] };
|
|
176
176
|
const options = { new: true, upsert: true };
|
|
177
177
|
const updatedThread = await Thread.findOneAndUpdate(condition, {run_id: null, ...thread}, options);
|
|
178
|
-
|
|
178
|
+
logger.info('[createAssistant] Updated thread:', updatedThread);
|
|
179
179
|
|
|
180
180
|
// Delete previous thread
|
|
181
181
|
if (force) {
|
|
@@ -188,12 +188,12 @@ const createAssistant = async (code, assistant_id, messages=[], force=false) =>
|
|
|
188
188
|
const addMsgAssistant = async (code, inMessages, role = 'user', reply = false) => {
|
|
189
189
|
try {
|
|
190
190
|
const thread = await Thread.findOne({ code: code });
|
|
191
|
-
|
|
191
|
+
logger.info(thread);
|
|
192
192
|
if (thread === null) return null;
|
|
193
193
|
|
|
194
194
|
const provider = createProvider({ variant: process.env.VARIANT || 'assistants' });
|
|
195
195
|
for (const message of inMessages) {
|
|
196
|
-
|
|
196
|
+
logger.info(message);
|
|
197
197
|
await provider.addMessage({
|
|
198
198
|
threadId: thread.getConversationId(),
|
|
199
199
|
role: role,
|
|
@@ -209,17 +209,17 @@ const addMsgAssistant = async (code, inMessages, role = 'user', reply = false) =
|
|
|
209
209
|
const assistant = getAssistantById(thread.getAssistantId(), thread);
|
|
210
210
|
do {
|
|
211
211
|
({ output, completed } = await runAssistantAndWait({ thread, assistant }));
|
|
212
|
-
|
|
212
|
+
logger.info(`Attempt ${retries + 1}: completed=${completed}, output=${output || '(empty)'}`);
|
|
213
213
|
|
|
214
214
|
if (completed && output) break;
|
|
215
215
|
if (retries < maxRetries) await new Promise(resolve => setTimeout(resolve, 2000));
|
|
216
216
|
retries++;
|
|
217
217
|
} while (retries <= maxRetries && (!completed || !output));
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
logger.info('THE ANS IS', output);
|
|
220
220
|
return output;
|
|
221
221
|
} catch (error) {
|
|
222
|
-
|
|
222
|
+
logger.info(error);
|
|
223
223
|
return null;
|
|
224
224
|
}
|
|
225
225
|
};
|
|
@@ -254,7 +254,7 @@ const addInstructionCore = async (code, instruction, role = 'user') => {
|
|
|
254
254
|
null // no patientReply for instructions
|
|
255
255
|
);
|
|
256
256
|
|
|
257
|
-
|
|
257
|
+
logger.info('RUN RESPONSE', output);
|
|
258
258
|
return output;
|
|
259
259
|
};
|
|
260
260
|
|
|
@@ -290,14 +290,14 @@ const replyAssistantCore = async (code, message_ = null, thread_ = null, runOpti
|
|
|
290
290
|
timings.getMessages = Date.now() - timings.getMessages;
|
|
291
291
|
|
|
292
292
|
if (!patientReply) {
|
|
293
|
-
logger.
|
|
293
|
+
logger.info('[replyAssistantCore] No relevant data found for this assistant.');
|
|
294
294
|
return null;
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
const provider = createProvider({ variant: process.env.VARIANT || 'assistants' });
|
|
298
298
|
|
|
299
299
|
timings.processMessages = Date.now();
|
|
300
|
-
logger.
|
|
300
|
+
logger.info(`[replyAssistantCore] Processing ${patientReply.length} messages in parallel`);
|
|
301
301
|
|
|
302
302
|
const processResults = await processThreadMessage(code, patientReply, provider);
|
|
303
303
|
|
|
@@ -308,7 +308,7 @@ const replyAssistantCore = async (code, message_ = null, thread_ = null, runOpti
|
|
|
308
308
|
|
|
309
309
|
if (allMessagesToAdd.length > 0) {
|
|
310
310
|
const threadId = thread.getConversationId();
|
|
311
|
-
logger.
|
|
311
|
+
logger.info(`[replyAssistantCore] Adding ${allMessagesToAdd.length} messages to thread in batch`);
|
|
312
312
|
await provider.addMessage({ threadId, messages: allMessagesToAdd });
|
|
313
313
|
}
|
|
314
314
|
|
|
@@ -319,10 +319,10 @@ const replyAssistantCore = async (code, message_ = null, thread_ = null, runOpti
|
|
|
319
319
|
|
|
320
320
|
if (urls.length > 0) {
|
|
321
321
|
timings.pdfCombination = Date.now();
|
|
322
|
-
logger.
|
|
322
|
+
logger.info(`[replyAssistantCore] Processing ${urls.length} URLs for PDF combination`);
|
|
323
323
|
const { pdfBuffer, processedFiles } = await combineImagesToPDF({ code });
|
|
324
324
|
timings.pdfCombination = Date.now() - timings.pdfCombination;
|
|
325
|
-
logger.
|
|
325
|
+
logger.info(`[replyAssistantCore] PDF combination complete: ${processedFiles?.length || 0} files processed`);
|
|
326
326
|
|
|
327
327
|
if (pdfBuffer) {
|
|
328
328
|
const key = `${code}-${Date.now()}-combined.pdf`;
|
|
@@ -353,7 +353,7 @@ const replyAssistantCore = async (code, message_ = null, thread_ = null, runOpti
|
|
|
353
353
|
timings.runAssistant = Date.now() - timings.runAssistant;
|
|
354
354
|
timings.total = Date.now() - startTotal;
|
|
355
355
|
|
|
356
|
-
logger.
|
|
356
|
+
logger.info('[Performance Breakdown]', {
|
|
357
357
|
code: code ? `${code.substring(0, 3)}***${code.slice(-4)}` : 'unknown',
|
|
358
358
|
messageCount: patientReply.length,
|
|
359
359
|
hasMedia: urls.length > 0,
|
|
@@ -378,7 +378,7 @@ const replyAssistantCore = async (code, message_ = null, thread_ = null, runOpti
|
|
|
378
378
|
run_assistant_ms: timings.runAssistant,
|
|
379
379
|
total_ms: timings.total
|
|
380
380
|
}
|
|
381
|
-
}).catch(err =>
|
|
381
|
+
}).catch(err => logger.error('[replyAssistantCore] Failed to store metrics:', err));
|
|
382
382
|
}
|
|
383
383
|
|
|
384
384
|
return output;
|
|
@@ -398,7 +398,7 @@ const replyAssistant = withTracing(
|
|
|
398
398
|
const switchAssistant = async (code, assistant_id) => {
|
|
399
399
|
try {
|
|
400
400
|
const thread = await Thread.findOne({ code: code });
|
|
401
|
-
|
|
401
|
+
logger.info('Inside thread', thread);
|
|
402
402
|
if (thread === null) return;
|
|
403
403
|
|
|
404
404
|
const variant = process.env.VARIANT || 'assistants';
|
|
@@ -412,7 +412,7 @@ const switchAssistant = async (code, assistant_id) => {
|
|
|
412
412
|
|
|
413
413
|
await Thread.updateOne({ code }, { $set: updateFields });
|
|
414
414
|
} catch (error) {
|
|
415
|
-
|
|
415
|
+
logger.info(error);
|
|
416
416
|
return null;
|
|
417
417
|
}
|
|
418
418
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { Message } = require('../models/messageModel');
|
|
2
2
|
const { Historial_Clinico_ID } = require('../config/airtableConfig');
|
|
3
3
|
const { getRecordByFilter } = require('./airtableService');
|
|
4
|
+
const { logger } = require('../utils/logger');
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
const fetchConversationData = async (filter, skip, limit) => {
|
|
@@ -16,11 +17,11 @@ const fetchConversationData = async (filter, skip, limit) => {
|
|
|
16
17
|
{ read: { $exists: false } }
|
|
17
18
|
]
|
|
18
19
|
};
|
|
19
|
-
|
|
20
|
+
logger.info('Applying unread filter');
|
|
20
21
|
break;
|
|
21
22
|
|
|
22
23
|
case 'no-response':
|
|
23
|
-
|
|
24
|
+
logger.info('Applying no-response filter');
|
|
24
25
|
break;
|
|
25
26
|
|
|
26
27
|
case 'recent': {
|
|
@@ -30,18 +31,18 @@ const fetchConversationData = async (filter, skip, limit) => {
|
|
|
30
31
|
is_group: false,
|
|
31
32
|
createdAt: { $gt: yesterday }
|
|
32
33
|
};
|
|
33
|
-
|
|
34
|
+
logger.info('Applying recent filter (last 24 hours)');
|
|
34
35
|
break;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
case 'all':
|
|
38
39
|
default:
|
|
39
40
|
filterConditions = { is_group: false };
|
|
40
|
-
|
|
41
|
+
logger.info('Applying all conversations filter');
|
|
41
42
|
break;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
logger.info('Executing aggregation pipeline...');
|
|
45
46
|
const aggregationStartTime = Date.now();
|
|
46
47
|
|
|
47
48
|
let aggregationPipeline = [
|
|
@@ -77,7 +78,7 @@ const fetchConversationData = async (filter, skip, limit) => {
|
|
|
77
78
|
const conversations = await Message.aggregate(aggregationPipeline);
|
|
78
79
|
|
|
79
80
|
const aggregationTime = Date.now() - aggregationStartTime;
|
|
80
|
-
|
|
81
|
+
logger.info(`Aggregation completed in ${aggregationTime}ms, found ${conversations.length} conversations`);
|
|
81
82
|
|
|
82
83
|
// Fetch names from Airtable and WhatsApp
|
|
83
84
|
const phoneNumbers = conversations.map(conv => conv._id).filter(Boolean);
|
|
@@ -89,7 +90,7 @@ const fetchConversationData = async (filter, skip, limit) => {
|
|
|
89
90
|
map[patient.whatsapp_id] = patient.name;
|
|
90
91
|
return map;
|
|
91
92
|
}, {});
|
|
92
|
-
|
|
93
|
+
logger.info(`Found ${Object.keys(airtableNameMap).length} names in Airtable`);
|
|
93
94
|
|
|
94
95
|
const contactNames = await Message.aggregate([
|
|
95
96
|
{ $match: { is_group: false, from_me: false } },
|
|
@@ -110,7 +111,7 @@ const fetchConversationData = async (filter, skip, limit) => {
|
|
|
110
111
|
}, {...airtableNameMap}) || airtableNameMap || {};
|
|
111
112
|
|
|
112
113
|
// Fetch unread counts
|
|
113
|
-
|
|
114
|
+
logger.info('Fetching unread counts using Message.aggregate');
|
|
114
115
|
const unreadCounts = await Message.aggregate([
|
|
115
116
|
{
|
|
116
117
|
$match: {
|
|
@@ -134,8 +135,8 @@ const fetchConversationData = async (filter, skip, limit) => {
|
|
|
134
135
|
}
|
|
135
136
|
return map;
|
|
136
137
|
}, {}) || {};
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
logger.info('unreadMap', JSON.stringify(unreadMap));
|
|
139
|
+
logger.info('Number of conversations found:', conversations?.length || 0);
|
|
139
140
|
|
|
140
141
|
// Calculate total count for pagination
|
|
141
142
|
let totalFilterConditions = { is_group: false };
|
|
@@ -193,14 +194,14 @@ const fetchConversationData = async (filter, skip, limit) => {
|
|
|
193
194
|
* Processes conversations to prepare them for the response
|
|
194
195
|
*/
|
|
195
196
|
const processConversations = async (conversations, nameMap, unreadMap) => {
|
|
196
|
-
|
|
197
|
+
logger.info('Processing conversations for response...');
|
|
197
198
|
|
|
198
199
|
let processedConversations = [];
|
|
199
200
|
try {
|
|
200
201
|
processedConversations = (conversations || []).map((conv, index) => {
|
|
201
202
|
try {
|
|
202
203
|
if (!conv || !conv.latestMessage) {
|
|
203
|
-
|
|
204
|
+
logger.warn(`Conversation ${index} missing latestMessage:`, conv?._id || 'unknown');
|
|
204
205
|
return {
|
|
205
206
|
phoneNumber: conv?._id || 'unknown',
|
|
206
207
|
name: 'Unknown',
|
|
@@ -245,7 +246,7 @@ const processConversations = async (conversations, nameMap, unreadMap) => {
|
|
|
245
246
|
lastMessageFromMe: conv?.latestMessage?.from_me || false
|
|
246
247
|
};
|
|
247
248
|
} catch (convError) {
|
|
248
|
-
|
|
249
|
+
logger.error(`Error processing conversation ${index}:`, convError);
|
|
249
250
|
return {
|
|
250
251
|
phoneNumber: conv?._id || `error_${index}`,
|
|
251
252
|
name: 'Error Processing',
|
|
@@ -260,11 +261,10 @@ const processConversations = async (conversations, nameMap, unreadMap) => {
|
|
|
260
261
|
}
|
|
261
262
|
});
|
|
262
263
|
|
|
263
|
-
|
|
264
|
+
logger.info(`Successfully processed ${processedConversations.length} conversations`);
|
|
264
265
|
|
|
265
266
|
} catch (mappingError) {
|
|
266
|
-
|
|
267
|
-
// Return empty conversations if mapping fails
|
|
267
|
+
logger.error('Error in conversation mapping:', mappingError);
|
|
268
268
|
processedConversations = [];
|
|
269
269
|
}
|
|
270
270
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const { logger } = require('../utils/logger');
|
|
2
|
+
|
|
1
3
|
let preprocessingHandler = null;
|
|
2
4
|
|
|
3
5
|
const setPreprocessingHandler = (handler) => {
|
|
@@ -16,7 +18,7 @@ const invokePreprocessingHandler = async (payload) => {
|
|
|
16
18
|
const result = await preprocessingHandler(payload);
|
|
17
19
|
return Boolean(result);
|
|
18
20
|
} catch (error) {
|
|
19
|
-
|
|
21
|
+
logger.warn('[PreprocessingHooks] Handler threw an error:', error?.message || error);
|
|
20
22
|
return false;
|
|
21
23
|
}
|
|
22
24
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const mongoose = require('mongoose');
|
|
2
2
|
const runtimeConfig = require('../config/runtimeConfig');
|
|
3
|
+
const { logger } = require('../utils/logger');
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* MongoDB storage interface for messages and interactions
|
|
@@ -34,7 +35,7 @@ class MongoStorage {
|
|
|
34
35
|
useNewUrlParser: true,
|
|
35
36
|
useUnifiedTopology: true
|
|
36
37
|
});
|
|
37
|
-
|
|
38
|
+
logger.info('MongoDB connected successfully');
|
|
38
39
|
} catch (error) {
|
|
39
40
|
throw new Error(`MongoDB connection failed: ${error.message}`);
|
|
40
41
|
}
|
|
@@ -46,10 +47,10 @@ class MongoStorage {
|
|
|
46
47
|
const values = this.buildMessageValues(enrichedMessage);
|
|
47
48
|
const { insertMessage } = require('../models/messageModel');
|
|
48
49
|
await insertMessage(values);
|
|
49
|
-
|
|
50
|
+
logger.info('[MongoStorage] Message stored');
|
|
50
51
|
return values;
|
|
51
52
|
} catch (error) {
|
|
52
|
-
|
|
53
|
+
logger.error('Error saving message:', error);
|
|
53
54
|
throw error;
|
|
54
55
|
}
|
|
55
56
|
}
|
|
@@ -64,23 +65,22 @@ class MongoStorage {
|
|
|
64
65
|
return messageData;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
logger.info('[MongoStorage] Detected Twilio media message', {
|
|
68
69
|
from: rawMessage.From,
|
|
69
70
|
numMedia
|
|
70
71
|
});
|
|
71
72
|
|
|
72
73
|
const bucketName = runtimeConfig.get('AWS_S3_BUCKET_NAME') || process.env.AWS_S3_BUCKET_NAME;
|
|
73
74
|
if (!bucketName) {
|
|
74
|
-
|
|
75
|
+
logger.warn('[MongoStorage] AWS_S3_BUCKET_NAME not configured. Skipping media upload.');
|
|
75
76
|
return messageData;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
const { processTwilioMediaMessage } = require('../helpers/twilioMediaProcessor');
|
|
79
|
-
const { logger } = require('../utils/logger');
|
|
80
80
|
|
|
81
|
-
const mediaItems = await processTwilioMediaMessage(rawMessage,
|
|
81
|
+
const mediaItems = await processTwilioMediaMessage(rawMessage, bucketName);
|
|
82
82
|
if (!mediaItems || mediaItems.length === 0) {
|
|
83
|
-
|
|
83
|
+
logger.warn('[MongoStorage] Media processing returned no items');
|
|
84
84
|
return messageData;
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -91,7 +91,7 @@ class MongoStorage {
|
|
|
91
91
|
|
|
92
92
|
rawMessage.__nexusMediaProcessed = true;
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
logger.info('[MongoStorage] Media processed successfully', {
|
|
95
95
|
primaryType: mediaPayload.mediaType,
|
|
96
96
|
mediaCount: mediaItems.length,
|
|
97
97
|
s3Key: mediaPayload.key
|
|
@@ -107,7 +107,7 @@ class MongoStorage {
|
|
|
107
107
|
caption: primary.caption || messageData.caption
|
|
108
108
|
};
|
|
109
109
|
} catch (error) {
|
|
110
|
-
|
|
110
|
+
logger.error('[MongoStorage] Failed to enrich Twilio media message:', error);
|
|
111
111
|
return messageData;
|
|
112
112
|
}
|
|
113
113
|
}
|
|
@@ -197,7 +197,7 @@ class MongoStorage {
|
|
|
197
197
|
.sort({ createdAt: -1 })
|
|
198
198
|
.limit(limit);
|
|
199
199
|
} catch (error) {
|
|
200
|
-
|
|
200
|
+
logger.error('Error getting messages:', error);
|
|
201
201
|
throw error;
|
|
202
202
|
}
|
|
203
203
|
}
|
|
@@ -206,7 +206,7 @@ class MongoStorage {
|
|
|
206
206
|
try {
|
|
207
207
|
return await this.schemas.Thread.findOne({ code, active: true });
|
|
208
208
|
} catch (error) {
|
|
209
|
-
|
|
209
|
+
logger.error('Error getting thread:', error);
|
|
210
210
|
throw error;
|
|
211
211
|
}
|
|
212
212
|
}
|
|
@@ -217,7 +217,7 @@ class MongoStorage {
|
|
|
217
217
|
await thread.save();
|
|
218
218
|
return thread;
|
|
219
219
|
} catch (error) {
|
|
220
|
-
|
|
220
|
+
logger.error('Error creating thread:', error);
|
|
221
221
|
throw error;
|
|
222
222
|
}
|
|
223
223
|
}
|
|
@@ -230,7 +230,7 @@ class MongoStorage {
|
|
|
230
230
|
{ new: true }
|
|
231
231
|
);
|
|
232
232
|
} catch (error) {
|
|
233
|
-
|
|
233
|
+
logger.error('Error updating thread:', error);
|
|
234
234
|
throw error;
|
|
235
235
|
}
|
|
236
236
|
}
|
package/lib/utils/logger.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const pino = require('pino');
|
|
2
|
-
const { trace
|
|
2
|
+
const { trace } = require('@opentelemetry/api');
|
|
3
3
|
|
|
4
4
|
const createLogger = (config = {}) => {
|
|
5
5
|
const {
|
|
@@ -98,12 +98,44 @@ const createObservabilityLogger = (serviceName = 'nexus-assistant', config = {})
|
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
// Default logger instances
|
|
101
|
-
const
|
|
101
|
+
const baseLogger = createLogger();
|
|
102
102
|
const observabilityLogger = createObservabilityLogger();
|
|
103
103
|
|
|
104
|
+
let getRequestId = () => null;
|
|
105
|
+
|
|
106
|
+
function setRequestIdGetter(getter) {
|
|
107
|
+
getRequestId = getter;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const logger = {
|
|
111
|
+
info: (message, meta = {}) => {
|
|
112
|
+
const requestId = getRequestId();
|
|
113
|
+
baseLogger.info(requestId ? { requestId, ...meta } : meta, message);
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
error: (message, meta = {}) => {
|
|
117
|
+
const requestId = getRequestId();
|
|
118
|
+
baseLogger.error(requestId ? { requestId, ...meta } : meta, message);
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
warn: (message, meta = {}) => {
|
|
122
|
+
const requestId = getRequestId();
|
|
123
|
+
baseLogger.warn(requestId ? { requestId, ...meta } : meta, message);
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
debug: (message, meta = {}) => {
|
|
127
|
+
const requestId = getRequestId();
|
|
128
|
+
baseLogger.debug(requestId ? { requestId, ...meta } : meta, message);
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
child: (bindings) => baseLogger.child(bindings),
|
|
132
|
+
level: baseLogger.level
|
|
133
|
+
};
|
|
134
|
+
|
|
104
135
|
module.exports = {
|
|
105
136
|
logger,
|
|
106
137
|
createLogger,
|
|
107
138
|
observabilityLogger,
|
|
108
|
-
createObservabilityLogger
|
|
139
|
+
createObservabilityLogger,
|
|
140
|
+
setRequestIdGetter
|
|
109
141
|
};
|
package/lib/utils/sanitizer.js
CHANGED
|
@@ -39,8 +39,6 @@ function sanitizeLogMetadata(metadata) {
|
|
|
39
39
|
delete safe.text;
|
|
40
40
|
delete safe.content;
|
|
41
41
|
delete safe.body;
|
|
42
|
-
delete safe.phone;
|
|
43
|
-
delete safe.numero;
|
|
44
42
|
|
|
45
43
|
if (safe.message_id) {
|
|
46
44
|
safe.message_id = safe.message_id.length > 8
|
|
@@ -48,10 +46,6 @@ function sanitizeLogMetadata(metadata) {
|
|
|
48
46
|
: '***';
|
|
49
47
|
}
|
|
50
48
|
|
|
51
|
-
if (safe.code && safe.code.length > 8) {
|
|
52
|
-
safe.code = `${safe.code.substring(0, 3)}***${safe.code.slice(-4)}`;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
49
|
return safe;
|
|
56
50
|
}
|
|
57
51
|
|