@peopl-health/nexus 1.1.7 → 1.1.8
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/lib/adapters/TwilioProvider.js +19 -0
- package/lib/config/llmConfig.js +1 -2
- package/lib/index.js +2 -9
- package/lib/services/twilioService.js +56 -0
- package/lib/utils/dateUtils.js +26 -0
- package/package.json +1 -1
- package/lib/utils/AssistantManager.js +0 -218
- /package/lib/utils/{DefaultLLMProvider.js → defaultLLMProvider.js} +0 -0
- /package/lib/utils/{MessageParser.js → messageParser.js} +0 -0
|
@@ -113,6 +113,25 @@ class TwilioProvider extends MessageProvider {
|
|
|
113
113
|
const targetTime = new Date(sendTime);
|
|
114
114
|
return Math.max(0, targetTime.getTime() - now.getTime());
|
|
115
115
|
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* List templates from Twilio Content API
|
|
119
|
+
* @param {Object} options - Query options
|
|
120
|
+
* @returns {Promise<Array>} Array of templates
|
|
121
|
+
*/
|
|
122
|
+
async listTemplates(options = {}) {
|
|
123
|
+
if (!this.isConnected || !this.twilioClient) {
|
|
124
|
+
throw new Error('Twilio provider not initialized');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
const { limit = 50 } = options;
|
|
129
|
+
const templates = await this.twilioClient.content.v1.contents.list({ limit });
|
|
130
|
+
return templates;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
throw new Error(`Failed to list templates: ${error.message}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
116
135
|
}
|
|
117
136
|
|
|
118
137
|
module.exports = { TwilioProvider };
|
package/lib/config/llmConfig.js
CHANGED
package/lib/index.js
CHANGED
|
@@ -2,15 +2,8 @@ const { NexusMessaging } = require('./core/NexusMessaging');
|
|
|
2
2
|
const { TwilioProvider } = require('./adapters/TwilioProvider');
|
|
3
3
|
const { BaileysProvider } = require('./adapters/BaileysProvider');
|
|
4
4
|
const { MongoStorage } = require('./storage/MongoStorage');
|
|
5
|
-
const { MessageParser } = require('./utils/
|
|
6
|
-
const { DefaultLLMProvider } = require('./utils/
|
|
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');
|
|
5
|
+
const { MessageParser } = require('./utils/messageParser');
|
|
6
|
+
const { DefaultLLMProvider } = require('./utils/defaultLLMProvider');
|
|
14
7
|
|
|
15
8
|
/**
|
|
16
9
|
* Main Nexus class that orchestrates all components
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// TwilioService that connects to Nexus Twilio provider
|
|
2
|
+
let nexusProvider = null;
|
|
3
|
+
|
|
4
|
+
// Configure the Nexus provider
|
|
5
|
+
const configureNexusProvider = (provider) => {
|
|
6
|
+
nexusProvider = provider;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// Check if provider is configured and supports Twilio operations
|
|
10
|
+
const checkTwilioSupport = () => {
|
|
11
|
+
if (!nexusProvider) {
|
|
12
|
+
throw new Error('Nexus provider not configured. Call configureNexusProvider() first.');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!nexusProvider.listTemplates || typeof nexusProvider.listTemplates !== 'function') {
|
|
16
|
+
throw new Error('Twilio operations are only supported with Twilio provider');
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// TwilioService wrapper that delegates to Nexus provider
|
|
21
|
+
const TwilioService = {
|
|
22
|
+
async listTemplates(options = {}) {
|
|
23
|
+
checkTwilioSupport();
|
|
24
|
+
return await nexusProvider.listTemplates(options);
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
async getTemplate(sid) {
|
|
28
|
+
checkTwilioSupport();
|
|
29
|
+
return await nexusProvider.getTemplate(sid);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
async checkApprovalStatus(sid) {
|
|
33
|
+
checkTwilioSupport();
|
|
34
|
+
return await nexusProvider.checkApprovalStatus(sid);
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
async submitForApproval(contentSid, name, category) {
|
|
38
|
+
checkTwilioSupport();
|
|
39
|
+
return await nexusProvider.submitForApproval(contentSid, name, category);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
async deleteTemplate(sid) {
|
|
43
|
+
checkTwilioSupport();
|
|
44
|
+
return await nexusProvider.deleteTemplate(sid);
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
async createTemplate(templateData) {
|
|
48
|
+
checkTwilioSupport();
|
|
49
|
+
return await nexusProvider.createTemplate(templateData);
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
// Add any other Twilio operations as needed
|
|
53
|
+
configureNexusProvider
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
module.exports = TwilioService;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const moment = require('moment-timezone');
|
|
2
|
+
|
|
3
|
+
const ISO_DATE = 'YYYY-MM-DD';
|
|
4
|
+
|
|
5
|
+
const parseStartTime = (startTime) => {
|
|
6
|
+
return moment(startTime);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const addDays = (date, days) => {
|
|
10
|
+
return moment(date).add(days, 'days');
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const dateAndTimeFromStart = (startTime) => {
|
|
14
|
+
const momentTime = moment(startTime);
|
|
15
|
+
return {
|
|
16
|
+
date: momentTime.format(ISO_DATE),
|
|
17
|
+
time: momentTime.format('HH:mm')
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
module.exports = {
|
|
22
|
+
ISO_DATE,
|
|
23
|
+
parseStartTime,
|
|
24
|
+
addDays,
|
|
25
|
+
dateAndTimeFromStart
|
|
26
|
+
};
|
package/package.json
CHANGED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configurable assistant manager for handling AI interactions
|
|
3
|
-
*/
|
|
4
|
-
class AssistantManager {
|
|
5
|
-
constructor(config = {}) {
|
|
6
|
-
this.config = config;
|
|
7
|
-
this.assistants = new Map();
|
|
8
|
-
this.llmClient = null;
|
|
9
|
-
this.handlers = {
|
|
10
|
-
onRequiresAction: null,
|
|
11
|
-
onCompleted: null,
|
|
12
|
-
onFailed: null
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Initialize with LLM client (OpenAI, etc.)
|
|
18
|
-
* @param {Object} llmClient - LLM client instance
|
|
19
|
-
*/
|
|
20
|
-
setLLMClient(llmClient) {
|
|
21
|
-
this.llmClient = llmClient;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Register assistant configurations
|
|
26
|
-
* @param {Object} assistantConfigs - Map of assistant IDs to configurations
|
|
27
|
-
*/
|
|
28
|
-
registerAssistants(assistantConfigs) {
|
|
29
|
-
Object.entries(assistantConfigs).forEach(([key, config]) => {
|
|
30
|
-
this.assistants.set(key, config);
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Set event handlers for assistant interactions
|
|
36
|
-
* @param {Object} handlers - Handler functions
|
|
37
|
-
*/
|
|
38
|
-
setHandlers(handlers) {
|
|
39
|
-
this.handlers = { ...this.handlers, ...handlers };
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Create a new thread for a conversation
|
|
44
|
-
* @param {string} code - User/conversation identifier
|
|
45
|
-
* @param {string} assistantId - Assistant ID to use
|
|
46
|
-
* @param {Array} initialMessages - Initial messages for context
|
|
47
|
-
*/
|
|
48
|
-
async createThread(code, assistantId, initialMessages = []) {
|
|
49
|
-
if (!this.llmClient) {
|
|
50
|
-
throw new Error('LLM client not configured');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
const thread = await this.llmClient.beta.threads.create();
|
|
55
|
-
|
|
56
|
-
// Add initial messages if provided
|
|
57
|
-
for (const message of initialMessages) {
|
|
58
|
-
await this.llmClient.beta.threads.messages.create(
|
|
59
|
-
thread.id,
|
|
60
|
-
{ role: 'assistant', content: message }
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
code,
|
|
66
|
-
assistantId,
|
|
67
|
-
threadId: thread.id,
|
|
68
|
-
active: true,
|
|
69
|
-
createdAt: new Date()
|
|
70
|
-
};
|
|
71
|
-
} catch (error) {
|
|
72
|
-
throw new Error(`Failed to create thread: ${error.message}`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Send message to assistant and get response
|
|
78
|
-
* @param {Object} threadData - Thread information
|
|
79
|
-
* @param {string} message - User message
|
|
80
|
-
* @param {Object} runOptions - Additional run options
|
|
81
|
-
*/
|
|
82
|
-
async sendMessage(threadData, message, runOptions = {}) {
|
|
83
|
-
if (!this.llmClient) {
|
|
84
|
-
throw new Error('LLM client not configured');
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
// Add user message to thread
|
|
89
|
-
await this.llmClient.beta.threads.messages.create(
|
|
90
|
-
threadData.threadId,
|
|
91
|
-
{ role: 'user', content: message }
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
// Create run
|
|
95
|
-
const run = await this.llmClient.beta.threads.runs.create(
|
|
96
|
-
threadData.threadId,
|
|
97
|
-
{
|
|
98
|
-
assistant_id: threadData.assistantId,
|
|
99
|
-
...runOptions
|
|
100
|
-
}
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
// Wait for completion and handle actions
|
|
104
|
-
const result = await this.waitForCompletion(threadData.threadId, run.id);
|
|
105
|
-
|
|
106
|
-
if (result.status === 'completed') {
|
|
107
|
-
const messages = await this.llmClient.beta.threads.messages.list(
|
|
108
|
-
threadData.threadId,
|
|
109
|
-
{ run_id: run.id }
|
|
110
|
-
);
|
|
111
|
-
return messages.data[0]?.content[0]?.text?.value || '';
|
|
112
|
-
} else if (result.status === 'requires_action') {
|
|
113
|
-
if (this.handlers.onRequiresAction) {
|
|
114
|
-
return await this.handlers.onRequiresAction(result, threadData);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return null;
|
|
119
|
-
} catch (error) {
|
|
120
|
-
throw new Error(`Assistant interaction failed: ${error.message}`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Wait for run completion and handle different statuses
|
|
126
|
-
* @param {string} threadId - Thread ID
|
|
127
|
-
* @param {string} runId - Run ID
|
|
128
|
-
*/
|
|
129
|
-
async waitForCompletion(threadId, runId) {
|
|
130
|
-
const maxAttempts = 30;
|
|
131
|
-
let attempts = 0;
|
|
132
|
-
|
|
133
|
-
while (attempts < maxAttempts) {
|
|
134
|
-
const run = await this.llmClient.beta.threads.runs.retrieve(threadId, runId);
|
|
135
|
-
|
|
136
|
-
if (run.status === 'completed') {
|
|
137
|
-
return { status: 'completed', run };
|
|
138
|
-
} else if (run.status === 'requires_action') {
|
|
139
|
-
return { status: 'requires_action', run };
|
|
140
|
-
} else if (run.status === 'failed' || run.status === 'cancelled' || run.status === 'expired') {
|
|
141
|
-
if (this.handlers.onFailed) {
|
|
142
|
-
await this.handlers.onFailed(run);
|
|
143
|
-
}
|
|
144
|
-
return { status: 'failed', run };
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Wait before next check
|
|
148
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
149
|
-
attempts++;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
throw new Error('Assistant run timeout');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Submit tool outputs for function calls
|
|
157
|
-
* @param {string} threadId - Thread ID
|
|
158
|
-
* @param {string} runId - Run ID
|
|
159
|
-
* @param {Array} toolOutputs - Tool outputs array
|
|
160
|
-
*/
|
|
161
|
-
async submitToolOutputs(threadId, runId, toolOutputs) {
|
|
162
|
-
if (!this.llmClient) {
|
|
163
|
-
throw new Error('LLM client not configured');
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
const run = await this.llmClient.beta.threads.runs.submitToolOutputs(
|
|
168
|
-
threadId,
|
|
169
|
-
runId,
|
|
170
|
-
{ tool_outputs: toolOutputs }
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
return await this.waitForCompletion(threadId, run.id);
|
|
174
|
-
} catch (error) {
|
|
175
|
-
throw new Error(`Failed to submit tool outputs: ${error.message}`);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Add instruction to existing thread
|
|
181
|
-
* @param {Object} threadData - Thread information
|
|
182
|
-
* @param {string} instruction - Additional instruction
|
|
183
|
-
*/
|
|
184
|
-
async addInstruction(threadData, instruction) {
|
|
185
|
-
if (!this.llmClient) {
|
|
186
|
-
throw new Error('LLM client not configured');
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
try {
|
|
190
|
-
const run = await this.llmClient.beta.threads.runs.create(
|
|
191
|
-
threadData.threadId,
|
|
192
|
-
{
|
|
193
|
-
assistant_id: threadData.assistantId,
|
|
194
|
-
additional_instructions: instruction,
|
|
195
|
-
additional_messages: [
|
|
196
|
-
{ role: 'user', content: instruction }
|
|
197
|
-
]
|
|
198
|
-
}
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
const result = await this.waitForCompletion(threadData.threadId, run.id);
|
|
202
|
-
|
|
203
|
-
if (result.status === 'completed') {
|
|
204
|
-
const messages = await this.llmClient.beta.threads.messages.list(
|
|
205
|
-
threadData.threadId,
|
|
206
|
-
{ run_id: run.id }
|
|
207
|
-
);
|
|
208
|
-
return messages.data[0]?.content[0]?.text?.value || '';
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return null;
|
|
212
|
-
} catch (error) {
|
|
213
|
-
throw new Error(`Failed to add instruction: ${error.message}`);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
module.exports = { AssistantManager };
|
|
File without changes
|
|
File without changes
|