@tiledesk/tiledesk-voice-twilio-connector 0.1.28 → 0.2.0-rc6

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.
Files changed (49) hide show
  1. package/LICENSE +179 -0
  2. package/README.md +515 -0
  3. package/index.js +7 -1562
  4. package/package.json +23 -21
  5. package/src/app.js +154 -0
  6. package/src/config/index.js +32 -0
  7. package/src/controllers/VoiceController.js +493 -0
  8. package/src/middlewares/httpLogger.js +43 -0
  9. package/src/models/KeyValueStore.js +78 -0
  10. package/src/routes/manageApp.js +298 -0
  11. package/src/routes/voice.js +22 -0
  12. package/src/services/AiService.js +219 -0
  13. package/src/services/AiService.sdk.js +367 -0
  14. package/src/services/IntegrationService.js +74 -0
  15. package/src/services/MessageService.js +139 -0
  16. package/src/services/README_SDK.md +107 -0
  17. package/src/services/SessionService.js +143 -0
  18. package/src/services/SpeechService.js +134 -0
  19. package/src/services/TiledeskMessageBuilder.js +135 -0
  20. package/src/services/TwilioService.js +129 -0
  21. package/src/services/UploadService.js +78 -0
  22. package/src/services/channels/TiledeskChannel.js +268 -0
  23. package/{tiledesk → src/services/channels}/VoiceChannel.js +20 -59
  24. package/src/services/clients/TiledeskSubscriptionClient.js +78 -0
  25. package/src/services/index.js +45 -0
  26. package/src/services/translators/TiledeskTwilioTranslator.js +514 -0
  27. package/src/utils/fileUtils.js +24 -0
  28. package/src/utils/logger.js +32 -0
  29. package/{tiledesk → src/utils}/utils-message.js +6 -21
  30. package/logs/app.log +0 -3082
  31. package/routes/manageApp.js +0 -419
  32. package/tiledesk/KVBaseMongo.js +0 -101
  33. package/tiledesk/TiledeskChannel.js +0 -363
  34. package/tiledesk/TiledeskSubscriptionClient.js +0 -135
  35. package/tiledesk/TiledeskTwilioTranslator.js +0 -707
  36. package/tiledesk/fileUtils.js +0 -55
  37. package/tiledesk/services/AiService.js +0 -230
  38. package/tiledesk/services/IntegrationService.js +0 -81
  39. package/tiledesk/services/UploadService.js +0 -88
  40. /package/{winston.js → src/config/logger.js} +0 -0
  41. /package/{tiledesk → src}/services/voiceEventEmitter.js +0 -0
  42. /package/{template → src/template}/configure.html +0 -0
  43. /package/{template → src/template}/css/configure.css +0 -0
  44. /package/{template → src/template}/css/error.css +0 -0
  45. /package/{template → src/template}/css/style.css +0 -0
  46. /package/{template → src/template}/error.html +0 -0
  47. /package/{tiledesk → src/utils}/constants.js +0 -0
  48. /package/{tiledesk → src/utils}/errors.js +0 -0
  49. /package/{tiledesk → src/utils}/utils.js +0 -0
package/package.json CHANGED
@@ -1,48 +1,50 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-voice-twilio-connector",
3
- "version": "0.1.28",
3
+ "version": "0.2.0-rc6",
4
4
  "description": "Tiledesk VOICE Twilio connector",
5
5
  "license": "MIT",
6
6
  "author": "Gabriele Panico",
7
7
  "main": "index.js",
8
+ "files": [
9
+ "index.js",
10
+ "src/**/*",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
8
14
  "repository": {
9
15
  "type": "git",
10
16
  "url": "https://github.com/Tiledesk/tiledesk-voice-twilio-connector"
11
17
  },
12
18
  "scripts": {
13
- "test": "mocha",
19
+ "test": "echo \"Error: no test specified\" && exit 1",
14
20
  "start": "node index.js"
15
21
  },
16
- "engines": {
17
- "node": ">=18.0.0",
18
- "npm": ">=8.15.0"
19
- },
20
- "keywords": [],
21
22
  "dependencies": {
22
23
  "app-root-path": "^3.0.0",
23
24
  "axios": "^0.27.2",
24
- "axios-retry": "^4.5.0",
25
- "bluebird": "^3.7.2",
26
25
  "body-parser": "^1.20.2",
27
- "dotenv": "^16.0.2",
28
- "express": "^4.18.1",
26
+ "dotenv": "^16.4.5",
27
+ "elevenlabs": "^1.59.0",
28
+ "express": "^4.19.2",
29
29
  "form-data": "^4.0.0",
30
30
  "handlebars": "^4.7.7",
31
- "jobs-worker-queued": "^0.0.5",
32
31
  "jsonwebtoken": "^8.5.1",
33
32
  "mongodb": "^3.5.5",
34
- "mongoose": "^6.5.0",
35
- "multer": "^1.4.5-lts.1",
36
33
  "redis": "^4.6.13",
37
- "redis-lock": "^1.0.0",
38
- "redlock": "^4.2.0",
39
34
  "remove-markdown": "^0.6.2",
40
35
  "twilio": "^5.2.1",
41
- "uuid": "^8.3.2",
42
36
  "winston": "^3.3.3",
43
- "xmlbuilder": "^15.1.1"
37
+ "uuid": "^9.0.0"
38
+ },
39
+ "engines": {
40
+ "node": ">=18.0.0",
41
+ "npm": ">=8.15.0"
44
42
  },
45
- "devDependencies": {
46
- "mocha": "^8.2.1"
47
- }
43
+ "keywords": [
44
+ "node",
45
+ "tiledesk",
46
+ "twilio",
47
+ "voice",
48
+ "connector"
49
+ ]
48
50
  }
package/src/app.js ADDED
@@ -0,0 +1,154 @@
1
+ const express = require('express');
2
+ const config = require('./config');
3
+ const logger = require('./utils/logger');
4
+ const redis = require('redis');
5
+
6
+ // Services
7
+ const { VoiceChannel } = require('./services/channels/VoiceChannel');
8
+ // Use SDK version (with automatic HTTP fallback if SDK not available)
9
+ const { AiService } = require('./services/AiService.sdk');
10
+ // const { AiService } = require('./services/AiService');
11
+ const { IntegrationService } = require('./services/IntegrationService');
12
+ const { UploadService } = require('./services/UploadService');
13
+ const { KVBaseMongo } = require('./models/KeyValueStore');
14
+
15
+ // Routes
16
+ const voiceRoutes = require('./routes/voice');
17
+ const manageApp = require('./routes/manageApp');
18
+ const httpLogger = require('./middlewares/httpLogger');
19
+
20
+ const app = express();
21
+ app.use(express.json());
22
+ app.use(express.urlencoded({ extended: true }));
23
+ app.use(httpLogger);
24
+
25
+ app.get('/health-check', (req, res) => {
26
+ res.send("(VOICE) Health check passed");
27
+ });
28
+
29
+ /**
30
+ * Merge configuration from options parameter with config (which already reads from process.env)
31
+ * Options parameter takes priority over config (which contains process.env values)
32
+ */
33
+ function mergeConfig(options = {}) {
34
+ return {
35
+ port: options.PORT || config.port || 3000,
36
+ api: {
37
+ url: options.API_URL || config.api.url,
38
+ baseUrl: options.BASE_URL || config.api.baseUrl,
39
+ baseFileUrl: options.BASE_FILE_URL || config.api.baseFileUrl
40
+ },
41
+ database: {
42
+ mongodbUri: options.MONGODB_URI || config.database.mongodbUri
43
+ },
44
+ redis: {
45
+ host: options.REDIS_HOST || config.redis.host,
46
+ port: options.REDIS_PORT || config.redis.port,
47
+ password: options.REDIS_PASSWORD || config.redis.password
48
+ },
49
+ ai: {
50
+ openaiEndpoint: options.OPENAI_ENDPOINT || config.ai.openaiEndpoint,
51
+ elevenlabsEndpoint: options.ELEVENLABS_ENDPOINT || config.ai.elevenlabsEndpoint || "https://api.elevenlabs.io",
52
+ gptKey: options.GPT_KEY || config.ai.gptKey,
53
+ useElevenLabsSDK: options.USE_ELEVENLABS_SDK !== undefined
54
+ ? (options.USE_ELEVENLABS_SDK === 'true' || options.USE_ELEVENLABS_SDK === '1' || options.USE_ELEVENLABS_SDK === true)
55
+ : config.ai.useElevenLabsSDK
56
+ },
57
+ app: {
58
+ brandName: options.BRAND_NAME || config.app.brandName,
59
+ basePoolingDelay: options.BASE_POOLING_DELAY || config.app.basePoolingDelay,
60
+ maxPollingTime: options.MAX_POLLING_TIME || config.app.maxPollingTime,
61
+ logLevel: options.VOICE_TWILIO_LOG || config.app.logLevel || "info"
62
+ }
63
+ };
64
+ }
65
+
66
+ async function startServer(options = {}) {
67
+ try {
68
+ // Merge configuration: options parameter takes priority over process.env
69
+ const mergedConfig = mergeConfig(options);
70
+
71
+ // Redis
72
+ let redisClient;
73
+ if (mergedConfig.redis.host && mergedConfig.redis.port) {
74
+ logger.info("Redis config: " + JSON.stringify(mergedConfig.redis));
75
+ redisClient = redis.createClient({
76
+ url: mergedConfig.redis.password ? `redis://:${mergedConfig.redis.password}@${mergedConfig.redis.host}:${mergedConfig.redis.port}` : `redis://${mergedConfig.redis.host}:${mergedConfig.redis.port}`
77
+ });
78
+ await redisClient.connect();
79
+ logger.info("Redis connected");
80
+ } else {
81
+ logger.error("Missing redis parameters");
82
+ }
83
+
84
+ // Mongo - Reuse existing connection if provided, otherwise create new one
85
+ const db = new KVBaseMongo('kvstore');
86
+ if (options.dbconnection) {
87
+ await db.reuseConnection(options.dbconnection);
88
+ logger.debug("KVBaseMongo reused existing db connection");
89
+ } else {
90
+ if (!mergedConfig.database.mongodbUri) {
91
+ throw new Error("MONGODB_URI is required when dbconnection is not provided");
92
+ }
93
+ await db.connect(mergedConfig.database.mongodbUri);
94
+ logger.info("KVBaseMongo successfully connected.");
95
+ }
96
+
97
+ // Services
98
+ const voiceChannel = new VoiceChannel({
99
+ BASE_POOLING_DELAY: mergedConfig.app.basePoolingDelay,
100
+ redis_client: redisClient,
101
+ });
102
+
103
+ // Use SDK version (with automatic HTTP fallback if SDK not available)
104
+ const useSDK = mergedConfig.ai.useElevenLabsSDK;
105
+
106
+ if (useSDK) {
107
+ logger.info("Using ElevenLabs SDK implementation (with HTTP fallback if needed)");
108
+ } else {
109
+ logger.info("Using ElevenLabs HTTP implementation (SDK disabled via config)");
110
+ }
111
+
112
+ const aiService = new AiService({
113
+ OPENAI_ENDPOINT: mergedConfig.ai.openaiEndpoint,
114
+ ELEVENLABS_ENDPOINT: mergedConfig.ai.elevenlabsEndpoint,
115
+ API_URL: mergedConfig.api.url,
116
+ useSDK: useSDK // Pass flag to service to enable/disable SDK usage
117
+ });
118
+
119
+ const integrationService = new IntegrationService({
120
+ API_URL: mergedConfig.api.url,
121
+ });
122
+
123
+ const uploadService = new UploadService({
124
+ API_URL: mergedConfig.api.baseFileUrl,
125
+ });
126
+
127
+ const services = {
128
+ voiceChannel,
129
+ aiService,
130
+ integrationService,
131
+ uploadService,
132
+ db,
133
+ redisClient,
134
+ config: {
135
+ API_URL: mergedConfig.api.url,
136
+ BASE_URL: mergedConfig.api.baseUrl,
137
+ GPT_KEY: mergedConfig.ai.gptKey,
138
+ MAX_POLLING_TIME: mergedConfig.app.maxPollingTime
139
+ }
140
+ };
141
+
142
+ app.use('/', voiceRoutes(services));
143
+ app.use('/manage', manageApp(services));
144
+
145
+ app.listen(mergedConfig.port, "0.0.0.0", () => {
146
+ logger.info("VOICE connector listening on port: " + mergedConfig.port);
147
+ });
148
+
149
+ } catch (err) {
150
+ logger.error("Unable to start tiledesk-voice-twilio-connector.", err);
151
+ }
152
+ }
153
+
154
+ module.exports = { app, startServer };
@@ -0,0 +1,32 @@
1
+ require('dotenv').config();
2
+
3
+ const config = {
4
+ port: process.env.PORT || 3000,
5
+ api: {
6
+ url: process.env.API_URL,
7
+ baseUrl: process.env.BASE_URL,
8
+ baseFileUrl: process.env.BASE_FILE_URL
9
+ },
10
+ database: {
11
+ mongodbUri: process.env.MONGODB_URI
12
+ },
13
+ redis: {
14
+ host: process.env.REDIS_HOST,
15
+ port: process.env.REDIS_PORT,
16
+ password: process.env.REDIS_PASSWORD
17
+ },
18
+ ai: {
19
+ openaiEndpoint: process.env.OPENAI_ENDPOINT,
20
+ elevenlabsEndpoint: process.env.ELEVENLABS_ENDPOINT || "https://api.elevenlabs.io",
21
+ gptKey: process.env.GPT_KEY,
22
+ useElevenLabsSDK: process.env.USE_ELEVENLABS_SDK === 'true' || process.env.USE_ELEVENLABS_SDK === '1'
23
+ },
24
+ app: {
25
+ brandName: process.env.BRAND_NAME,
26
+ basePoolingDelay: process.env.BASE_POOLING_DELAY,
27
+ maxPollingTime: process.env.MAX_POLLING_TIME,
28
+ logLevel: process.env.VOICE_TWILIO_LOG || "info"
29
+ }
30
+ };
31
+
32
+ module.exports = config;