@peopl-health/nexus 1.0.2
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.
- package/CHANGELOG.md +55 -0
- package/LICENSE +21 -0
- package/MIGRATION_GUIDE.md +388 -0
- package/README.md +532 -0
- package/examples/.env.example +24 -0
- package/examples/assistants/BaseAssistant.js +242 -0
- package/examples/assistants/ExampleAssistant.js +111 -0
- package/examples/assistants/index.js +7 -0
- package/examples/basic-usage.js +109 -0
- package/examples/consumer-server.js +206 -0
- package/lib/adapters/BaileysProvider.js +180 -0
- package/lib/adapters/TwilioProvider.js +118 -0
- package/lib/adapters/index.js +7 -0
- package/lib/core/MessageProvider.js +71 -0
- package/lib/core/NexusMessaging.js +231 -0
- package/lib/core/index.js +7 -0
- package/lib/index.d.ts +276 -0
- package/lib/index.js +204 -0
- package/lib/models/index.js +9 -0
- package/lib/models/messageModel.js +91 -0
- package/lib/models/threadModel.js +20 -0
- package/lib/storage/MongoStorage.js +183 -0
- package/lib/storage/index.js +5 -0
- package/lib/utils/AssistantManager.js +218 -0
- package/lib/utils/DefaultLLMProvider.js +22 -0
- package/lib/utils/MessageParser.js +249 -0
- package/lib/utils/index.js +22 -0
- package/lib/utils/logger.js +22 -0
- package/lib/utils/mongoAuthConfig.js +139 -0
- package/lib/utils/twilioHelper.js +77 -0
- package/lib/utils/whatsappHelper.js +68 -0
- package/package.json +82 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
declare module '@peopl/nexus' {
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import mongoose from 'mongoose';
|
|
4
|
+
|
|
5
|
+
// Core Types
|
|
6
|
+
export interface MessageData {
|
|
7
|
+
id?: string;
|
|
8
|
+
from: string;
|
|
9
|
+
to?: string;
|
|
10
|
+
message?: string;
|
|
11
|
+
fileUrl?: string;
|
|
12
|
+
fileType?: 'text' | 'image' | 'document' | 'audio' | 'video';
|
|
13
|
+
contentSid?: string;
|
|
14
|
+
variables?: Record<string, string>;
|
|
15
|
+
timestamp?: Date;
|
|
16
|
+
interactive?: InteractiveData;
|
|
17
|
+
media?: MediaData;
|
|
18
|
+
command?: CommandData;
|
|
19
|
+
keyword?: string;
|
|
20
|
+
flow?: string;
|
|
21
|
+
type?: 'message' | 'interactive' | 'media' | 'command' | 'keyword' | 'flow';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface InteractiveData {
|
|
25
|
+
type: 'button' | 'list' | 'flow';
|
|
26
|
+
payload?: string;
|
|
27
|
+
title?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
data?: any;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface MediaData {
|
|
33
|
+
url?: string;
|
|
34
|
+
contentType?: string;
|
|
35
|
+
filename?: string;
|
|
36
|
+
type?: string;
|
|
37
|
+
data?: any;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface CommandData {
|
|
41
|
+
prefix: string;
|
|
42
|
+
command: string;
|
|
43
|
+
args: string[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ScheduledMessage extends MessageData {
|
|
47
|
+
sendTime: string | Date;
|
|
48
|
+
timeZone?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface ThreadData {
|
|
52
|
+
code: string;
|
|
53
|
+
assistantId: string;
|
|
54
|
+
threadId: string;
|
|
55
|
+
patientId?: string;
|
|
56
|
+
runId?: string;
|
|
57
|
+
nombre?: string;
|
|
58
|
+
active: boolean;
|
|
59
|
+
stopped?: boolean;
|
|
60
|
+
nextSid?: string[];
|
|
61
|
+
createdAt: Date;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Provider Configurations
|
|
65
|
+
export interface TwilioConfig {
|
|
66
|
+
accountSid: string;
|
|
67
|
+
authToken: string;
|
|
68
|
+
whatsappNumber: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface BaileysConfig {
|
|
72
|
+
authState?: string;
|
|
73
|
+
mongoUri?: string;
|
|
74
|
+
userDbMongo?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface StorageConfig {
|
|
78
|
+
mongoUri: string;
|
|
79
|
+
dbName: string;
|
|
80
|
+
collections?: {
|
|
81
|
+
messages?: string;
|
|
82
|
+
interactions?: string;
|
|
83
|
+
threads?: string;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface AssistantConfig {
|
|
88
|
+
llmClient?: any;
|
|
89
|
+
assistants?: Record<string, string>;
|
|
90
|
+
handlers?: {
|
|
91
|
+
onRequiresAction?: (result: any, threadData: ThreadData) => Promise<any>;
|
|
92
|
+
onCompleted?: (result: any) => Promise<void>;
|
|
93
|
+
onFailed?: (result: any) => Promise<void>;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface ParserConfig {
|
|
98
|
+
commandPrefixes?: string[];
|
|
99
|
+
keywords?: (string | { pattern: string; flags?: string })[];
|
|
100
|
+
flowTriggers?: (string | { pattern: string; flags?: string })[];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Handler Types
|
|
104
|
+
export type MessageHandler = (messageData: MessageData, nexus: Nexus) => Promise<void>;
|
|
105
|
+
export type InteractiveHandler = (messageData: MessageData, nexus: Nexus) => Promise<void>;
|
|
106
|
+
export type MediaHandler = (messageData: MessageData, nexus: Nexus) => Promise<void>;
|
|
107
|
+
export type CommandHandler = (messageData: MessageData, nexus: Nexus) => Promise<void>;
|
|
108
|
+
export type KeywordHandler = (messageData: MessageData, nexus: Nexus) => Promise<void>;
|
|
109
|
+
export type FlowHandler = (messageData: MessageData, nexus: Nexus) => Promise<void>;
|
|
110
|
+
|
|
111
|
+
export interface MessageHandlers {
|
|
112
|
+
onMessage?: MessageHandler;
|
|
113
|
+
onInteractive?: InteractiveHandler;
|
|
114
|
+
onMedia?: MediaHandler;
|
|
115
|
+
onCommand?: CommandHandler;
|
|
116
|
+
onKeyword?: KeywordHandler;
|
|
117
|
+
onFlow?: FlowHandler;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Core Classes
|
|
121
|
+
export abstract class MessageProvider {
|
|
122
|
+
constructor(config: any);
|
|
123
|
+
abstract initialize(): Promise<void>;
|
|
124
|
+
abstract sendMessage(messageData: MessageData): Promise<any>;
|
|
125
|
+
abstract sendScheduledMessage(scheduledMessage: ScheduledMessage): Promise<void>;
|
|
126
|
+
abstract getConnectionStatus(): boolean;
|
|
127
|
+
abstract disconnect(): Promise<void>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export class TwilioProvider extends MessageProvider {
|
|
131
|
+
constructor(config: TwilioConfig);
|
|
132
|
+
initialize(): Promise<void>;
|
|
133
|
+
sendMessage(messageData: MessageData): Promise<any>;
|
|
134
|
+
sendScheduledMessage(scheduledMessage: ScheduledMessage): Promise<void>;
|
|
135
|
+
getConnectionStatus(): boolean;
|
|
136
|
+
disconnect(): Promise<void>;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export class BaileysProvider extends MessageProvider {
|
|
140
|
+
constructor(config: BaileysConfig);
|
|
141
|
+
initialize(): Promise<void>;
|
|
142
|
+
sendMessage(messageData: MessageData): Promise<any>;
|
|
143
|
+
sendScheduledMessage(scheduledMessage: ScheduledMessage): Promise<void>;
|
|
144
|
+
getConnectionStatus(): boolean;
|
|
145
|
+
disconnect(): Promise<void>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export class NexusMessaging {
|
|
149
|
+
constructor(config?: any);
|
|
150
|
+
initializeProvider(providerType: 'twilio' | 'baileys', providerConfig: TwilioConfig | BaileysConfig): Promise<void>;
|
|
151
|
+
setMessageStorage(storage: any): void;
|
|
152
|
+
setHandlers(handlers: MessageHandlers): void;
|
|
153
|
+
sendMessage(messageData: MessageData): Promise<any>;
|
|
154
|
+
sendScheduledMessage(scheduledMessage: ScheduledMessage): Promise<void>;
|
|
155
|
+
processIncomingMessage(messageData: MessageData): Promise<any>;
|
|
156
|
+
isConnected(): boolean;
|
|
157
|
+
disconnect(): Promise<void>;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export class MongoStorage {
|
|
161
|
+
constructor(config: StorageConfig);
|
|
162
|
+
connect(): Promise<void>;
|
|
163
|
+
saveMessage(messageData: MessageData): Promise<any>;
|
|
164
|
+
saveInteractive(interactionData: any): Promise<any>;
|
|
165
|
+
getMessages(numero: string, limit?: number): Promise<any[]>;
|
|
166
|
+
getThread(code: string): Promise<ThreadData | null>;
|
|
167
|
+
createThread(threadData: ThreadData): Promise<ThreadData>;
|
|
168
|
+
updateThread(code: string, updateData: Partial<ThreadData>): Promise<ThreadData | null>;
|
|
169
|
+
disconnect(): Promise<void>;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export class AssistantManager {
|
|
173
|
+
constructor(config?: AssistantConfig);
|
|
174
|
+
setLLMClient(llmClient: any): void;
|
|
175
|
+
registerAssistants(assistantConfigs: Record<string, string>): void;
|
|
176
|
+
setHandlers(handlers: AssistantConfig['handlers']): void;
|
|
177
|
+
createThread(code: string, assistantId: string, initialMessages?: string[]): Promise<ThreadData>;
|
|
178
|
+
sendMessage(threadData: ThreadData, message: string, runOptions?: any): Promise<string | null>;
|
|
179
|
+
submitToolOutputs(threadId: string, runId: string, toolOutputs: any[]): Promise<any>;
|
|
180
|
+
addInstruction(threadData: ThreadData, instruction: string): Promise<string | null>;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export class MessageParser {
|
|
184
|
+
constructor(config?: ParserConfig);
|
|
185
|
+
parseMessage(rawMessage: any): MessageData;
|
|
186
|
+
updateConfig(newConfig: ParserConfig): void;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Main Nexus Class
|
|
190
|
+
export interface NexusConfig {
|
|
191
|
+
messaging?: any;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface InitializeOptions {
|
|
195
|
+
provider?: 'twilio' | 'baileys';
|
|
196
|
+
providerConfig?: TwilioConfig | BaileysConfig;
|
|
197
|
+
storage?: 'mongo';
|
|
198
|
+
storageConfig?: StorageConfig;
|
|
199
|
+
assistant?: AssistantConfig;
|
|
200
|
+
parser?: boolean;
|
|
201
|
+
parserConfig?: ParserConfig;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export class Nexus {
|
|
205
|
+
constructor(config?: NexusConfig);
|
|
206
|
+
initialize(options?: InitializeOptions): Promise<void>;
|
|
207
|
+
setHandlers(handlers: MessageHandlers): void;
|
|
208
|
+
sendMessage(messageData: MessageData): Promise<any>;
|
|
209
|
+
sendScheduledMessage(scheduledMessage: ScheduledMessage): Promise<void>;
|
|
210
|
+
processMessage(rawMessage: any): Promise<any>;
|
|
211
|
+
createAssistantThread(code: string, assistantId: string, initialMessages?: string[]): Promise<ThreadData>;
|
|
212
|
+
sendToAssistant(code: string, message: string, runOptions?: any): Promise<string | null>;
|
|
213
|
+
isConnected(): boolean;
|
|
214
|
+
disconnect(): Promise<void>;
|
|
215
|
+
getMessaging(): NexusMessaging;
|
|
216
|
+
getStorage(): MongoStorage | null;
|
|
217
|
+
getAssistantManager(): AssistantManager | null;
|
|
218
|
+
getMessageParser(): MessageParser | null;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Utility Functions
|
|
222
|
+
export function createLogger(config?: any): any;
|
|
223
|
+
export function delay(ms: number): Promise<void>;
|
|
224
|
+
export function formatCode(codeBase: string): string;
|
|
225
|
+
export function calculateDelay(sendTime: string | Date, timeZone?: string): number;
|
|
226
|
+
export function ensureWhatsAppFormat(phoneNumber: string): string | null;
|
|
227
|
+
export function convertTwilioToInternalFormat(twilioMessage: any): any;
|
|
228
|
+
export function downloadMediaFromTwilio(mediaUrl: string, credentials: any): Promise<Buffer>;
|
|
229
|
+
export function getMediaTypeFromContentType(contentType: string): string;
|
|
230
|
+
export function extractTitle(message: any, mediaType: string): string | null;
|
|
231
|
+
export function useMongoDBAuthState(uri: string, dbName: string, sessionId: string): Promise<any>;
|
|
232
|
+
|
|
233
|
+
// Models
|
|
234
|
+
export const Message: mongoose.Model<any>;
|
|
235
|
+
export const Thread: mongoose.Model<any>;
|
|
236
|
+
export function getMessageValues(message: any, content: string, reply?: string, is_media?: boolean): any;
|
|
237
|
+
export function formatTimestamp(unixTimestamp: number): string;
|
|
238
|
+
|
|
239
|
+
// Module Exports
|
|
240
|
+
export const adapters: {
|
|
241
|
+
TwilioProvider: typeof TwilioProvider;
|
|
242
|
+
BaileysProvider: typeof BaileysProvider;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export const core: {
|
|
246
|
+
NexusMessaging: typeof NexusMessaging;
|
|
247
|
+
MessageProvider: typeof MessageProvider;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
export const storage: {
|
|
251
|
+
MongoStorage: typeof MongoStorage;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export const utils: {
|
|
255
|
+
AssistantManager: typeof AssistantManager;
|
|
256
|
+
MessageParser: typeof MessageParser;
|
|
257
|
+
logger: any;
|
|
258
|
+
createLogger: typeof createLogger;
|
|
259
|
+
delay: typeof delay;
|
|
260
|
+
formatCode: typeof formatCode;
|
|
261
|
+
calculateDelay: typeof calculateDelay;
|
|
262
|
+
useMongoDBAuthState: typeof useMongoDBAuthState;
|
|
263
|
+
convertTwilioToInternalFormat: typeof convertTwilioToInternalFormat;
|
|
264
|
+
downloadMediaFromTwilio: typeof downloadMediaFromTwilio;
|
|
265
|
+
getMediaTypeFromContentType: typeof getMediaTypeFromContentType;
|
|
266
|
+
extractTitle: typeof extractTitle;
|
|
267
|
+
ensureWhatsAppFormat: typeof ensureWhatsAppFormat;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
export const models: {
|
|
271
|
+
Message: typeof Message;
|
|
272
|
+
Thread: typeof Thread;
|
|
273
|
+
getMessageValues: typeof getMessageValues;
|
|
274
|
+
formatTimestamp: typeof formatTimestamp;
|
|
275
|
+
};
|
|
276
|
+
}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
const { NexusMessaging } = require('./core/NexusMessaging');
|
|
2
|
+
const { TwilioProvider } = require('./adapters/TwilioProvider');
|
|
3
|
+
const { BaileysProvider } = require('./adapters/BaileysProvider');
|
|
4
|
+
const { MongoStorage } = require('./storage/MongoStorage');
|
|
5
|
+
const { MessageParser } = require('./utils/MessageParser');
|
|
6
|
+
const { DefaultLLMProvider } = require('./utils/DefaultLLMProvider');
|
|
7
|
+
|
|
8
|
+
// Export individual components
|
|
9
|
+
const adapters = require('./adapters');
|
|
10
|
+
const core = require('./core');
|
|
11
|
+
const storage = require('./storage');
|
|
12
|
+
const utils = require('./utils');
|
|
13
|
+
const models = require('./models');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Main Nexus class that orchestrates all components
|
|
17
|
+
*/
|
|
18
|
+
class Nexus {
|
|
19
|
+
constructor(config = {}) {
|
|
20
|
+
this.config = config;
|
|
21
|
+
this.messaging = new NexusMessaging(config.messaging || {});
|
|
22
|
+
this.storage = null;
|
|
23
|
+
this.messageParser = null;
|
|
24
|
+
this.llmProvider = null;
|
|
25
|
+
this.isInitialized = false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Initialize Nexus with providers and storage
|
|
30
|
+
* @param {Object} options - Initialization options
|
|
31
|
+
* @param {string} [options.provider='twilio'] - Messaging provider ('twilio' or 'baileys')
|
|
32
|
+
* @param {Object} [options.providerConfig={}] - Provider-specific configuration
|
|
33
|
+
* @param {string} [options.storage='mongo'] - Storage type ('mongo' or false)
|
|
34
|
+
* @param {Object} [options.storageConfig={}] - Storage configuration
|
|
35
|
+
* @param {string} [options.parser='MessageParser'] - Message parser type
|
|
36
|
+
* @param {Object} [options.parserConfig={}] - Parser configuration
|
|
37
|
+
* @param {string} [options.llm='openai'] - LLM provider type
|
|
38
|
+
* @param {Object} [options.llmConfig={}] - LLM configuration
|
|
39
|
+
* @returns {Promise<void>}
|
|
40
|
+
*/
|
|
41
|
+
async initialize(options = {}) {
|
|
42
|
+
const {
|
|
43
|
+
provider = 'twilio',
|
|
44
|
+
providerConfig = {},
|
|
45
|
+
storage = 'mongo',
|
|
46
|
+
storageConfig = {},
|
|
47
|
+
parser = 'MessageParser',
|
|
48
|
+
parserConfig = {},
|
|
49
|
+
llm = 'openai',
|
|
50
|
+
llmConfig = {}
|
|
51
|
+
} = options;
|
|
52
|
+
|
|
53
|
+
// Initialize messaging provider
|
|
54
|
+
await this.messaging.initializeProvider(provider, providerConfig);
|
|
55
|
+
|
|
56
|
+
// Initialize storage if provided
|
|
57
|
+
if (storage === 'mongo') {
|
|
58
|
+
this.storage = new MongoStorage(storageConfig);
|
|
59
|
+
await this.storage.connect();
|
|
60
|
+
this.messaging.setMessageStorage(this.storage);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Initialize message parser if provided
|
|
64
|
+
if (parser !== false) {
|
|
65
|
+
this.messageParser = new MessageParser(parserConfig);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Initialize default LLM provider if requested
|
|
69
|
+
if (llm === 'openai') {
|
|
70
|
+
this.llmProvider = new DefaultLLMProvider(llmConfig);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this.isInitialized = true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Set message handlers for different types
|
|
78
|
+
* @param {Object} handlers - Handler functions
|
|
79
|
+
*/
|
|
80
|
+
setHandlers(handlers) {
|
|
81
|
+
this.messaging.setHandlers(handlers);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Send a message
|
|
86
|
+
* @param {Object} messageData - Message data
|
|
87
|
+
* @param {string} messageData.to - Recipient phone number
|
|
88
|
+
* @param {string} messageData.message - Message text
|
|
89
|
+
* @param {string} [messageData.fileUrl] - Optional file URL
|
|
90
|
+
* @param {string} [messageData.fileType] - File type
|
|
91
|
+
* @param {Object} [messageData.variables] - Template variables
|
|
92
|
+
* @param {string} [messageData.contentSid] - Template content SID
|
|
93
|
+
* @returns {Promise<Object>} Message result
|
|
94
|
+
*/
|
|
95
|
+
async sendMessage(messageData) {
|
|
96
|
+
if (!this.isInitialized) {
|
|
97
|
+
throw new Error('Nexus not initialized. Call initialize() first.');
|
|
98
|
+
}
|
|
99
|
+
return await this.messaging.sendMessage(messageData);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Send a scheduled message
|
|
104
|
+
* @param {Object} scheduledMessage - Scheduled message data
|
|
105
|
+
* @param {string} scheduledMessage.to - Recipient phone number
|
|
106
|
+
* @param {string} scheduledMessage.message - Message text
|
|
107
|
+
* @param {Date|string} scheduledMessage.sendAt - When to send the message
|
|
108
|
+
* @returns {Promise<Object>} Scheduled message result
|
|
109
|
+
*/
|
|
110
|
+
async sendScheduledMessage(scheduledMessage) {
|
|
111
|
+
if (!this.isInitialized) {
|
|
112
|
+
throw new Error('Nexus not initialized. Call initialize() first.');
|
|
113
|
+
}
|
|
114
|
+
return await this.messaging.sendScheduledMessage(scheduledMessage);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Process incoming message
|
|
119
|
+
* @param {Object} rawMessage - Raw message from webhook/event
|
|
120
|
+
* @returns {Promise<void>}
|
|
121
|
+
*/
|
|
122
|
+
async processMessage(rawMessage) {
|
|
123
|
+
if (!this.isInitialized) {
|
|
124
|
+
throw new Error('Nexus not initialized. Call initialize() first.');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let messageData = rawMessage;
|
|
128
|
+
|
|
129
|
+
// Parse message if parser is available
|
|
130
|
+
if (this.messageParser) {
|
|
131
|
+
messageData = this.messageParser.parseMessage(rawMessage);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return await this.messaging.processIncomingMessage(messageData);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get connection status
|
|
140
|
+
* @returns {boolean} Connection status
|
|
141
|
+
*/
|
|
142
|
+
isConnected() {
|
|
143
|
+
return this.messaging.isConnected();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Disconnect all services
|
|
148
|
+
* @returns {Promise<void>}
|
|
149
|
+
*/
|
|
150
|
+
async disconnect() {
|
|
151
|
+
await this.messaging.disconnect();
|
|
152
|
+
if (this.storage) {
|
|
153
|
+
await this.storage.disconnect();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Expose individual components for advanced usage
|
|
158
|
+
/**
|
|
159
|
+
* Get messaging instance
|
|
160
|
+
* @returns {NexusMessaging} Messaging instance
|
|
161
|
+
*/
|
|
162
|
+
getMessaging() {
|
|
163
|
+
return this.messaging;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get storage instance
|
|
168
|
+
* @returns {MongoStorage|null} Storage instance
|
|
169
|
+
*/
|
|
170
|
+
getStorage() {
|
|
171
|
+
return this.storage;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get message parser instance
|
|
176
|
+
* @returns {MessageParser|null} Parser instance
|
|
177
|
+
*/
|
|
178
|
+
getMessageParser() {
|
|
179
|
+
return this.messageParser;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Get LLM provider instance
|
|
184
|
+
* @returns {DefaultLLMProvider|null} LLM provider instance
|
|
185
|
+
*/
|
|
186
|
+
getLLMProvider() {
|
|
187
|
+
return this.llmProvider;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Export main class and individual components
|
|
192
|
+
module.exports = {
|
|
193
|
+
Nexus,
|
|
194
|
+
NexusMessaging,
|
|
195
|
+
TwilioProvider,
|
|
196
|
+
BaileysProvider,
|
|
197
|
+
MongoStorage,
|
|
198
|
+
MessageParser,
|
|
199
|
+
adapters,
|
|
200
|
+
core,
|
|
201
|
+
storage,
|
|
202
|
+
utils,
|
|
203
|
+
models
|
|
204
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
const moment = require('moment-timezone');
|
|
3
|
+
|
|
4
|
+
const messageSchema = new mongoose.Schema({
|
|
5
|
+
nombre_whatsapp: { type: String, required: true },
|
|
6
|
+
numero: { type: String, required: true },
|
|
7
|
+
body: { type: String, required: true },
|
|
8
|
+
timestamp: { type: String, required: true, default: Date.now },
|
|
9
|
+
message_id: { type: String, required: true },
|
|
10
|
+
is_group: { type: Boolean, required: true },
|
|
11
|
+
is_media: { type: Boolean, required: true },
|
|
12
|
+
group_id: { type: String, default: null },
|
|
13
|
+
reply_id: { type: String, default: null },
|
|
14
|
+
processed: { type: Boolean, default: false },
|
|
15
|
+
thread_id: { type: String, default: null },
|
|
16
|
+
assistant_id: { type: String, default: null },
|
|
17
|
+
content_sid: { type: String, default: null },
|
|
18
|
+
from_me: { type: Boolean, default: false },
|
|
19
|
+
media: {
|
|
20
|
+
contentType: { type: String, default: null },
|
|
21
|
+
bucketName: { type: String, default: null },
|
|
22
|
+
key: { type: String, default: null },
|
|
23
|
+
mediaType: { type: String, enum: ['image', 'video', 'audio', 'document', 'sticker', 'other'], default: null },
|
|
24
|
+
fileName: { type: String, default: null },
|
|
25
|
+
fileSize: { type: Number, default: null },
|
|
26
|
+
duration: { type: Number, default: null },
|
|
27
|
+
caption: { type: String, default: null },
|
|
28
|
+
thumbnail: { type: String, default: null },
|
|
29
|
+
metadata: { type: Object, default: null }
|
|
30
|
+
},
|
|
31
|
+
memoryType: {
|
|
32
|
+
type: String,
|
|
33
|
+
enum: ['active', 'archived'],
|
|
34
|
+
default: 'active',
|
|
35
|
+
index: true
|
|
36
|
+
},
|
|
37
|
+
read: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: false
|
|
40
|
+
}
|
|
41
|
+
}, { timestamps: true });
|
|
42
|
+
|
|
43
|
+
messageSchema.index({ message_id: 1, body: 1 }, { unique: true });
|
|
44
|
+
|
|
45
|
+
messageSchema.pre('save', function (next) {
|
|
46
|
+
if (this.timestamp) {
|
|
47
|
+
this.timestamp = moment.tz(this.timestamp, 'America/Mexico_City').toDate();
|
|
48
|
+
}
|
|
49
|
+
next();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const Message = mongoose.model('Message', messageSchema);
|
|
53
|
+
|
|
54
|
+
function formatTimestamp(unixTimestamp) {
|
|
55
|
+
const date = new Date(unixTimestamp * 1000);
|
|
56
|
+
return date.toLocaleString('sv-MX', {
|
|
57
|
+
timeZone: 'America/Mexico_City',
|
|
58
|
+
hour12: false,
|
|
59
|
+
}).replace(' ', 'T').slice(0, 19);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getMessageValues(message, content, reply, is_media) {
|
|
63
|
+
const nombre_whatsapp = message.pushName;
|
|
64
|
+
const numero = message.key.participant || message.key.remoteJid;
|
|
65
|
+
const body = content;
|
|
66
|
+
const timestamp = formatTimestamp(message.messageTimestamp);
|
|
67
|
+
const message_id = message.key.id;
|
|
68
|
+
const is_group = message.key.remoteJid.endsWith('@g.us');
|
|
69
|
+
const group_id = is_group ? message.key.remoteJid : null;
|
|
70
|
+
const reply_id = reply || null;
|
|
71
|
+
const from_me = message.key.fromMe;
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
nombre_whatsapp,
|
|
75
|
+
numero,
|
|
76
|
+
body,
|
|
77
|
+
timestamp,
|
|
78
|
+
message_id,
|
|
79
|
+
is_group,
|
|
80
|
+
is_media,
|
|
81
|
+
group_id,
|
|
82
|
+
reply_id,
|
|
83
|
+
from_me
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
Message,
|
|
89
|
+
getMessageValues,
|
|
90
|
+
formatTimestamp
|
|
91
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const threadSchema = new mongoose.Schema({
|
|
4
|
+
code: { type: String, required: true },
|
|
5
|
+
assistant_id: { type: String, required: true },
|
|
6
|
+
thread_id: { type: String, required: true },
|
|
7
|
+
patient_id: { type: String, default: null },
|
|
8
|
+
run_id: { type: String, default: null },
|
|
9
|
+
nombre: { type: String, default: null },
|
|
10
|
+
active: { type: Boolean, default: true },
|
|
11
|
+
stopped: { type: Boolean, default: false },
|
|
12
|
+
nextSid: { type: [String], default: [] }
|
|
13
|
+
}, { timestamps: true });
|
|
14
|
+
|
|
15
|
+
threadSchema.index({ code: 1, active: 1 });
|
|
16
|
+
threadSchema.index({ thread_id: 1 });
|
|
17
|
+
|
|
18
|
+
const Thread = mongoose.model('Thread', threadSchema);
|
|
19
|
+
|
|
20
|
+
module.exports = { Thread };
|