@peopl-health/nexus 1.5.5 → 1.5.6
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.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { airtable, getBase } = require('../config/airtableConfig');
|
|
2
2
|
const { replyAssistant } = require('../services/assistantService');
|
|
3
3
|
const { createProvider } = require('../adapters/registry');
|
|
4
|
+
const runtimeConfig = require('../config/runtimeConfig');
|
|
4
5
|
|
|
5
6
|
const mongoose = require('mongoose');
|
|
6
7
|
const OpenAI = require('openai');
|
|
@@ -374,7 +375,12 @@ class NexusMessaging {
|
|
|
374
375
|
typeof messageData.message?.conversation === 'string' ? messageData.message.conversation : null,
|
|
375
376
|
typeof messageData.Body === 'string' ? messageData.Body : null,
|
|
376
377
|
typeof messageData.raw?.message?.conversation === 'string' ? messageData.raw.message.conversation : null,
|
|
377
|
-
typeof messageData.raw?.Body === 'string' ? messageData.raw.Body : null
|
|
378
|
+
typeof messageData.raw?.Body === 'string' ? messageData.raw.Body : null,
|
|
379
|
+
typeof messageData.caption === 'string' ? messageData.caption : null,
|
|
380
|
+
typeof messageData.media?.caption === 'string' ? messageData.media.caption : null,
|
|
381
|
+
Array.isArray(messageData.media) && typeof messageData.media[0]?.caption === 'string'
|
|
382
|
+
? messageData.media[0].caption
|
|
383
|
+
: null
|
|
378
384
|
].find((value) => typeof value === 'string' && value.trim().length > 0) || null;
|
|
379
385
|
|
|
380
386
|
return { from, message };
|
|
@@ -416,7 +422,109 @@ class NexusMessaging {
|
|
|
416
422
|
}
|
|
417
423
|
|
|
418
424
|
async handleMedia(messageData) {
|
|
419
|
-
|
|
425
|
+
await this._ensureMediaPersistence(messageData);
|
|
426
|
+
|
|
427
|
+
return await this._handleWithPipeline('media', 'onMedia', messageData, async (ctx) => {
|
|
428
|
+
return await this.handleMediaWithAssistant(ctx);
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
async handleMediaWithAssistant(messageData) {
|
|
433
|
+
try {
|
|
434
|
+
const { from, message } = this._extractAssistantInputs(messageData);
|
|
435
|
+
|
|
436
|
+
if (!from) {
|
|
437
|
+
console.warn('Unable to resolve sender for media message, skipping automatic reply.');
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const mediaDescriptor = (() => {
|
|
442
|
+
const media = Array.isArray(messageData.media) ? messageData.media[0] : messageData.media;
|
|
443
|
+
if (!media) return null;
|
|
444
|
+
if (typeof media.mediaType === 'string') return media.mediaType;
|
|
445
|
+
if (typeof media.type === 'string') return media.type;
|
|
446
|
+
if (typeof media.contentType === 'string') return media.contentType;
|
|
447
|
+
return null;
|
|
448
|
+
})();
|
|
449
|
+
|
|
450
|
+
const fallbackMessage = message && message.trim().length > 0
|
|
451
|
+
? message
|
|
452
|
+
: `Media received (${mediaDescriptor || 'attachment'})`;
|
|
453
|
+
|
|
454
|
+
const response = await replyAssistant(from, fallbackMessage);
|
|
455
|
+
|
|
456
|
+
if (response) {
|
|
457
|
+
await this.sendMessage({
|
|
458
|
+
to: from,
|
|
459
|
+
message: response
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
} catch (error) {
|
|
463
|
+
console.error('Error in handleMediaWithAssistant:', error);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
async _ensureMediaPersistence(messageData) {
|
|
468
|
+
try {
|
|
469
|
+
const raw = messageData?.raw;
|
|
470
|
+
if (!raw || raw.__nexusMediaProcessed) return;
|
|
471
|
+
|
|
472
|
+
const numMedia = parseInt(raw.NumMedia || '0', 10);
|
|
473
|
+
if (!numMedia || numMedia <= 0 || !raw.MediaUrl0) return;
|
|
474
|
+
|
|
475
|
+
const bucketName = runtimeConfig.get('AWS_S3_BUCKET_NAME') || process.env.AWS_S3_BUCKET_NAME;
|
|
476
|
+
if (!bucketName) {
|
|
477
|
+
console.warn('[NexusMessaging] AWS_S3_BUCKET_NAME not configured. Skipping media persistence.');
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const { processTwilioMediaMessage } = require('../helpers/twilioMediaProcessor');
|
|
482
|
+
const { logger } = require('../utils/logger');
|
|
483
|
+
const mediaItems = await processTwilioMediaMessage(raw, logger, bucketName);
|
|
484
|
+
|
|
485
|
+
if (!mediaItems || mediaItems.length === 0) {
|
|
486
|
+
console.warn('[NexusMessaging] Media processing returned no items for incoming message.');
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
raw.__nexusMediaProcessed = true;
|
|
491
|
+
|
|
492
|
+
const [primary, ...rest] = mediaItems;
|
|
493
|
+
const mediaPayload = rest.length > 0
|
|
494
|
+
? { ...primary, metadata: { ...(primary.metadata || {}), attachments: rest } }
|
|
495
|
+
: primary;
|
|
496
|
+
|
|
497
|
+
messageData.media = messageData.media || mediaPayload;
|
|
498
|
+
messageData.fileUrl = messageData.fileUrl || mediaPayload.metadata?.presignedUrl || null;
|
|
499
|
+
messageData.fileType = messageData.fileType || mediaPayload.mediaType;
|
|
500
|
+
messageData.caption = messageData.caption || primary.caption;
|
|
501
|
+
if (!messageData.message && messageData.caption) {
|
|
502
|
+
messageData.message = messageData.caption;
|
|
503
|
+
}
|
|
504
|
+
messageData.isMedia = true;
|
|
505
|
+
|
|
506
|
+
if (!this.messageStorage) {
|
|
507
|
+
const { convertTwilioToInternalFormat } = require('../helpers/twilioHelper');
|
|
508
|
+
const { getMessageValues, insertMessage } = require('../models/messageModel');
|
|
509
|
+
|
|
510
|
+
const messageObj = convertTwilioToInternalFormat(raw);
|
|
511
|
+
const values = getMessageValues(
|
|
512
|
+
messageObj,
|
|
513
|
+
messageData.message || messageData.caption || '',
|
|
514
|
+
null,
|
|
515
|
+
true
|
|
516
|
+
);
|
|
517
|
+
values.media = mediaPayload;
|
|
518
|
+
|
|
519
|
+
await insertMessage(values);
|
|
520
|
+
console.log('[NexusMessaging] Media message stored via legacy inserter', {
|
|
521
|
+
messageId: values.message_id,
|
|
522
|
+
numero: values.numero
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
} catch (error) {
|
|
526
|
+
console.error('[NexusMessaging] Failed to ensure media persistence:', error);
|
|
527
|
+
}
|
|
420
528
|
}
|
|
421
529
|
|
|
422
530
|
async handleCommand(messageData) {
|
|
@@ -120,6 +120,8 @@ class MongoStorage {
|
|
|
120
120
|
? { ...primary, metadata: { ...(primary.metadata || {}), attachments: rest } }
|
|
121
121
|
: primary;
|
|
122
122
|
|
|
123
|
+
rawMessage.__nexusMediaProcessed = true;
|
|
124
|
+
|
|
123
125
|
console.log('[MongoStorage] Media processed successfully', {
|
|
124
126
|
primaryType: mediaPayload.mediaType,
|
|
125
127
|
mediaCount: mediaItems.length,
|