@peopl-health/nexus 2.0.13 → 2.0.15

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.
@@ -61,10 +61,9 @@ class TwilioProvider extends MessageProvider {
61
61
 
62
62
  // Handle template messages
63
63
  if (contentSid) {
64
- // Render template and add to messageData for storage
65
64
  const renderedMessage = await this.renderTemplate(contentSid, variables);
66
65
  if (renderedMessage) {
67
- messageData.body = renderedMessage; // Add rendered content for storage
66
+ messageData.body = renderedMessage;
68
67
  }
69
68
 
70
69
  messageParams.contentSid = contentSid;
@@ -320,7 +320,8 @@ class NexusMessaging {
320
320
  await this.messageStorage.saveMessage({
321
321
  ...messageData,
322
322
  timestamp: new Date(),
323
- fromMe: false
323
+ fromMe: false,
324
+ origin: 'patient'
324
325
  });
325
326
  }
326
327
 
@@ -16,7 +16,7 @@ const moment = require('moment-timezone');
16
16
  const mode = process.env.NODE_ENV || 'dev';
17
17
 
18
18
 
19
- async function checkRunStatus(assistant, thread_id, run_id, retryCount = 0, maxRetries = 100, actionHandled = false) {
19
+ async function checkRunStatus(assistant, thread_id, run_id, retryCount = 0, maxRetries = 10, actionHandled = false) {
20
20
  try {
21
21
  const provider = createProvider({ variant: process.env.VARIANT || 'assistants' });
22
22
  const run = await provider.getRun({ threadId: thread_id, runId: run_id });
@@ -295,13 +295,12 @@ async function processIndividualMessage(code, reply, provider, thread) {
295
295
  // ONLY add user messages to the thread
296
296
  const threadId = process.env.VARIANT === 'responses' ? thread?.conversation_id : thread?.thread_id;
297
297
  if (isNotAssistant) {
298
- console.log('Adding user message to thread', thread);
299
298
  await provider.addMessage({
300
299
  threadId,
301
300
  role: 'user',
302
301
  content: messagesChat
303
302
  });
304
- console.log('[processIndividualMessage] User message added to thread');
303
+ console.log(`[processIndividualMessage] User message added to thread ${threadId}`);
305
304
  }
306
305
 
307
306
  await Message.updateOne(
@@ -45,7 +45,7 @@ async function analyzeImage(imagePath) {
45
45
  // Descrciption of the image
46
46
  const imageDescription = 'Describe the image in detail.';
47
47
  const messageDescription = await anthropicClient.messages.create({
48
- model: 'claude-3-7-sonnet-20250219',
48
+ model: 'claude-sonnet-4-5',
49
49
  max_tokens: 1024,
50
50
  messages: [
51
51
  {
@@ -29,8 +29,8 @@ const messageSchema = new mongoose.Schema({
29
29
  from_me: { type: Boolean, default: false },
30
30
  origin: {
31
31
  type: String,
32
- enum: ['whatsapp', 'assistant', 'patient'],
33
- default: 'whatsapp' },
32
+ enum: ['whatsapp_platform', 'assistant', 'patient'],
33
+ default: 'whatsapp_platform' },
34
34
  media: {
35
35
  contentType: { type: String, default: null },
36
36
  bucketName: { type: String, default: null },
@@ -102,9 +102,10 @@ async function insertMessage(values) {
102
102
  media: values.media ? values.media : null,
103
103
  content_sid: values.content_sid || null,
104
104
  clinical_context: clinical_context,
105
+ origin: values.origin,
105
106
  raw: values.raw || null
106
107
  };
107
- console.log('Inserting message', messageData);
108
+ console.log('[MongoStorage] Inserting message', messageData);
108
109
 
109
110
  await Message.findOneAndUpdate(
110
111
  { message_id: values.message_id, body: values.body },
@@ -112,9 +113,9 @@ async function insertMessage(values) {
112
113
  { upsert: true, new: true }
113
114
  );
114
115
 
115
- console.log('Message inserted or updated successfully');
116
+ console.log('[MongoStorage] Message inserted or updated successfully');
116
117
  } catch (err) {
117
- console.error('Error inserting message:', err);
118
+ console.error('[MongoStorage] Error inserting message:', err);
118
119
  throw err;
119
120
  }
120
121
  }
@@ -166,7 +167,7 @@ async function getContactDisplayName(contactNumber) {
166
167
  return contactNumber;
167
168
  }
168
169
  } catch (error) {
169
- console.error(`Error fetching display name for ${contactNumber}:`, error);
170
+ console.error('[MongoStorage] Error fetching display name for ${contactNumber}:', error);
170
171
  return contactNumber;
171
172
  }
172
173
  }
@@ -265,10 +265,20 @@ const addMsgAssistant = async (code, inMessages, reply = false) => {
265
265
 
266
266
  if (!reply) return null;
267
267
 
268
+ let output, completed;
269
+ let retries = 0;
270
+ const maxRetries = 10;
268
271
  const assistant = getAssistantById(thread?.prompt_id || thread?.assistant_id, thread);
269
- const { output } = await runAssistantAndWait({ thread, assistant });
270
- console.log('THE ANS IS', output);
272
+ do {
273
+ ({ output, completed } = await runAssistantAndWait({ thread, assistant }));
274
+ console.log(`Attempt ${retries + 1}: completed=${completed}, output=${output || '(empty)'}`);
275
+
276
+ if (completed && output) break;
277
+ if (retries < maxRetries) await new Promise(resolve => setTimeout(resolve, 2000));
278
+ retries++;
279
+ } while (retries <= maxRetries && (!completed || !output));
271
280
 
281
+ console.log('THE ANS IS', output);
272
282
  return output;
273
283
  } catch (error) {
274
284
  console.log(error);
@@ -282,17 +292,27 @@ const addInsAssistant = async (code, instruction) => {
282
292
  console.log(thread);
283
293
  if (thread === null) return null;
284
294
 
295
+ let output, completed;
296
+ let retries = 0;
297
+ const maxRetries = 10;
285
298
  const assistant = getAssistantById(thread?.prompt_id || thread?.assistant_id, thread);
286
- const { output } = await runAssistantAndWait({
287
- thread,
288
- assistant,
289
- runConfig: {
290
- additionalInstructions: instruction,
291
- additionalMessages: [
292
- { role: 'user', content: instruction }
293
- ]
294
- }
295
- });
299
+ do {
300
+ ({ output, completed } = await runAssistantAndWait({
301
+ thread,
302
+ assistant,
303
+ runConfig: {
304
+ additionalInstructions: instruction,
305
+ additionalMessages: [
306
+ { role: 'user', content: instruction }
307
+ ]
308
+ }
309
+ }));
310
+ console.log(`Attempt ${retries + 1}: completed=${completed}, output=${output || '(empty)'}`);
311
+
312
+ if (completed && output) break;
313
+ if (retries < maxRetries) await new Promise(resolve => setTimeout(resolve, 2000));
314
+ retries++;
315
+ } while (retries <= maxRetries && (!completed || !output));
296
316
  console.log('RUN RESPONSE', output);
297
317
 
298
318
  return output;
@@ -399,11 +419,22 @@ const replyAssistant = async function (code, message_ = null, thread_ = null, ru
399
419
  const assistant = getAssistantById(process.env.VARIANT === 'responses' ? thread?.prompt_id : thread?.assistant_id, thread);
400
420
  assistant.setReplies(patientReply);
401
421
 
402
- const { run, output, completed } = await runAssistantAndWait({
403
- thread,
404
- assistant,
405
- runConfig: runOptions
406
- });
422
+ let run, output, completed;
423
+ let retries = 0;
424
+ const maxRetries = 10;
425
+ do {
426
+ ({ run, output, completed } = await runAssistantAndWait({
427
+ thread,
428
+ assistant,
429
+ runConfig: runOptions
430
+ }));
431
+ console.log(`Attempt ${retries + 1}: completed=${completed}, output=${output || '(empty)'}`);
432
+
433
+ if (completed && output) break;
434
+ if (retries < maxRetries) await new Promise(resolve => setTimeout(resolve, 2000));
435
+ retries++;
436
+ } while (retries <= maxRetries && (!completed || !output));
437
+
407
438
  console.log('RUN LAST ERROR:', run?.last_error);
408
439
  console.log('RUN STATUS', completed);
409
440
  console.log(output);
@@ -18,32 +18,13 @@ class MongoStorage {
18
18
 
19
19
  createSchemas() {
20
20
  const { Message } = require('../models/messageModel');
21
- const interactionSchema = new mongoose.Schema({
22
- messageId: String,
23
- numero: String,
24
- interactive_type: String, // 'button', 'list', 'flow'
25
- payload: mongoose.Schema.Types.Mixed,
26
- timestamp: String,
27
- createdAt: { type: Date, default: Date.now }
28
- });
29
-
30
- const threadSchema = new mongoose.Schema({
31
- code: String,
32
- assistantId: String,
33
- threadId: String,
34
- patientId: String,
35
- runId: String,
36
- nombre: String,
37
- active: { type: Boolean, default: true },
38
- stopped: { type: Boolean, default: false },
39
- nextSid: [String],
40
- createdAt: { type: Date, default: Date.now }
41
- });
21
+ const { Interaction } = require('../models/interactionModel');
22
+ const { Thread } = require('../models/threadModel');
42
23
 
43
24
  return {
44
25
  Message,
45
- Interaction: mongoose.models.Interaction || mongoose.model('Interaction', interactionSchema),
46
- Thread: mongoose.models.Thread || mongoose.model('Thread', threadSchema)
26
+ Interaction,
27
+ Thread
47
28
  };
48
29
  }
49
30
 
@@ -61,18 +42,12 @@ class MongoStorage {
61
42
 
62
43
  async saveMessage(messageData) {
63
44
  try {
64
- console.log('[MongoStorage] Saving message', messageData);
65
45
  const enrichedMessage = await this._enrichTwilioMedia(messageData);
66
46
  console.log('[MongoStorage] Enriched message', enrichedMessage);
67
47
  const values = this.buildMessageValues(enrichedMessage);
68
48
  const { insertMessage } = require('../models/messageModel');
69
49
  await insertMessage(values);
70
- console.log('[MongoStorage] Message stored', {
71
- messageId: values.message_id,
72
- numero: values.numero,
73
- isMedia: values.is_media,
74
- hasMediaPayload: Boolean(values.media)
75
- });
50
+ console.log('[MongoStorage] Message stored');
76
51
  return values;
77
52
  } catch (error) {
78
53
  console.error('Error saving message:', error);
@@ -172,6 +147,7 @@ class MongoStorage {
172
147
  const timestamp = now.toISOString();
173
148
  const nombre = messageData.nombre_whatsapp || messageData.author || messageData.fromName || runtimeConfig.get('USER_DB_MONGO') || process.env.USER_DB_MONGO || 'Nexus';
174
149
  const processed = messageData.processed || false;
150
+ const origin = messageData.origin || 'whatsapp_platform';
175
151
 
176
152
  // Use message body directly (template rendering is now handled by the provider)
177
153
  let textBody = messageData.body;
@@ -210,7 +186,8 @@ class MongoStorage {
210
186
  media,
211
187
  content_sid: messageData.contentSid || null,
212
188
  template_variables: messageData.variables ? JSON.stringify(messageData.variables) : null,
213
- raw: messageData.raw || null
189
+ raw: messageData.raw || null,
190
+ origin
214
191
  };
215
192
  }
216
193
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peopl-health/nexus",
3
- "version": "2.0.13",
3
+ "version": "2.0.15",
4
4
  "description": "Core messaging and assistant library for WhatsApp communication platforms",
5
5
  "keywords": [
6
6
  "whatsapp",