@peopl-health/nexus 4.4.1 → 4.4.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.
@@ -20,7 +20,6 @@ class TwilioMessageAdapter extends MessageAdapter {
20
20
  origin: 'patient',
21
21
  processed: false,
22
22
  pushName: rawMessage.ProfileName || null,
23
- timestamp: new Date(),
24
23
  body,
25
24
  media,
26
25
  interactive,
@@ -18,7 +18,7 @@ async function logBugReportToAirtable(reportedBug) {
18
18
  if (messages?.length) {
19
19
  const msgs = await Message.find({ _id: { $in: messages } }).sort({ createdAt: 1 });
20
20
  conversation = msgs.map(msg => {
21
- const timestamp = new Date(msg.timestamp).toISOString().slice(0, 16).replace('T', ' ');
21
+ const timestamp = msg.createdAt.toISOString().slice(0, 16).replace('T', ' ');
22
22
  const role = msg.from_me ? 'Assistant' : 'Patient';
23
23
  return `[${timestamp}] ${role}: ${msg.body || '(media)'}`;
24
24
  }).join('\n');
@@ -341,7 +341,7 @@ const getConversationsByNameController = async (req, res) => {
341
341
  phoneNumber: conv._id,
342
342
  name: conv.name,
343
343
  lastMessage: conv.latestMessage.body,
344
- lastMessageTime: conv.latestMessage.timestamp,
344
+ lastMessageTime: conv.latestMessage.createdAt,
345
345
  messageCount: conv.messageCount
346
346
  })),
347
347
  pagination: {
@@ -13,7 +13,7 @@ async function logInteractionToAirtable(messageIds, whatsapp_id, reporter, quali
13
13
  const messageObjects = await Message.find({ _id: { $in: messageIds } }).sort({ createdAt: -1 });
14
14
 
15
15
  const conversation = messageObjects.map(msg => {
16
- const timestamp = new Date(msg.timestamp).toISOString().slice(0, 16).replace('T', ' ');
16
+ const timestamp = msg.createdAt.toISOString().slice(0, 16).replace('T', ' ');
17
17
  const role = msg.from_me ? 'Assistant' : 'Patient';
18
18
  return `[${timestamp}] ${role}: ${msg.body || '(media)'}`;
19
19
  }).join('\n');
@@ -248,7 +248,7 @@ class NexusMessaging {
248
248
  ? await Message.findById(messageData.parentMessageId)
249
249
  : await this.messageStorage.savePendingMessage({
250
250
  ...messageData,
251
- provider: 'twilio', timestamp: new Date(), fromMe: true,
251
+ provider: 'twilio', fromMe: true,
252
252
  processed: messageData.processed ?? false
253
253
  });
254
254
  await triggerTemplateRecovery(parent, { source: 'preemptive' });
@@ -261,7 +261,7 @@ class NexusMessaging {
261
261
  const pending = await this.messageStorage.savePendingMessage({
262
262
  ...messageData,
263
263
  provider: 'twilio',
264
- timestamp: new Date(), fromMe: true,
264
+ fromMe: true,
265
265
  processed: messageData.processed ?? false
266
266
  });
267
267
  parentId = pending?._id || null;
@@ -281,7 +281,8 @@ class NexusMessaging {
281
281
  ...messageData,
282
282
  messageId: result.messageId,
283
283
  provider: result.provider,
284
- timestamp: new Date(), fromMe: true, processed: true
284
+ fromMe: true,
285
+ processed: true
285
286
  });
286
287
  }
287
288
 
@@ -91,7 +91,6 @@ async function downloadMediaAndCreateFile(code, reply) {
91
91
  try {
92
92
  const resultMedia = await Message.findOne({
93
93
  message_id: reply.message_id,
94
- timestamp: reply.timestamp,
95
94
  media: { $ne: null }
96
95
  });
97
96
 
@@ -9,7 +9,7 @@ const storeProcessedContent = async (reply, thread, processedContent) => {
9
9
  if (!processedContent || !reply.media) return;
10
10
 
11
11
  await Message.updateOne(
12
- { message_id: reply.message_id, timestamp: reply.timestamp },
12
+ { message_id: reply.message_id },
13
13
  { $set: {
14
14
  assistant_id: thread.getAssistantId(),
15
15
  thread_id: thread.getConversationId(),
@@ -54,7 +54,7 @@ async function updateMessageStatus(messageSid, status, errorCode = null, errorMe
54
54
  whatsapp_id: updated.numero,
55
55
  error_code: errorCode || null,
56
56
  status,
57
- date: updated.timestamp,
57
+ date: updated.createdAt.toISOString(),
58
58
  message_id: updated.message_id
59
59
  },
60
60
  {
package/lib/index.d.ts CHANGED
@@ -9,7 +9,6 @@ declare module '@peopl-health/nexus' {
9
9
  fileType?: 'text' | 'image' | 'document' | 'audio' | 'video';
10
10
  contentSid?: string;
11
11
  variables?: Record<string, string>;
12
- timestamp?: Date;
13
12
  interactive?: InteractiveData;
14
13
  media?: MediaData;
15
14
  command?: CommandData;
@@ -446,6 +445,23 @@ declare module '@peopl-health/nexus' {
446
445
  handlePendingFunctionCalls(assistant: any, conversationMessages: any[], toolMetadata?: any): Promise<{ outputs: any[]; toolsExecuted: any[] }>;
447
446
  }
448
447
 
448
+ export interface MapCacheOptions {
449
+ maxSize?: number;
450
+ ttl?: number | null;
451
+ }
452
+
453
+ export class MapCache<V = any> {
454
+ constructor(options?: MapCacheOptions);
455
+ get(key: any): V | undefined;
456
+ getEntry(key: any): { value: V; timestamp: number } | null;
457
+ set(key: any, value: V): void;
458
+ has(key: any): boolean;
459
+ delete(key: any): void;
460
+ clear(): void;
461
+ readonly size: number;
462
+ entries(): Array<[string, V]>;
463
+ }
464
+
449
465
  export interface SessionEndResult {
450
466
  summary: any | null;
451
467
  memoriesCreated: number;
package/lib/index.js CHANGED
@@ -21,6 +21,7 @@ const { EvalProvider } = require('./eval/EvalProvider');
21
21
  const { registerTool, hasTool, getToolSchemas, clearRegistry } = require('./services/toolRegistryService');
22
22
  const { DefaultMemoryManager } = require('./memory/DefaultMemoryManager');
23
23
  const { EnhancedMemoryManager } = require('./memory/EnhancedMemoryManager');
24
+ const MapCache = require('./utils/MapCache');
24
25
 
25
26
  class Nexus {
26
27
  constructor(config = {}) {
@@ -227,4 +228,5 @@ module.exports = {
227
228
  clearRegistry,
228
229
  DefaultMemoryManager,
229
230
  EnhancedMemoryManager,
231
+ MapCache,
230
232
  };
@@ -1,5 +1,4 @@
1
1
  const mongoose = require('mongoose');
2
- const moment = require('moment-timezone');
3
2
 
4
3
  const { Monitoreo_ID } = require('../config/airtableConfig');
5
4
 
@@ -19,7 +18,6 @@ const messageSchema = new mongoose.Schema({
19
18
  body: { type: String, default: '' },
20
19
  numero: { type: String, required: true },
21
20
  nombre_whatsapp: { type: String, default: null },
22
- timestamp: { type: String, required: true, default: Date.now },
23
21
  message_id: { type: String, default: null},
24
22
  interactive_type: {
25
23
  type: String,
@@ -109,13 +107,6 @@ messageSchema.index({ message_id: 1 }, { name: 'message_id_idx', sparse: true })
109
107
 
110
108
  messageSchema.index({ triggeredBy: 1, createdAt: -1 }, { name: 'triggered_by_idx', sparse: true });
111
109
 
112
- messageSchema.pre('save', function (next) {
113
- if (this.timestamp) {
114
- this.timestamp = moment.tz(this.timestamp, 'America/Mexico_City').toDate();
115
- }
116
- next();
117
- });
118
-
119
110
  const Message = mongoose.model('Message', messageSchema);
120
111
 
121
112
  async function insertMessage(values) {
@@ -168,7 +159,7 @@ async function insertMessage(values) {
168
159
 
169
160
  updateRecordByFilter(Monitoreo_ID, 'message_monitor', `{whatsapp_id} = "${values.numero}"`, {
170
161
  ...(values.from_me ? { last_message_bot: values.body } : { last_message_patient: values.body, read: false }),
171
- ...(values.from_me ? { last_message_bot_time: values.timestamp } : { last_message_patient_time: values.timestamp })
162
+ ...(values.from_me ? { last_message_bot_time: doc.createdAt.toISOString() } : { last_message_patient_time: doc.createdAt.toISOString() })
172
163
  }, values.numero).catch(err => logger.error('[MongoStorage] Failed to update message_monitor table', { numero: values.numero, error: err.message }));
173
164
 
174
165
  logger.info('[MongoStorage] Message inserted or updated successfully');
@@ -179,20 +170,11 @@ async function insertMessage(values) {
179
170
  }
180
171
  }
181
172
 
182
- function formatTimestamp(unixTimestamp) {
183
- const date = new Date(unixTimestamp * 1000);
184
- return date.toLocaleString('sv-MX', {
185
- timeZone: 'America/Mexico_City',
186
- hour12: false,
187
- }).replace(' ', 'T').slice(0, 19);
188
- }
189
-
190
173
  function getMessageValues(message, content) {
191
174
  return {
192
175
  nombre_whatsapp: message.pushName,
193
176
  numero: message.key.participant || message.key.remoteJid,
194
177
  body: content,
195
- timestamp: formatTimestamp(message.messageTimestamp),
196
178
  message_id: message.key.id,
197
179
  group_id: message.key.remoteJid || null,
198
180
  from_me: message.key.fromMe
@@ -223,6 +205,5 @@ module.exports = {
223
205
  Message,
224
206
  insertMessage,
225
207
  getMessageValues,
226
- formatTimestamp,
227
208
  getContactDisplayName
228
209
  };
@@ -97,7 +97,6 @@ class MongoStorage {
97
97
  }
98
98
 
99
99
  buildMessageValues(messageData = {}) {
100
- const now = new Date();
101
100
  const messageId = messageData.messageId ?? null;
102
101
  const fromMe = messageData.fromMe !== undefined ? messageData.fromMe : true;
103
102
 
@@ -105,7 +104,6 @@ class MongoStorage {
105
104
  nombre_whatsapp: fromMe ? runtimeConfig.get('USER_DB_MONGO') : messageData.pushName,
106
105
  numero: ensureWhatsAppFormat(messageData.code),
107
106
  body: messageData.body || '',
108
- timestamp: messageData.timestamp?.toISOString() || now.toISOString(),
109
107
  processed: messageData.processed || false,
110
108
  message_id: messageId,
111
109
  interactive_type: messageData.interactive?.type || null,
@@ -172,12 +170,6 @@ class MongoStorage {
172
170
  }
173
171
  }
174
172
 
175
- formatTimestamp(timestamp) {
176
- const date = new Date(timestamp || Date.now());
177
- const mexicoTime = new Date(date.getTime() - (6 * 60 * 60 * 1000));
178
- return mexicoTime.toISOString().replace('T', ' ').slice(0, 19);
179
- }
180
-
181
173
  async disconnect() {
182
174
  await mongoDisconnect();
183
175
  }
@@ -8,17 +8,17 @@ class MapCache {
8
8
  get(key) {
9
9
  const k = String(key);
10
10
  const entry = this._cache.get(k);
11
- if (!entry) return null;
11
+ if (!entry) return undefined;
12
12
  if (this._ttl && (Date.now() - entry.timestamp >= this._ttl)) {
13
13
  this._cache.delete(k);
14
- return null;
14
+ return undefined;
15
15
  }
16
16
  return entry.value;
17
17
  }
18
18
 
19
19
  getEntry(key) {
20
20
  const k = String(key);
21
- return this._cache.get(k) || null;
21
+ return this._cache.get(k) || undefined;
22
22
  }
23
23
 
24
24
  set(key, value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peopl-health/nexus",
3
- "version": "4.4.1",
3
+ "version": "4.4.3",
4
4
  "description": "Core messaging and assistant library for WhatsApp communication platforms",
5
5
  "keywords": [
6
6
  "whatsapp",