@peopl-health/nexus 2.0.15 → 2.0.17

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.
@@ -6,8 +6,16 @@ const app = express();
6
6
  app.use(express.json());
7
7
 
8
8
  async function startServer() {
9
- // Initialize Nexus with all services
10
- const nexus = new Nexus();
9
+ // Initialize Nexus with all services and batching enabled
10
+ const nexus = new Nexus({
11
+ messaging: {
12
+ messageBatching: {
13
+ enabled: true,
14
+ baseWaitTime: 10000, // 10 seconds base wait (shorter for testing)
15
+ randomVariation: 5000 // 0-5 seconds random variation
16
+ }
17
+ }
18
+ });
11
19
 
12
20
  await nexus.initialize({
13
21
  // MongoDB connection
@@ -34,6 +42,7 @@ async function startServer() {
34
42
  // Add webhook endpoint for incoming messages
35
43
  app.post('/webhook', async (req, res) => {
36
44
  try {
45
+ console.log('📨 Received webhook:', JSON.stringify(req.body, null, 2));
37
46
  await nexus.processMessage(req.body);
38
47
  res.status(200).send('OK');
39
48
  } catch (error) {
@@ -73,11 +82,17 @@ async function startServer() {
73
82
  console.log(`Server running on port ${PORT}`);
74
83
  console.log('Available endpoints:');
75
84
  console.log('- POST /webhook - Webhook for incoming messages');
85
+ console.log('- POST /twilio/webhook - Twilio webhook for incoming messages');
76
86
  console.log('- GET /status - Connection status');
77
87
  console.log('- GET /airtable-test - Test Airtable connection');
78
88
  console.log('- GET /media-test - Test AWS media upload configuration');
79
89
  console.log('- All Nexus API routes under /api/*');
80
90
  console.log('');
91
+ console.log('🔄 Message Batching:');
92
+ console.log(' - Batching is ENABLED with 10-15 second wait times');
93
+ console.log(' - Multiple messages from same sender will be batched');
94
+ console.log(' - Use test-batching.js to test the functionality');
95
+ console.log('');
81
96
  console.log('📸 Media Upload Setup:');
82
97
  console.log(' Add these to your .env file for media upload:');
83
98
  console.log(' - AWS_ACCESS_KEY_ID=your_access_key');
@@ -325,11 +325,12 @@ class BaseAssistant {
325
325
 
326
326
  async close() {
327
327
  this.status = 'closed';
328
- if (this.thread?.code && this.thread?.assistant_id) {
329
- await Thread.updateOne(
330
- { code: this.thread.code, assistant_id: this.thread.assistant_id },
331
- { $set: { active: false } }
332
- );
328
+ const assistantId = process.env.VARIANT === 'responses' ? this.thread?.prompt_id : this.thread?.assistant_id;
329
+ if (this.thread?.code && assistantId) {
330
+ const filter = process.env.VARIANT === 'responses'
331
+ ? { code: this.thread.code, prompt_id: assistantId }
332
+ : { code: this.thread.code, assistant_id: assistantId };
333
+ await Thread.updateOne(filter, { $set: { active: false } });
333
334
  }
334
335
 
335
336
  if (this.assistantId) {
@@ -47,18 +47,20 @@ const addMsgAssistantController = async (req, res) => {
47
47
  };
48
48
 
49
49
  const createAssistantController = async (req, res) => {
50
- const { assistant_id, codes, instrucciones=[], messages=[], force=false } = req.body;
50
+ let { assistant_id, codes, instrucciones=[], messages=[], force=false } = req.body;
51
51
  if (!Array.isArray(codes) || codes.length === 0) {
52
52
  return res.status(400).send({ error: 'codes must be a non-empty array' });
53
53
  }
54
+ instrucciones = Array.isArray(instrucciones) ? instrucciones : [];
55
+ messages = Array.isArray(messages) ? messages : [];
54
56
 
55
57
  try {
56
- console.log('codes', codes);
58
+ console.log('[createAssistantController] codes', codes);
57
59
  for (const code of codes) {
58
60
  await createAssistant(code, assistant_id, [...instrucciones, ...messages], force);
59
- console.log('messages', messages);
61
+ console.log('[createAssistantController] messages', messages);
60
62
  for (const message of messages) {
61
- console.log('message', message);
63
+ console.log('[createAssistantController] message', message);
62
64
  await sendMessage({code, body: message, fileType: 'text'});
63
65
  }
64
66
  }
@@ -303,9 +303,10 @@ async function processIndividualMessage(code, reply, provider, thread) {
303
303
  console.log(`[processIndividualMessage] User message added to thread ${threadId}`);
304
304
  }
305
305
 
306
+ const assistantId = process.env.VARIANT === 'responses' ? thread.prompt_id : thread.assistant_id;
306
307
  await Message.updateOne(
307
308
  { message_id: reply.message_id, timestamp: reply.timestamp },
308
- { $set: { assistant_id: thread.assistant_id, thread_id: threadId } }
309
+ { $set: { assistant_id: assistantId, thread_id: threadId } }
309
310
  );
310
311
 
311
312
  return {isNotAssistant, url};
@@ -194,13 +194,23 @@ const createAssistant = async (code, assistant_id, messages=[], force=false) =>
194
194
  // If thread already exists, update it
195
195
  const findThread = await Thread.findOne({ code: code });
196
196
  const variant = process.env.VARIANT || 'assistants';
197
+ console.log('[createAssistant] findThread', findThread);
197
198
  if ((findThread?.conversation_id && variant === 'responses') || (findThread?.thread_id && variant === 'assistants')) {
198
- await Thread.updateOne({ code: code }, { $set: { active: true, stopped: false, assistant_id: assistant_id } });
199
+ console.log('[createAssistant] Thread already exists');
200
+ const updateFields = { active: true, stopped: false };
201
+
202
+ if (variant === 'responses') {
203
+ updateFields.prompt_id = assistant_id;
204
+ } else {
205
+ updateFields.assistant_id = assistant_id;
206
+ }
207
+
208
+ await Thread.updateOne({ code: code }, { $set: updateFields });
199
209
  return findThread;
200
210
  }
201
211
 
202
212
  const curRow = await getCurRow(Historial_Clinico_ID, code);
203
- console.log('curRow', curRow[0]);
213
+ console.log('[createAssistant] curRow', curRow[0]);
204
214
  const nombre = curRow?.[0]?.['name'] || null;
205
215
  const patientId = curRow?.[0]?.['record_id'] || null;
206
216
 
@@ -217,7 +227,7 @@ const createAssistant = async (code, assistant_id, messages=[], force=false) =>
217
227
  });
218
228
  }
219
229
 
220
- console.log('initialThread', initialThread);
230
+ console.log('[createAssistant] initialThread', initialThread);
221
231
  // Define new thread data
222
232
  const thread = {
223
233
  code: code,
@@ -233,11 +243,12 @@ const createAssistant = async (code, assistant_id, messages=[], force=false) =>
233
243
  const updateData = Object.fromEntries(
234
244
  Object.entries(thread).filter(([_, v]) => v != null)
235
245
  );
246
+ console.log('[createAssistant] updateData', updateData);
236
247
 
237
- const condition = { $or: [{ thread_id: findThread?.thread_id }, { conversation_id: findThread?.conversation_id }] };
248
+ const condition = { $or: [{ code: code }] };
238
249
  const options = { new: true, upsert: true };
239
250
  const updatedThread = await Thread.findOneAndUpdate(condition, {run_id: null, ...updateData}, options);
240
- console.log('Updated thread:', updatedThread);
251
+ console.log('[createAssistant] Updated thread:', updatedThread);
241
252
 
242
253
  // Delete previous thread
243
254
  if (force) {
@@ -451,7 +462,16 @@ const switchAssistant = async (code, assistant_id) => {
451
462
  console.log('Inside thread', thread);
452
463
  if (thread === null) return;
453
464
 
454
- await Thread.updateOne({ code }, { $set: { assistant_id: assistant_id, active: true, stopped: false } });
465
+ const variant = process.env.VARIANT || 'assistants';
466
+ const updateFields = { active: true, stopped: false };
467
+
468
+ if (variant === 'responses') {
469
+ updateFields.prompt_id = assistant_id;
470
+ } else {
471
+ updateFields.assistant_id = assistant_id;
472
+ }
473
+
474
+ await Thread.updateOne({ code }, { $set: updateFields });
455
475
  } catch (error) {
456
476
  console.log(error);
457
477
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peopl-health/nexus",
3
- "version": "2.0.15",
3
+ "version": "2.0.17",
4
4
  "description": "Core messaging and assistant library for WhatsApp communication platforms",
5
5
  "keywords": [
6
6
  "whatsapp",