@peopl-health/nexus 3.8.21 → 3.8.23

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.
@@ -3,7 +3,6 @@ const { v4: uuidv4 } = require('uuid');
3
3
  const twilio = require('twilio');
4
4
 
5
5
  const runtimeConfig = require('../config/runtimeConfig');
6
- const { Symptoms_ID } = require('../config/airtableConfig');
7
6
  const { generatePresignedUrl } = require('../config/awsConfig');
8
7
 
9
8
  const { sanitizeMediaFilename } = require('../utils/sanitizerUtils');
@@ -18,8 +17,6 @@ const { uploadMediaToS3, getFileExtension } = require('../helpers/mediaHelper');
18
17
 
19
18
  const { MessageProvider } = require('../adapters/MessageProvider');
20
19
 
21
- const { updateRecordByFilter } = require('../services/airtableService');
22
-
23
20
  class TwilioProvider extends MessageProvider {
24
21
  constructor(config) {
25
22
  super(config);
@@ -233,11 +230,6 @@ class TwilioProvider extends MessageProvider {
233
230
  }
234
231
  }
235
232
  );
236
-
237
- if (scheduledMessage.contentSid) {
238
- updateRecordByFilter(Symptoms_ID, 'weekly_questionnaires', `{sid}="${scheduledMessage.contentSid}"`, { send_status: status })
239
- .catch(err => logger.warn('[TwilioProvider] Failed to update weekly_questionnaires send_status', err?.message));
240
- }
241
233
  } catch (err) {
242
234
  logger.warn('[TwilioProvider] Failed to update scheduled message status', err?.message);
243
235
  }
@@ -1,7 +1,6 @@
1
1
  const moment = require('moment-timezone');
2
2
 
3
3
  const runtimeConfig = require('../config/runtimeConfig');
4
- const { Symptoms_ID } = require('../config/airtableConfig');
5
4
 
6
5
  const { logger } = require('../utils/logger');
7
6
 
@@ -12,7 +11,7 @@ const FlowRouting = require('../models/flowRoutingModel.js');
12
11
  const { ensureWhatsAppFormat } = require('../helpers/twilioHelper');
13
12
  const { ensureFlowTokenInVariables } = require('../helpers/templateFlowControllerHelper');
14
13
 
15
- const { getRecordByFilter: defaultGetRecordByFilter, updateRecordByFilter: defaultUpdateRecordByFilter } = require('../services/airtableService');
14
+ const { getRecordByFilter: defaultGetRecordByFilter } = require('../services/airtableService');
16
15
 
17
16
  const {
18
17
  sendMessage: defaultSendMessage,
@@ -23,7 +22,6 @@ const {
23
22
  const dependencies = {
24
23
  ScheduledMessage: DefaultScheduledMessage,
25
24
  getRecordByFilter: defaultGetRecordByFilter,
26
- updateRecordByFilter: defaultUpdateRecordByFilter,
27
25
  sendScheduledMessage: defaultSendScheduledMessage,
28
26
  sendMessage: defaultSendMessage
29
27
  };
@@ -62,11 +60,6 @@ const _pickMessageId = (result, fallback) =>
62
60
  const _sendAndPersist = async (payload) => {
63
61
  const saved = await dependencies.ScheduledMessage.create(payload);
64
62
 
65
- if (saved.contentSid) {
66
- dependencies.updateRecordByFilter(Symptoms_ID, 'weekly_questionnaires', `{sid}="${saved.contentSid}"`, { send_status: 'pending' })
67
- .catch(err => logger.error('[messageController] Failed to update weekly_questionnaires send_status', { contentSid: saved.contentSid, error: err.message }));
68
- }
69
-
70
63
  const result = dependencies.sendScheduledMessage
71
64
  ? await dependencies.sendScheduledMessage(saved)
72
65
  : await dependencies.sendMessage({ ...payload, body: payload.message });
@@ -36,28 +36,6 @@ async function fetchBasePrompt(promptId) {
36
36
  return record;
37
37
  }
38
38
 
39
- async function fetchSnippets(promptId) {
40
- const cacheKey = `snippets:${promptId}`;
41
- const cached = snippetCache.get(cacheKey);
42
- if (cached) return cached;
43
-
44
- try {
45
- const records = await getRecordByFilter(
46
- Config_ID,
47
- 'context_snippets',
48
- `FIND("${promptId}", ARRAYJOIN({prompts}))`,
49
- );
50
- const snippets = records || [];
51
- snippetCache.set(cacheKey, snippets);
52
- return snippets;
53
- } catch (error) {
54
- logger.error('[promptComposer] Failed to fetch snippets', {
55
- promptId, error: error.message,
56
- });
57
- return [];
58
- }
59
- }
60
-
61
39
  function sortSnippets(snippets) {
62
40
  return [...snippets].sort((a, b) => {
63
41
  const aIndex = SNIPPET_TYPE_ORDER.indexOf(a.type || '');
@@ -103,7 +81,10 @@ async function composePrompt({ presetId = null, promptId = null, variables = nul
103
81
  const promptRecordId = preset.prompt?.[0];
104
82
  if (promptRecordId) {
105
83
  const promptRecords = await getRecordByFilter(Config_ID, 'responses', `RECORD_ID()="${promptRecordId}"`);
106
- resolvedPromptId = promptRecords?.[0]?.prompt_id || promptId;
84
+ const presetPromptId = promptRecords?.[0]?.prompt_id;
85
+ if (presetPromptId) {
86
+ resolvedPromptId = presetPromptId;
87
+ }
107
88
  }
108
89
  } else {
109
90
  logger.error('[promptComposer] Preset not found in Airtable', { presetId });
@@ -112,6 +93,18 @@ async function composePrompt({ presetId = null, promptId = null, variables = nul
112
93
 
113
94
  const baseRecord = await fetchBasePrompt(resolvedPromptId);
114
95
 
96
+ // If no explicit preset was passed, check if the prompt defines one via preset_id field
97
+ if (!presetId && baseRecord?.preset_id) {
98
+ presetId = baseRecord.preset_id;
99
+ const preset = await fetchPreset(presetId);
100
+ if (preset) {
101
+ presetSnippetIds = preset.snippets || [];
102
+ presetToolIds = preset.tools || [];
103
+ } else {
104
+ logger.error('[promptComposer] Prompt-level preset not found in Airtable', { presetId, promptId: resolvedPromptId });
105
+ }
106
+ }
107
+
115
108
  if (!baseRecord) {
116
109
  logger.error('[promptComposer] Base prompt not found in Airtable', { promptId: resolvedPromptId });
117
110
  }
@@ -120,7 +113,7 @@ async function composePrompt({ presetId = null, promptId = null, variables = nul
120
113
 
121
114
  const snippets = presetSnippetIds
122
115
  ? await fetchSnippetsByRecordIds(presetSnippetIds)
123
- : await fetchSnippets(resolvedPromptId);
116
+ : [];
124
117
 
125
118
  const activeSnippets = status
126
119
  ? snippets.filter(s => !s.status || s.status === status)
@@ -147,28 +140,6 @@ async function composePrompt({ presetId = null, promptId = null, variables = nul
147
140
  return { resolvedPrompt, snippetIds, promptId: resolvedPromptId, presetToolIds };
148
141
  }
149
142
 
150
- async function fetchToolMapping(promptId) {
151
- const cacheKey = `tools:${promptId}`;
152
- const cached = toolCache.get(cacheKey);
153
- if (cached) return cached;
154
-
155
- try {
156
- const records = await getRecordByFilter(
157
- Config_ID,
158
- 'tools',
159
- `FIND("${promptId}", ARRAYJOIN({prompts}))`,
160
- );
161
- const tools = records || [];
162
- toolCache.set(cacheKey, tools);
163
- return tools;
164
- } catch (error) {
165
- logger.warn('[promptComposer] Failed to fetch tool mapping, returning empty list', {
166
- promptId, error: error.message,
167
- });
168
- return [];
169
- }
170
- }
171
-
172
143
  async function fetchToolsByRecordIds(recordIds) {
173
144
  if (!recordIds?.length) return [];
174
145
 
@@ -194,9 +165,9 @@ async function resolveTools({ promptId, assistant, presetToolIds = null, status
194
165
 
195
166
  if (!hasRegistryTools && !hasAssistantTools) return { toolIds: [], filtered: false };
196
167
 
197
- const mappedTools = presetToolIds
198
- ? await fetchToolsByRecordIds(presetToolIds)
199
- : await fetchToolMapping(promptId);
168
+ if (!presetToolIds) return { toolIds: [], filtered: false };
169
+
170
+ const mappedTools = await fetchToolsByRecordIds(presetToolIds);
200
171
  if (!mappedTools.length) return { toolIds: [], filtered: false };
201
172
 
202
173
  const activeTools = status
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peopl-health/nexus",
3
- "version": "3.8.21",
3
+ "version": "3.8.23",
4
4
  "description": "Core messaging and assistant library for WhatsApp communication platforms",
5
5
  "keywords": [
6
6
  "whatsapp",