@peopl-health/nexus 4.2.2 → 4.2.4

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.
@@ -16,7 +16,7 @@ const { triggerTemplateRecovery } = require('../helpers/templateRecoveryHelper')
16
16
 
17
17
  const { createMessagingProvider } = require('../adapters/registry');
18
18
 
19
- const { addMsgAssistant, preProcessMessages } = require('../services/assistantService');
19
+ const { preProcessMessages } = require('../services/assistantService');
20
20
  const { hasPreprocessingHandler, invokePreprocessingHandler } = require('../services/preprocessingService');
21
21
 
22
22
  const { BatchingManager } = require('../core/BatchingManager');
@@ -238,11 +238,13 @@ class NexusMessaging {
238
238
  if (messageData._fromConversationReply) messageData.processed = true;
239
239
 
240
240
  if (this._needsTemplateRoute(messageData) && !(await isWithin24HourWindow(messageData.code))) {
241
- const parent = await this.messageStorage.savePendingMessage({
242
- ...messageData,
243
- provider: 'twilio', timestamp: new Date(), fromMe: true,
244
- processed: messageData.processed ?? false
245
- });
241
+ const parent = messageData.parentMessageId
242
+ ? await Message.findById(messageData.parentMessageId)
243
+ : await this.messageStorage.savePendingMessage({
244
+ ...messageData,
245
+ provider: 'twilio', timestamp: new Date(), fromMe: true,
246
+ processed: messageData.processed ?? false
247
+ });
246
248
  await triggerTemplateRecovery(parent, { source: 'preemptive' });
247
249
  return { success: true, messageId: String(parent._id), status: 'queued', preemptive: true };
248
250
  }
@@ -280,32 +282,12 @@ class NexusMessaging {
280
282
  const chatId = messageData.code;
281
283
  if (chatId) ensureThreadExists(chatId);
282
284
 
283
- let content = messageData.body || messageData.message;
284
- if (!content && messageData.contentSid) {
285
- try {
286
- content = await this.provider.renderTemplate?.(messageData.contentSid, messageData.variables);
287
- } catch (err) {
288
- logger.warn('[NexusMessaging] Failed to render template', { error: err.message });
289
- }
290
- }
291
-
292
- if (messageData.origin !== 'assistant' && messageData.code && content) {
293
- await addMsgAssistant(
294
- messageData.code,
295
- [content],
296
- 'assistant',
297
- false,
298
- messageData._fromConversationReply || providerStores
299
- );
300
- }
301
-
302
285
  return result;
303
286
  }
304
287
 
305
288
  _needsTemplateRoute(messageData) {
306
289
  if (this.provider?.supportsMessageStorage?.() !== true) return false;
307
290
  if (messageData.contentSid) return false;
308
- if (messageData.parentMessageId) return false;
309
291
  if (!messageData.code) return false;
310
292
  return true;
311
293
  }
@@ -20,7 +20,7 @@ async function triggerTemplateRecovery(messageDoc, { source = 'reactive', messag
20
20
 
21
21
  try {
22
22
  const claim = await Message.updateOne(
23
- { _id: messageDocId, 'statusInfo.recoveryStartedAt': { $exists: false } },
23
+ { _id: messageDocId, 'statusInfo.recoveryStartedAt': null },
24
24
  { $set: { 'statusInfo.recoveryStartedAt': new Date() } }
25
25
  );
26
26
  if (!claim.modifiedCount && !claim.nModified) {
@@ -63,6 +63,11 @@ async function triggerTemplateRecovery(messageDoc, { source = 'reactive', messag
63
63
 
64
64
  if (setupErr) {
65
65
  logger.error('[TemplateRecovery] Setup failed', { ...logCtx, error: setupErr.message });
66
+ if (twilioContent?.sid) {
67
+ provider.deleteTemplate(twilioContent.sid).catch(deleteErr =>
68
+ logger.warn('[TemplateRecovery] Failed to delete partially-created template', { templateSid: twilioContent.sid, error: deleteErr.message })
69
+ );
70
+ }
66
71
  return;
67
72
  }
68
73
 
@@ -93,6 +93,12 @@ class TemplateApprovalJob extends BaseJob {
93
93
  const nextAttempt = attempt + 1;
94
94
  if (nextAttempt >= MAX_ATTEMPTS) {
95
95
  logger.warn('[TemplateApprovalJob] Max attempts reached, giving up', { templateSid, messageId, attempt, reason });
96
+ try {
97
+ const provider = this.requireProvider();
98
+ await provider.deleteTemplate(templateSid);
99
+ } catch (deleteErr) {
100
+ logger.warn('[TemplateApprovalJob] Failed to delete template after giving up', { templateSid, error: deleteErr.message });
101
+ }
96
102
  return { success: false, reason: 'max_attempts', priorReason: reason };
97
103
  }
98
104
  await this.schedule({ templateSid, messageId, originalMessageSid, attempt: nextAttempt });
@@ -101,7 +107,7 @@ class TemplateApprovalJob extends BaseJob {
101
107
 
102
108
  async _handleApproved({ provider, message, templateSid, originalMessageSid }) {
103
109
  const claim = await Message.updateOne(
104
- { _id: message._id, 'statusInfo.recoverySentAt': { $exists: false } },
110
+ { _id: message._id, 'statusInfo.recoverySentAt': null },
105
111
  { $set: { 'statusInfo.recoverySentAt': new Date() } }
106
112
  );
107
113
  if (!claim.modifiedCount && !claim.nModified) {
@@ -116,7 +116,7 @@ class MongoStorage {
116
116
  prompt: messageData.prompt || null,
117
117
  preset: messageData.preset || null,
118
118
  response_id: messageData.response_id || null,
119
- statusInfo: messageData.statusInfo || null,
119
+ statusInfo: messageData.statusInfo,
120
120
  clinical_context: messageData.clinicalContext || null,
121
121
  triggeredBy: messageData.triggeredBy || null
122
122
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peopl-health/nexus",
3
- "version": "4.2.2",
3
+ "version": "4.2.4",
4
4
  "description": "Core messaging and assistant library for WhatsApp communication platforms",
5
5
  "keywords": [
6
6
  "whatsapp",