@tiledesk/tiledesk-server 2.4.52 → 2.4.53
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/app.js +2 -2
- package/models/faq.js +6 -0
- package/package.json +2 -2
- package/routes/faq.js +66 -23
- package/routes/faq_kb.js +7 -3
- package/routes/openai.js +112 -0
- package/routes/users.js +24 -0
- package/services/emailService.js +33 -0
- package/services/openaiService.js +41 -0
- package/template/email/redirectToDesktopEmail.html +304 -0
- package/template/email/redirectToDesktopEmail_new.html +604 -0
- package/test/faqRoute.js +116 -51
- package/test/openaiRoute.js +134 -0
- package/test/userRoute.js +63 -0
- package/routes/openai_kbs.js +0 -58
- package/test/openaiKbsRoute.js +0 -75
package/app.js
CHANGED
|
@@ -112,7 +112,7 @@ var jwtroute = require('./routes/jwt');
|
|
|
112
112
|
var key = require('./routes/key');
|
|
113
113
|
var widgets = require('./routes/widget');
|
|
114
114
|
var widgetsLoader = require('./routes/widgetLoader');
|
|
115
|
-
var
|
|
115
|
+
var openai = require('./routes/openai');
|
|
116
116
|
var kbsettings = require('./routes/kbsettings');
|
|
117
117
|
|
|
118
118
|
// var admin = require('./routes/admin');
|
|
@@ -551,7 +551,7 @@ app.use('/:projectid/emails',[passport.authenticate(['basic', 'jwt'], { session:
|
|
|
551
551
|
|
|
552
552
|
app.use('/:projectid/properties',[passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], property);
|
|
553
553
|
|
|
554
|
-
app.use('/:projectid/
|
|
554
|
+
app.use('/:projectid/openai', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent')], openai);
|
|
555
555
|
app.use('/:projectid/kbsettings', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], kbsettings);
|
|
556
556
|
|
|
557
557
|
|
package/models/faq.js
CHANGED
|
@@ -7,6 +7,12 @@ const uuidv4 = require('uuid/v4');
|
|
|
7
7
|
var defaultFullTextLanguage = process.env.DEFAULT_FULLTEXT_INDEX_LANGUAGE || "none";
|
|
8
8
|
|
|
9
9
|
var FaqSchema = new Schema({
|
|
10
|
+
_id: {
|
|
11
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
12
|
+
index: true,
|
|
13
|
+
required: true,
|
|
14
|
+
auto: true,
|
|
15
|
+
},
|
|
10
16
|
id_faq_kb: {
|
|
11
17
|
type: String,
|
|
12
18
|
index: true
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiledesk/tiledesk-server",
|
|
3
3
|
"description": "The Tiledesk server module",
|
|
4
|
-
"version": "2.4.
|
|
4
|
+
"version": "2.4.53",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"start": "node ./bin/www",
|
|
7
7
|
"pretest": "mongodb-runner start",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@tiledesk/tiledesk-kaleyra-proxy": "^0.1.7",
|
|
45
45
|
"@tiledesk/tiledesk-messenger-connector": "0.1.9",
|
|
46
46
|
"@tiledesk/tiledesk-rasa-connector": "^1.0.10",
|
|
47
|
-
"@tiledesk/tiledesk-tybot-connector": "^0.1.
|
|
47
|
+
"@tiledesk/tiledesk-tybot-connector": "^0.1.94",
|
|
48
48
|
"@tiledesk/tiledesk-whatsapp-connector": "^0.1.51",
|
|
49
49
|
"amqplib": "^0.5.5",
|
|
50
50
|
"app-root-path": "^3.0.0",
|
package/routes/faq.js
CHANGED
|
@@ -147,6 +147,7 @@ router.post('/', function (req, res) {
|
|
|
147
147
|
winston.debug('faq_kb ', faq_kb.toJSON());
|
|
148
148
|
|
|
149
149
|
var newFaq = new Faq({
|
|
150
|
+
_id: req.body._id,
|
|
150
151
|
id_faq_kb: req.body.id_faq_kb,
|
|
151
152
|
question: req.body.question,
|
|
152
153
|
answer: req.body.answer,
|
|
@@ -203,6 +204,8 @@ router.patch('/:faqid/attributes', function (req, res) {
|
|
|
203
204
|
let data = req.body;
|
|
204
205
|
winston.debug("data: ", data);
|
|
205
206
|
|
|
207
|
+
// aggiugnere controllo su intent_id qui
|
|
208
|
+
|
|
206
209
|
Faq.findById(req.params.faqid, function (err, updatedFaq) {
|
|
207
210
|
if (err) {
|
|
208
211
|
winston.error('Find Faq by id ERROR: ', err);
|
|
@@ -253,6 +256,7 @@ router.patch('/:faqid/attributes', function (req, res) {
|
|
|
253
256
|
router.put('/:faqid', function (req, res) {
|
|
254
257
|
|
|
255
258
|
winston.debug('UPDATE FAQ ', req.body);
|
|
259
|
+
let faqid = req.params.faqid;
|
|
256
260
|
|
|
257
261
|
var update = {};
|
|
258
262
|
|
|
@@ -296,45 +300,84 @@ router.put('/:faqid', function (req, res) {
|
|
|
296
300
|
update.attributes = req.body.attributes;
|
|
297
301
|
}
|
|
298
302
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
if (faqid.startsWith("intentId")) {
|
|
304
|
+
let intent_id = faqid.substring(8);
|
|
305
|
+
Faq.findOneAndUpdate({ intent_id: intent_id }, update, { new: true, upsert: true}, (err, updatedFaq) => {
|
|
306
|
+
if (err) {
|
|
307
|
+
if (err.code == 11000) {
|
|
308
|
+
return res.status(409).send({ success: false, msg: 'Duplicate intent_display_name.' });
|
|
309
|
+
} else {
|
|
310
|
+
return res.status(500).send({ success: false, msg: 'Error updating object.' });
|
|
311
|
+
}
|
|
305
312
|
}
|
|
306
|
-
}
|
|
307
313
|
|
|
308
|
-
|
|
309
|
-
|
|
314
|
+
faqBotEvent.emit('faq.update', updatedFaq);
|
|
315
|
+
faqBotEvent.emit('faq_train.update', updatedFaq.id_faq_kb);
|
|
316
|
+
|
|
317
|
+
res.status(200).send(updatedFaq);
|
|
318
|
+
})
|
|
310
319
|
|
|
311
|
-
|
|
320
|
+
} else {
|
|
321
|
+
Faq.findByIdAndUpdate(req.params.faqid, update, { new: true, upsert: true }, function (err, updatedFaq) {
|
|
322
|
+
if (err) {
|
|
323
|
+
if (err.code == 11000) {
|
|
324
|
+
return res.status(409).send({ success: false, msg: 'Duplicate intent_display_name.' });
|
|
325
|
+
} else {
|
|
326
|
+
return res.status(500).send({ success: false, msg: 'Error updating object.' });
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
faqBotEvent.emit('faq.update', updatedFaq);
|
|
331
|
+
faqBotEvent.emit('faq_train.update', updatedFaq.id_faq_kb);
|
|
332
|
+
|
|
333
|
+
res.status(200).send(updatedFaq);
|
|
334
|
+
// updateRemoteFaq(updatedFaq)
|
|
335
|
+
});
|
|
336
|
+
}
|
|
312
337
|
|
|
313
|
-
// updateRemoteFaq(updatedFaq)
|
|
314
|
-
});
|
|
315
338
|
});
|
|
316
339
|
|
|
317
340
|
|
|
318
341
|
// DELETE REMOTE AND LOCAL FAQ
|
|
319
342
|
router.delete('/:faqid', function (req, res) {
|
|
320
343
|
|
|
321
|
-
// deleteRemoteFaq(req.params.faqid)
|
|
322
344
|
winston.debug('DELETE FAQ - FAQ ID ', req.params.faqid);
|
|
323
345
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
faqBotEvent.emit('faq.delete', faq);
|
|
331
|
-
faqBotEvent.emit('faq_train.delete', faq.id_faq_kb);
|
|
346
|
+
let faqid = req.params.faqid;
|
|
347
|
+
|
|
348
|
+
if (faqid.startsWith("intentId")) {
|
|
349
|
+
console.log("faqid is an intent_id")
|
|
350
|
+
let intent_id = faqid.substring(8);
|
|
351
|
+
console.log("faq intent_id: ", intent_id);
|
|
332
352
|
|
|
333
|
-
|
|
353
|
+
Faq.findOneAndDelete({ intent_id: intent_id }, (err, faq) => {
|
|
354
|
+
if (err) {
|
|
355
|
+
return res.status(500).send({ success: false, msg: "Error deleting object." });
|
|
356
|
+
}
|
|
334
357
|
|
|
335
|
-
|
|
358
|
+
winston.debug('Deleted FAQ ', faq);
|
|
359
|
+
|
|
360
|
+
faqBotEvent.emit('faq.delete', faq);
|
|
361
|
+
faqBotEvent.emit('faq_train.delete', faq.id_faq_kb);
|
|
362
|
+
|
|
363
|
+
res.status(200).send(faq);
|
|
336
364
|
|
|
365
|
+
})
|
|
337
366
|
|
|
367
|
+
} else {
|
|
368
|
+
Faq.findByIdAndRemove({ _id: req.params.faqid }, function (err, faq) {
|
|
369
|
+
if (err) {
|
|
370
|
+
return res.status(500).send({ success: false, msg: 'Error deleting object.' });
|
|
371
|
+
}
|
|
372
|
+
winston.debug('Deleted FAQ ', faq);
|
|
373
|
+
|
|
374
|
+
faqBotEvent.emit('faq.delete', faq);
|
|
375
|
+
faqBotEvent.emit('faq_train.delete', faq.id_faq_kb);
|
|
376
|
+
|
|
377
|
+
res.status(200).send(faq);
|
|
378
|
+
|
|
379
|
+
});
|
|
380
|
+
}
|
|
338
381
|
});
|
|
339
382
|
|
|
340
383
|
// EXPORT FAQ TO CSV
|
package/routes/faq_kb.js
CHANGED
|
@@ -639,6 +639,7 @@ router.post('/importjson/:id_faq_kb', upload.single('uploadFile'), async (req, r
|
|
|
639
639
|
|
|
640
640
|
winston.debug("json source " + json_string)
|
|
641
641
|
|
|
642
|
+
// intentOnly still existing?
|
|
642
643
|
if (req.query.intentsOnly && req.query.intentsOnly == "true") {
|
|
643
644
|
|
|
644
645
|
winston.debug("intents only")
|
|
@@ -658,7 +659,8 @@ router.post('/importjson/:id_faq_kb', upload.single('uploadFile'), async (req, r
|
|
|
658
659
|
enabled: intent.enabled,
|
|
659
660
|
webhook_enabled: intent.webhook_enabled,
|
|
660
661
|
language: intent.language,
|
|
661
|
-
actions: intent.actions
|
|
662
|
+
actions: intent.actions,
|
|
663
|
+
attributes: intent.attributes
|
|
662
664
|
}
|
|
663
665
|
|
|
664
666
|
// overwrite duplicated intents
|
|
@@ -746,7 +748,8 @@ router.post('/importjson/:id_faq_kb', upload.single('uploadFile'), async (req, r
|
|
|
746
748
|
enabled: intent.enabled,
|
|
747
749
|
webhook_enabled: intent.webhook_enabled,
|
|
748
750
|
language: intent.language,
|
|
749
|
-
actions: intent.actions
|
|
751
|
+
actions: intent.actions,
|
|
752
|
+
attributes: intent.attributes
|
|
750
753
|
}
|
|
751
754
|
|
|
752
755
|
// TO DELETE: no used when req.query.create = 'true'
|
|
@@ -869,7 +872,8 @@ router.post('/importjson/:id_faq_kb', upload.single('uploadFile'), async (req, r
|
|
|
869
872
|
enabled: intent.enabled,
|
|
870
873
|
webhook_enabled: intent.webhook_enabled,
|
|
871
874
|
language: intent.language,
|
|
872
|
-
actions: intent.actions
|
|
875
|
+
actions: intent.actions,
|
|
876
|
+
attributes: intent.attributes
|
|
873
877
|
}
|
|
874
878
|
|
|
875
879
|
// overwrite duplicated intents
|
package/routes/openai.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
var express = require('express');
|
|
2
|
+
var router = express.Router();
|
|
3
|
+
var KBSettings = require('../models/kb_setting');
|
|
4
|
+
var openaiService = require('../services/openaiService');
|
|
5
|
+
var winston = require('../config/winston');
|
|
6
|
+
|
|
7
|
+
router.post('/', async (req, res) => {
|
|
8
|
+
|
|
9
|
+
let project_id = req.projectid;
|
|
10
|
+
let body = req.body;
|
|
11
|
+
|
|
12
|
+
console.log("### --> body: ", body);
|
|
13
|
+
|
|
14
|
+
KBSettings.findOne({ id_project: project_id }, (err, kbSettings) => {
|
|
15
|
+
console.log("kbSettings: ", kbSettings);
|
|
16
|
+
|
|
17
|
+
if (!kbSettings) {
|
|
18
|
+
return res.status(400).send({ success: false, message: "Missing gptkey parameter (settings not exist)" })
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let gptkey = kbSettings.gptkey;
|
|
22
|
+
|
|
23
|
+
if (!gptkey) {
|
|
24
|
+
return res.status(400).send({ success: false, message: "Missing gptkey parameter" })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// attua modifiche
|
|
28
|
+
let json = {
|
|
29
|
+
"model": body.model,
|
|
30
|
+
"messages": [
|
|
31
|
+
{
|
|
32
|
+
"role": "user",
|
|
33
|
+
"content": body.question
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"max_tokens": body.max_tokens,
|
|
37
|
+
"temperature": body.temperature
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let message = { role: "", content: "" };
|
|
41
|
+
if (body.context) {
|
|
42
|
+
message.role = "system";
|
|
43
|
+
message.content = body.context;
|
|
44
|
+
json.messages.unshift(message);
|
|
45
|
+
}
|
|
46
|
+
console.log("openai preview --> json: ", json);
|
|
47
|
+
|
|
48
|
+
openaiService.completions(json, gptkey).then((response) => {
|
|
49
|
+
// winston.debug("completions response: ", response);
|
|
50
|
+
res.status(200).send(response.data);
|
|
51
|
+
}).catch((err) => {
|
|
52
|
+
console.log("err: ", err);
|
|
53
|
+
// winston.error("completions error: ", err);
|
|
54
|
+
res.status(500).send(err)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// router.get('/', async (req, res) => {
|
|
61
|
+
|
|
62
|
+
// let project_id = req.projectid;
|
|
63
|
+
|
|
64
|
+
// OpenaiKbs.find({ id_project: project_id }, (err, kbs) => {
|
|
65
|
+
// if (err) {
|
|
66
|
+
// console.error("find all kbs error: ", err);
|
|
67
|
+
// return res.status(500).send({ success: false, error: err });
|
|
68
|
+
// } else {
|
|
69
|
+
// return res.status(200).send(kbs);
|
|
70
|
+
// }
|
|
71
|
+
// })
|
|
72
|
+
// })
|
|
73
|
+
|
|
74
|
+
// router.post('/', async (req, res) => {
|
|
75
|
+
|
|
76
|
+
// let body = req.body;
|
|
77
|
+
|
|
78
|
+
// let new_kbs = new OpenaiKbs({
|
|
79
|
+
// name: body.name,
|
|
80
|
+
// url: body.url,
|
|
81
|
+
// id_project: req.projectid,
|
|
82
|
+
// gptkey: req.body.gptkey
|
|
83
|
+
// })
|
|
84
|
+
|
|
85
|
+
// new_kbs.save(function (err, savedKbs) {
|
|
86
|
+
// if (err) {
|
|
87
|
+
// console.error("save new kbs error: ", err);
|
|
88
|
+
// return res.status(500).send({ success: false, error: err});
|
|
89
|
+
// } else {
|
|
90
|
+
// return res.status(200).send(savedKbs);
|
|
91
|
+
// }
|
|
92
|
+
// })
|
|
93
|
+
// })
|
|
94
|
+
|
|
95
|
+
// router.put('/', async (req, res) => {
|
|
96
|
+
// // to be implemented
|
|
97
|
+
// })
|
|
98
|
+
|
|
99
|
+
// router.delete('/:kbs_id', async (req, res) => {
|
|
100
|
+
// let kbs_id = req.params.kbs_id;
|
|
101
|
+
|
|
102
|
+
// OpenaiKbs.findOneAndDelete( { _id: kbs_id }, (err, kbDeleted) => {
|
|
103
|
+
// if (err) {
|
|
104
|
+
// console.error("find one and delete kbs error: ", err);
|
|
105
|
+
// return res.status(500).send({ success: false, error: err});
|
|
106
|
+
// } else {
|
|
107
|
+
// return res.status(200).send({ success: true, message: 'Knowledge Base deleted successfully', openai_kb: kbDeleted });
|
|
108
|
+
// }
|
|
109
|
+
// })
|
|
110
|
+
// })
|
|
111
|
+
|
|
112
|
+
module.exports = router;
|
package/routes/users.js
CHANGED
|
@@ -185,5 +185,29 @@ router.get('/', function (req, res) {
|
|
|
185
185
|
});
|
|
186
186
|
});
|
|
187
187
|
|
|
188
|
+
router.post('/loginemail', function (req, res) {
|
|
189
|
+
|
|
190
|
+
winston.debug("/loginemail... req.body: ", req.body);
|
|
191
|
+
let user_id = req.user._id;
|
|
192
|
+
let token = req.headers.authorization;
|
|
193
|
+
|
|
194
|
+
let project_id = req.body.id_project;
|
|
195
|
+
if (!project_id) {
|
|
196
|
+
res.status(500).send({ success: false, error: "missing 'id_project' field" })
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
User.findById(user_id, (err, user) => {
|
|
200
|
+
if (err) {
|
|
201
|
+
return res.status(404).send({ success: false, message: "No user found" });
|
|
202
|
+
}
|
|
203
|
+
winston.debug("user found: ", user);
|
|
204
|
+
|
|
205
|
+
emailService.sendEmailRedirectOnDesktop(user.email, token, project_id, user.email)
|
|
206
|
+
return res.status(200).send("Sending email...")
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
})
|
|
211
|
+
|
|
188
212
|
|
|
189
213
|
module.exports = router;
|
package/services/emailService.js
CHANGED
|
@@ -1851,6 +1851,39 @@ async sendRequestTranscript(to, messages, request, project) {
|
|
|
1851
1851
|
|
|
1852
1852
|
}
|
|
1853
1853
|
|
|
1854
|
+
async sendEmailRedirectOnDesktop(to, token, project_id) {
|
|
1855
|
+
winston.debug("sendEmailRedirectOnDesktop: " + to);
|
|
1856
|
+
|
|
1857
|
+
var that = this;
|
|
1858
|
+
|
|
1859
|
+
let html = await this.readTemplate('redirectToDesktopEmail.html');
|
|
1860
|
+
|
|
1861
|
+
let envTemplate = process.env.EMAIL_REDIRECT_TO_DESKTOP_TEMPLATE
|
|
1862
|
+
winston.debug("envTemplate: " + envTemplate);
|
|
1863
|
+
|
|
1864
|
+
if (envTemplate) {
|
|
1865
|
+
html = envTemplate;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
winston.debug("html: " + html);
|
|
1869
|
+
|
|
1870
|
+
let template = handlebars.compile(html);
|
|
1871
|
+
|
|
1872
|
+
let baseScope = JSON.parse(JSON.stringify(that));
|
|
1873
|
+
delete baseScope.pass;
|
|
1874
|
+
|
|
1875
|
+
let replacements = {
|
|
1876
|
+
baseScope: baseScope,
|
|
1877
|
+
token: token,
|
|
1878
|
+
project_id: project_id
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
html = template(replacements);
|
|
1882
|
+
|
|
1883
|
+
that.send({ to: to, subject: "Join Tiledesk from Desktop", html: html });
|
|
1884
|
+
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1854
1887
|
parseText(text, payload) {
|
|
1855
1888
|
|
|
1856
1889
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
var winston = require('../config/winston');
|
|
2
|
+
const axios = require("axios").default;
|
|
3
|
+
var configGlobal = require('../config/global');
|
|
4
|
+
require('dotenv').config();
|
|
5
|
+
|
|
6
|
+
let openai_endpoint = process.env.OPENAI_ENDPOINT;
|
|
7
|
+
|
|
8
|
+
class OpenaiService {
|
|
9
|
+
|
|
10
|
+
completions(data, gptkey) {
|
|
11
|
+
|
|
12
|
+
console.log("****** Serivcesssssssss openai_endpoint: ", openai_endpoint);
|
|
13
|
+
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
|
|
16
|
+
axios({
|
|
17
|
+
url: openai_endpoint + "/chat/completions",
|
|
18
|
+
headers: {
|
|
19
|
+
'Content-Type': 'application/json',
|
|
20
|
+
'Authorization': "Bearer " + gptkey
|
|
21
|
+
},
|
|
22
|
+
data: data,
|
|
23
|
+
method: 'POST'
|
|
24
|
+
}).then((resbody) => {
|
|
25
|
+
//winston.debug("[Openai] completions resbody: ", resbody.data);
|
|
26
|
+
resolve(resbody);
|
|
27
|
+
}).catch((err) => {
|
|
28
|
+
console.log("err: ", err);
|
|
29
|
+
// winston.error("[Openai] completions error: ", err);
|
|
30
|
+
reject(err);
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
var openaiService = new OpenaiService();
|
|
40
|
+
|
|
41
|
+
module.exports = openaiService;
|