@peopl-health/nexus 5.54.0-dev.7866 → 5.54.0-dev.7891

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.
@@ -15,20 +15,10 @@ const { cleanupFiles } = require('../../helpers/filesHelper.js');
15
15
  const { getMessages, countMessages } = require('../../services/messageService');
16
16
 
17
17
  const { getAssistantById } = require('./assistantResolver');
18
- const { recordPausedThreadMessage } = require('./clinicalAirtableService');
19
- const { offerSafetyNet } = require('./pausedSafetyNetService');
18
+ const { coverUnansweredPatient } = require('./pausedSafetyNetService');
20
19
 
21
20
  const MEDIA_BACKLOG_LIMIT = 10;
22
21
 
23
- const pausedAlertText = async (code, newest) => {
24
- if (!newest.interactive_type) return newest.plainBody || newest.body;
25
- const [written] = await getMessages(
26
- { numero: code, from_me: false, interactive_type: null, createdAt: { $lte: newest.createdAt } },
27
- { sort: { createdAt: -1 }, limit: 1 }
28
- );
29
- return written ? written.plainBody || written.body : null;
30
- };
31
-
32
22
  const fetchMediaBacklog = async (code, trigger) => {
33
23
  const [lastOutbound] = await getMessages(
34
24
  { numero: code, from_me: true, createdAt: { $lt: trigger.createdAt } },
@@ -122,12 +112,7 @@ const preProcessMessagesCore = async (code, message_ = null, thread) => {
122
112
  return { shouldProcess: false, messages: null, timings, pendingMediaUpdates: [] };
123
113
  }
124
114
 
125
- if (thread.stopped) {
126
- await Promise.allSettled([
127
- recordPausedThreadMessage({ code, text: await pausedAlertText(code, lastMessage[0]) }),
128
- offerSafetyNet({ code })
129
- ]);
130
- }
115
+ if (thread.stopped) await coverUnansweredPatient({ code });
131
116
 
132
117
  const backlog = await fetchMediaBacklog(code, lastMessage[0]);
133
118
  const replies = [...backlog, ...lastMessage];
@@ -18,7 +18,7 @@ const { getMessages } = require('../../services/messageService');
18
18
  const { getPatientTasks, updatePatientTask } = require('../../services/patientTaskService');
19
19
 
20
20
  const { WriteClaimStore } = require('./writeClaimStore');
21
- const { PAUSED_THREAD_DETAILS_PREFIX, recordUnresolvedRequest } = require('./clinicalAirtableService');
21
+ const { PAUSED_THREAD_DETAILS_PREFIX, recordPausedThreadMessage, recordUnresolvedRequest } = require('./clinicalAirtableService');
22
22
  const { humanRepliedSince, openPledge, stopSafetyNetSweep } = require('./safetyNetPledgeService');
23
23
 
24
24
  const getMessaging = () => require('../../core/NexusMessaging');
@@ -132,6 +132,30 @@ async function offerIsLive(code) {
132
132
  }
133
133
  }
134
134
 
135
+ async function unansweredText(code) {
136
+ const [written] = await getMessages(
137
+ { numero: code, from_me: false, interactive_type: null },
138
+ { sort: { createdAt: -1 }, limit: 1 }
139
+ );
140
+ return written ? written.plainBody || written.body : null;
141
+ }
142
+
143
+ async function coverUnansweredPatient({ code }) {
144
+ if (!code) return;
145
+
146
+ const claim = await acquireSendClaim({ idempotencyKey: `safetynet-cover:${code}` });
147
+ if (!claim.acquired) return;
148
+
149
+ const results = await Promise.allSettled([
150
+ unansweredText(code).then((text) => recordPausedThreadMessage({ code, text })),
151
+ offerSafetyNet({ code }),
152
+ ]);
153
+
154
+ const covered = results.every((r) => r.status === 'fulfilled');
155
+ if (covered) await completeSendClaim(claim.claimId);
156
+ else await releaseSendClaim(claim.claimId);
157
+ }
158
+
135
159
  async function fileUrgentRequest(code, choice) {
136
160
  const copy = REQUEST_COPY[choice];
137
161
  return recordUnresolvedRequest({
@@ -283,6 +307,7 @@ function registerSafetyNetRoutes() {
283
307
  }
284
308
 
285
309
  module.exports = {
310
+ coverUnansweredPatient,
286
311
  disarmSafetyNet,
287
312
  offerSafetyNet,
288
313
  handleSafetyNetTap,
@@ -31,6 +31,7 @@ const { releaseHeldMessages, sweepHeldMessages } = require('../services/heldMess
31
31
  const { BatchingManager } = require('../core/BatchingManager');
32
32
  const { ProcessingPipeline } = require('../core/ProcessingPipeline');
33
33
  const { preProcessMessages, configureOpenAIProvider, AssistantProcessor, TURN_KIND } = require('../clinical');
34
+ const { coverUnansweredPatient } = require('../clinical/services/pausedSafetyNetService');
34
35
  const { buildOutreachCarrier } = require('../clinical/services/outreachCarrierService');
35
36
  const { routineOutreachCollisionReason } = require('../clinical/services/outreachSweepService');
36
37
  const {
@@ -675,8 +676,14 @@ class NexusMessaging {
675
676
  return await this._executeWithPipeline(chatId, 'message', 'preempt',
676
677
  async (preProcessResult, shouldContinue, runId) => {
677
678
  return await this._processMessages(chatId, async () => {
678
- const resolved = await this.assistantProcessor.resolveThread(chatId);
679
- if (!resolved) return null;
679
+ const resolved = await this.assistantProcessor.resolveThread(chatId).catch((error) => {
680
+ logger.warn('[NexusMessaging] Could not resolve an assistant for this patient', { code: chatId, error: error.message });
681
+ return null;
682
+ });
683
+ if (!resolved) {
684
+ await coverUnansweredPatient({ code: chatId });
685
+ return null;
686
+ }
680
687
 
681
688
  const preProcessed = await preProcessMessages(chatId, null, resolved.thread);
682
689
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peopl-health/nexus",
3
- "version": "5.54.0-dev.7866",
3
+ "version": "5.54.0-dev.7891",
4
4
  "description": "Core messaging and assistant library for WhatsApp communication platforms",
5
5
  "keywords": [
6
6
  "whatsapp",