@peopl-health/nexus 5.68.11 → 5.68.12

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.
@@ -21,10 +21,12 @@ function latestAlarm(review) {
21
21
  function flagsByStatus(sections) {
22
22
  const flags = (Array.isArray(sections?.redFlags) ? sections.redFlags : []).filter((flag) => inlineOf(flag?.flag));
23
23
  const named = (present) => flags.filter((flag) => flag.present === present).map((flag) => inlineOf(flag.flag));
24
+ const pending = flags.filter((flag) => typeof flag.present !== 'boolean');
24
25
  return {
25
26
  present: named(true),
26
27
  absent: named(false),
27
- unassessed: flags.filter((flag) => typeof flag.present !== 'boolean').map((flag) => inlineOf(flag.flag)),
28
+ unassessed: pending.map((flag) => inlineOf(flag.flag)),
29
+ drugSafety: pending.filter((flag) => flag.blocksDrug !== false).map((flag) => inlineOf(flag.flag)),
28
30
  };
29
31
  }
30
32
 
@@ -49,13 +51,24 @@ function drugOf(symptom, item) {
49
51
 
50
52
  const proposedDrugs = ({ proposal }) => (proposal?.items ?? []).map((item) => drugOf(proposal.symptom, item)).filter(Boolean);
51
53
 
52
- function proposalLine({ proposal, withheldReason }) {
54
+ function proposalLine({ proposal, withheldReason, conduct, sections }) {
53
55
  const drugs = proposedDrugs({ proposal });
54
- if (!drugs.length) return `→ Sin propuesta de tratamiento: ${sentence(inlineOf(withheldReason) || 'requiere valoración médica')}`;
56
+ if (!drugs.length) {
57
+ const why = [withheldReason, conduct].map(inlineOf).filter(Boolean).map(sentence).join(' ');
58
+ return `→ Sin propuesta de tratamiento: ${why || 'requiere valoración médica.'}`;
59
+ }
55
60
  const declared = [...(proposal.conditions ?? []), ...(proposal.ruledOut ?? []).map((key) => `descartado ${key}`)]
56
61
  .map((key) => inlineOf(key)?.replace(/_/g, ' ')).filter(Boolean);
57
62
  const table = formularyFor(proposal.symptom)?.label;
58
- return [`→ Propuesta para su aprobación (tabla ${table}): ${sentence(drugs.join('; '))}`, declared.length && `Verificar: ${sentence(declared.join(', '))}`].filter(Boolean).join(' ');
63
+ const { unassessed, drugSafety } = flagsByStatus(sections);
64
+ const lead = drugSafety.length
65
+ ? `→ Propuesta para su aprobación si se confirma sin ${drugSafety.join(', ')} (tabla ${table})`
66
+ : `→ Propuesta para su aprobación (tabla ${table})`;
67
+ return [
68
+ `${lead}: ${sentence(drugs.join('; '))}`,
69
+ unassessed.length && 'Si algo de lo pendiente es positivo: valoración presencial.',
70
+ declared.length && `Verificar: ${sentence(declared.join(', '))}`,
71
+ ].filter(Boolean).join(' ');
59
72
  }
60
73
 
61
74
  function symptomParagraph(entry, fallbackSymptom) {
@@ -13,7 +13,7 @@ const { logger } = require('../../utils/logger');
13
13
  const { arrayArg, safeParse } = require('../../utils/jsonUtils');
14
14
  const { withTiming } = require('../../utils/tracingDecorator');
15
15
 
16
- const { crossSymptomIssues, unproposedDrugsIn, validateProposal } = require('./treatmentProposalService');
16
+ const { crossSymptomIssues, drugsNamedIn, unproposedDrugsIn, validateProposal } = require('./treatmentProposalService');
17
17
 
18
18
  const CONVERSATION_TURNS = 40;
19
19
  const TRIAGE_LIMIT = 3;
@@ -22,11 +22,10 @@ const CALL_LOG_LIMIT = 10;
22
22
  const trimmed = (value) => String(value ?? '').trim();
23
23
 
24
24
  function withholdReason(sections) {
25
- const { present, unassessed } = flagsByStatus(sections);
25
+ const { present } = flagsByStatus(sections);
26
26
  const modifiers = (Array.isArray(sections?.treatmentModifiers) ? sections.treatmentModifiers : []).map(trimmed).filter(Boolean);
27
27
  const reasons = [];
28
28
  if (present.length) reasons.push(present.length === 1 ? 'hay una bandera roja presente' : 'hay banderas rojas presentes');
29
- if (unassessed.length) reasons.push(unassessed.length === 1 ? 'hay una bandera roja sin evaluar' : 'hay banderas rojas sin evaluar');
30
29
  if (modifiers.length) reasons.push(`condición que cambia el algoritmo (${modifiers.join(', ')})`);
31
30
  return reasons.join('; ') || null;
32
31
  }
@@ -35,8 +34,10 @@ function settleProposal(parsed) {
35
34
  const withheld = withholdReason(parsed);
36
35
  const raw = parsed?.treatmentProposal;
37
36
  const items = Array.isArray(raw?.items) ? raw.items : [];
38
- if (withheld) return { proposal: null, withheldReason: withheld, strippedItems: items.length };
39
- if (!items.length) return { proposal: null, withheldReason: trimmed(parsed?.proposalWithheldReason) || null, strippedItems: 0 };
37
+ const stated = trimmed(parsed?.proposalWithheldReason);
38
+ const conduct = stated && !drugsNamedIn(stated).length ? stated : null;
39
+ if (withheld) return { proposal: null, withheldReason: withheld, conduct, strippedItems: items.length };
40
+ if (!items.length) return { proposal: null, withheldReason: null, conduct, strippedItems: 0 };
40
41
 
41
42
  const conditions = Array.isArray(raw.conditions) ? raw.conditions : [];
42
43
  const ruledOut = Array.isArray(raw.ruledOut) ? raw.ruledOut : [];
@@ -154,7 +155,8 @@ async function generateEscalationDraft({
154
155
 
155
156
  const issues = settled.flatMap((entry) => entry.invalid ?? []);
156
157
  if (!issues.length) issues.push(...crossSymptomIssues(proposals));
157
- const patientDrugs = unproposedDrugsIn(patientMessage, proposals);
158
+ const confirmed = settled.filter((entry) => entry.proposal && !flagsByStatus(entry.block).drugSafety.length).map((entry) => entry.proposal);
159
+ const patientDrugs = unproposedDrugsIn(patientMessage, confirmed);
158
160
  if (!issues.length && patientDrugs.length) {
159
161
  issues.push(`el mensaje al paciente menciona ${patientDrugs.join(', ')}, que no está en la propuesta de tratamiento`);
160
162
  }
@@ -167,7 +169,7 @@ async function generateEscalationDraft({
167
169
  const doctorText = composeDoctorBody({
168
170
  alarm: alarms[alarms.length - 1] ?? null,
169
171
  shared: parsed,
170
- symptoms: settled.map(({ block, proposal, withheldReason }) => ({ sections: block, proposal, withheldReason })),
172
+ symptoms: settled.map(({ block, proposal, withheldReason, conduct }) => ({ sections: block, proposal, withheldReason, conduct })),
171
173
  });
172
174
 
173
175
  if (!doctorText || !patientMessage) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peopl-health/nexus",
3
- "version": "5.68.11",
3
+ "version": "5.68.12",
4
4
  "description": "Core messaging and assistant library for WhatsApp communication platforms",
5
5
  "keywords": [
6
6
  "whatsapp",