@tiledesk/tiledesk-server 2.10.56 → 2.10.57
Sign up to get free protection for your applications and to get access to all the features.
- package/.github/workflows/docker-community-profiler-latest.yml +23 -0
- package/CHANGELOG.md +7 -0
- package/Dockerfile-profiler +33 -0
- package/app.js +10 -3
- package/package.json +3 -3
- package/routes/faq.js +13 -1
- package/routes/faq_kb.js +13 -1
- package/routes/files.js +10 -2
- package/routes/images.js +15 -3
- package/routes/kb.js +13 -0
- package/routes/llm.js +61 -0
- package/routes/message.js +0 -6
- package/services/aiService.js +22 -1
- package/websocket/webSocketServer.js +1 -1
@@ -0,0 +1,23 @@
|
|
1
|
+
name: Docker Image Community Profiler latest CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
push_to_registry:
|
11
|
+
name: Push Docker image to Docker Hub
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v2
|
16
|
+
name: Check out the repo
|
17
|
+
- uses: docker/build-push-action@v1
|
18
|
+
with:
|
19
|
+
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
20
|
+
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
21
|
+
repository: tiledesk/tiledesk-server
|
22
|
+
dockerfile: Dockerfile-profiler
|
23
|
+
tags: latest-profiler
|
package/CHANGELOG.md
CHANGED
@@ -5,6 +5,13 @@
|
|
5
5
|
🚀 IN PRODUCTION 🚀
|
6
6
|
(https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
|
7
7
|
|
8
|
+
# 2.10.57
|
9
|
+
- updated tybot-connector to 0.2.150
|
10
|
+
- fix issue on reconnect to rabbit queue (kb indexing)
|
11
|
+
- updated multi-worker to 0.1.19
|
12
|
+
- fix issue on TILEBOT_ENDPOINT undefined
|
13
|
+
- added endpoint for llm preview
|
14
|
+
|
8
15
|
# 2.10.56
|
9
16
|
- bug fix: wrong tilebot_endpoint declaration
|
10
17
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
FROM node:16
|
2
|
+
|
3
|
+
RUN sed -i 's/stable\/updates/stable-security\/updates/' /etc/apt/sources.list
|
4
|
+
|
5
|
+
|
6
|
+
RUN apt-get update
|
7
|
+
|
8
|
+
# Create app directory
|
9
|
+
WORKDIR /usr/src/app
|
10
|
+
|
11
|
+
ARG NPM_TOKEN
|
12
|
+
|
13
|
+
RUN if [ "$NPM_TOKEN" ]; \
|
14
|
+
then RUN COPY .npmrc_ .npmrc \
|
15
|
+
else export SOMEVAR=world; \
|
16
|
+
fi
|
17
|
+
|
18
|
+
|
19
|
+
# Install app dependencies
|
20
|
+
# A wildcard is used to ensure both package.json AND package-lock.json are copied
|
21
|
+
# where available (npm@5+)
|
22
|
+
COPY package*.json ./
|
23
|
+
|
24
|
+
RUN npm install --production
|
25
|
+
|
26
|
+
RUN rm -f .npmrc
|
27
|
+
|
28
|
+
# Bundle app source
|
29
|
+
COPY . .
|
30
|
+
|
31
|
+
EXPOSE 3000
|
32
|
+
|
33
|
+
CMD [ "node", "--prof", "./bin/www" ]
|
package/app.js
CHANGED
@@ -122,6 +122,7 @@ var key = require('./routes/key');
|
|
122
122
|
var widgets = require('./routes/widget');
|
123
123
|
var widgetsLoader = require('./routes/widgetLoader');
|
124
124
|
var openai = require('./routes/openai');
|
125
|
+
var llm = require('./routes/llm');
|
125
126
|
var quotes = require('./routes/quotes');
|
126
127
|
var integration = require('./routes/integration')
|
127
128
|
var kbsettings = require('./routes/kbsettings');
|
@@ -600,7 +601,7 @@ app.use('/:projectid/emails',[passport.authenticate(['basic', 'jwt'], { session:
|
|
600
601
|
app.use('/:projectid/properties',[passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], property);
|
601
602
|
app.use('/:projectid/segments',[passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], segment);
|
602
603
|
|
603
|
-
|
604
|
+
app.use('/:projectid/llm', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('admin', ['bot','subscription'])], llm);
|
604
605
|
app.use('/:projectid/openai', openai);
|
605
606
|
app.use('/:projectid/quotes', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], quotes)
|
606
607
|
|
@@ -655,11 +656,17 @@ app.use((err, req, res, next) => {
|
|
655
656
|
|
656
657
|
winston.debug("err.name", err.name)
|
657
658
|
if (err.name === "IpDeniedError") {
|
658
|
-
winston.
|
659
|
+
winston.debug("IpDeniedError");
|
659
660
|
return res.status(401).json({ err: "error ip filter" });
|
661
|
+
}
|
662
|
+
|
663
|
+
//emitted by multer when the file is too big
|
664
|
+
if (err.code === "LIMIT_FILE_SIZE") {
|
665
|
+
winston.debug("LIMIT_FILE_SIZE");
|
666
|
+
return res.status(413).json({ err: "Content Too Large", limit_file_size: process.env.MAX_UPLOAD_FILE_SIZE });
|
660
667
|
}
|
661
668
|
|
662
|
-
winston.error("General error", err);
|
669
|
+
winston.error("General error:: ", err);
|
663
670
|
return res.status(500).json({ err: "error" });
|
664
671
|
});
|
665
672
|
|
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.10.
|
4
|
+
"version": "2.10.57",
|
5
5
|
"scripts": {
|
6
6
|
"start": "node ./bin/www",
|
7
7
|
"pretest": "mongodb-runner start",
|
@@ -47,8 +47,8 @@
|
|
47
47
|
"@tiledesk/tiledesk-messenger-connector": "^0.1.23",
|
48
48
|
"@tiledesk/tiledesk-rasa-connector": "^1.0.10",
|
49
49
|
"@tiledesk/tiledesk-telegram-connector": "^0.1.14",
|
50
|
-
"@tiledesk/tiledesk-tybot-connector": "^0.2.
|
51
|
-
"@tiledesk/tiledesk-whatsapp-connector": "^0.1.
|
50
|
+
"@tiledesk/tiledesk-tybot-connector": "^0.2.150",
|
51
|
+
"@tiledesk/tiledesk-whatsapp-connector": "^0.1.77",
|
52
52
|
"@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.11",
|
53
53
|
"@tiledesk/tiledesk-sms-connector": "^0.1.11",
|
54
54
|
"@tiledesk/tiledesk-vxml-connector": "^0.1.67",
|
package/routes/faq.js
CHANGED
@@ -3,7 +3,6 @@ var router = express.Router();
|
|
3
3
|
var Faq = require("../models/faq");
|
4
4
|
var Faq_kb = require("../models/faq_kb");
|
5
5
|
var multer = require('multer')
|
6
|
-
var upload = multer()
|
7
6
|
const faqBotEvent = require('../event/faqBotEvent');
|
8
7
|
var winston = require('../config/winston');
|
9
8
|
const faqEvent = require('../event/faqBotEvent')
|
@@ -20,6 +19,19 @@ const roleChecker = require('../middleware/has-role');
|
|
20
19
|
|
21
20
|
const apiUrl = process.env.API_URL || configGlobal.apiUrl;
|
22
21
|
|
22
|
+
|
23
|
+
let MAX_UPLOAD_FILE_SIZE = process.env.MAX_UPLOAD_FILE_SIZE;
|
24
|
+
let uploadlimits = undefined;
|
25
|
+
|
26
|
+
if (MAX_UPLOAD_FILE_SIZE) {
|
27
|
+
uploadlimits = {fileSize: parseInt(MAX_UPLOAD_FILE_SIZE)} ;
|
28
|
+
winston.debug("Max upload file size is : " + MAX_UPLOAD_FILE_SIZE);
|
29
|
+
} else {
|
30
|
+
winston.debug("Max upload file size is infinity");
|
31
|
+
}
|
32
|
+
var upload = multer({limits: uploadlimits});
|
33
|
+
|
34
|
+
|
23
35
|
// POST CSV FILE UPLOAD FROM CLIENT
|
24
36
|
router.post('/uploadcsv', roleChecker.hasRoleOrTypes('admin', ['bot', 'subscription']), upload.single('uploadFile'), function (req, res, next) {
|
25
37
|
winston.debug(' -> -> REQ BODY ', req.body);
|
package/routes/faq_kb.js
CHANGED
@@ -10,7 +10,6 @@ var winston = require('../config/winston');
|
|
10
10
|
var httpUtil = require("../utils/httpUtil");
|
11
11
|
const { forEach } = require('lodash');
|
12
12
|
var multer = require('multer')
|
13
|
-
var upload = multer()
|
14
13
|
var configGlobal = require('../config/global');
|
15
14
|
const faq = require('../models/faq');
|
16
15
|
var jwt = require('jsonwebtoken');
|
@@ -22,6 +21,19 @@ const errorCodes = require('../errorCodes');
|
|
22
21
|
|
23
22
|
let chatbot_templates_api_url = process.env.CHATBOT_TEMPLATES_API_URL
|
24
23
|
|
24
|
+
|
25
|
+
let MAX_UPLOAD_FILE_SIZE = process.env.MAX_UPLOAD_FILE_SIZE;
|
26
|
+
let uploadlimits = undefined;
|
27
|
+
|
28
|
+
if (MAX_UPLOAD_FILE_SIZE) {
|
29
|
+
uploadlimits = {fileSize: parseInt(MAX_UPLOAD_FILE_SIZE)} ;
|
30
|
+
winston.debug("Max upload file size is : " + MAX_UPLOAD_FILE_SIZE);
|
31
|
+
} else {
|
32
|
+
winston.debug("Max upload file size is infinity");
|
33
|
+
}
|
34
|
+
var upload = multer({limits: uploadlimits});
|
35
|
+
|
36
|
+
|
25
37
|
router.post('/', roleChecker.hasRole('admin'), async function (req, res) {
|
26
38
|
winston.debug('create BOT ', req.body);
|
27
39
|
|
package/routes/files.js
CHANGED
@@ -19,8 +19,16 @@ const fileService = new FileGridFsService("files");
|
|
19
19
|
|
20
20
|
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
let MAX_UPLOAD_FILE_SIZE = process.env.MAX_UPLOAD_FILE_SIZE;
|
23
|
+
let uploadlimits = undefined;
|
24
|
+
|
25
|
+
if (MAX_UPLOAD_FILE_SIZE) {
|
26
|
+
uploadlimits = {fileSize: parseInt(MAX_UPLOAD_FILE_SIZE)} ;
|
27
|
+
winston.info("Max upload file size is : " + MAX_UPLOAD_FILE_SIZE);
|
28
|
+
} else {
|
29
|
+
winston.info("Max upload file size is infinity");
|
30
|
+
}
|
31
|
+
const upload = multer({ storage: fileService.getStorage("files"),limits: uploadlimits});
|
24
32
|
|
25
33
|
/*
|
26
34
|
curl -u andrea.leo@f21.it:123456 \
|
package/routes/images.js
CHANGED
@@ -35,6 +35,18 @@ const fileFilter = (req, file, cb) => {
|
|
35
35
|
}
|
36
36
|
}
|
37
37
|
|
38
|
+
|
39
|
+
let MAX_UPLOAD_FILE_SIZE = process.env.MAX_UPLOAD_FILE_SIZE;
|
40
|
+
let uploadlimits = undefined;
|
41
|
+
|
42
|
+
if (MAX_UPLOAD_FILE_SIZE) {
|
43
|
+
uploadlimits = {fileSize: parseInt(MAX_UPLOAD_FILE_SIZE)} ;
|
44
|
+
winston.debug("Max upload file size is : " + MAX_UPLOAD_FILE_SIZE);
|
45
|
+
} else {
|
46
|
+
winston.debug("Max upload file size is infinity");
|
47
|
+
}
|
48
|
+
|
49
|
+
|
38
50
|
// const bodymiddleware = function(req, res, next) {
|
39
51
|
// winston.info("YYYYYY req.body.folder:"+req.body.folder);
|
40
52
|
// winston.info("YYYYYY req.body:",req.body);
|
@@ -42,7 +54,7 @@ const fileFilter = (req, file, cb) => {
|
|
42
54
|
// }
|
43
55
|
|
44
56
|
|
45
|
-
const upload = multer({ storage: fileService.getStorage("images"), fileFilter: fileFilter });
|
57
|
+
const upload = multer({ storage: fileService.getStorage("images"), fileFilter: fileFilter, limits: uploadlimits });
|
46
58
|
|
47
59
|
/*
|
48
60
|
curl -u andrea.leo@f21.it:123456 \
|
@@ -96,7 +108,7 @@ upload.single('file'), (req, res, next) => {
|
|
96
108
|
|
97
109
|
|
98
110
|
|
99
|
-
const uploadFixedFolder = multer({ storage: fileService.getStorageFixFolder("images"), fileFilter: fileFilter });
|
111
|
+
const uploadFixedFolder = multer({ storage: fileService.getStorageFixFolder("images"), fileFilter: fileFilter, limits: uploadlimits });
|
100
112
|
|
101
113
|
/*
|
102
114
|
curl -v -X PUT -u andrea.leo@f21.it:123456 \
|
@@ -158,7 +170,7 @@ uploadFixedFolder.single('file'), (req, res, next) => {
|
|
158
170
|
|
159
171
|
|
160
172
|
|
161
|
-
const uploadAvatar= multer({ storage: fileService.getStorageAvatar("images"), fileFilter: fileFilter });
|
173
|
+
const uploadAvatar= multer({ storage: fileService.getStorageAvatar("images"), fileFilter: fileFilter, limits: uploadlimits });
|
162
174
|
|
163
175
|
/*
|
164
176
|
curl -v -X PUT -u andrea.leo@f21.it:123456 \
|
package/routes/kb.js
CHANGED
@@ -24,6 +24,19 @@ const JOB_TOPIC_EXCHANGE = process.env.JOB_TOPIC_EXCHANGE_TRAIN || 'tiledesk-tra
|
|
24
24
|
const KB_WEBHOOK_TOKEN = process.env.KB_WEBHOOK_TOKEN || 'kbcustomtoken';
|
25
25
|
const apiUrl = process.env.API_URL || configGlobal.apiUrl;
|
26
26
|
|
27
|
+
|
28
|
+
let MAX_UPLOAD_FILE_SIZE = process.env.MAX_UPLOAD_FILE_SIZE;
|
29
|
+
let uploadlimits = undefined;
|
30
|
+
|
31
|
+
if (MAX_UPLOAD_FILE_SIZE) {
|
32
|
+
uploadlimits = {fileSize: parseInt(MAX_UPLOAD_FILE_SIZE)} ;
|
33
|
+
winston.debug("Max upload file size is : " + MAX_UPLOAD_FILE_SIZE);
|
34
|
+
} else {
|
35
|
+
winston.debug("Max upload file size is infinity");
|
36
|
+
}
|
37
|
+
var upload = multer({limits: uploadlimits});
|
38
|
+
|
39
|
+
|
27
40
|
let jobManager = new JobManager(AMQP_MANAGER_URL, {
|
28
41
|
debug: false,
|
29
42
|
topic: JOB_TOPIC_EXCHANGE,
|
package/routes/llm.js
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
var express = require('express');
|
2
|
+
var router = express.Router();
|
3
|
+
var winston = require('../config/winston');
|
4
|
+
let Integration = require('../models/integrations');
|
5
|
+
const aiService = require('../services/aiService');
|
6
|
+
|
7
|
+
router.post('/preview', async (req, res) => {
|
8
|
+
|
9
|
+
let id_project = req.projectid;
|
10
|
+
let body = req.body;
|
11
|
+
let key;
|
12
|
+
|
13
|
+
if (!body.llm) {
|
14
|
+
return res.status(400).send({ success: false, error: "Missing required parameter 'llm'" });
|
15
|
+
}
|
16
|
+
|
17
|
+
let integration = await Integration.findOne({ id_project: id_project, name: body.llm }).catch((err) => {
|
18
|
+
winston.error("Error finding integration with name: ", body.llm);
|
19
|
+
return res.status(500).send({ success: false, error: "Error finding integration for " + body.llm});
|
20
|
+
})
|
21
|
+
|
22
|
+
if (!integration) {
|
23
|
+
winston.verbose("Integration for " + body.llm + " not found.")
|
24
|
+
return res.status(404).send({ success: false, error: "Integration for " + body.llm + " not found."})
|
25
|
+
}
|
26
|
+
|
27
|
+
if (!integration?.value?.apikey) {
|
28
|
+
return res.status(422).send({ success: false, error: "The key provided for " + body.llm + " is not valid or undefined." })
|
29
|
+
}
|
30
|
+
|
31
|
+
key = integration.value.apikey;
|
32
|
+
|
33
|
+
let json = {
|
34
|
+
question: body.question,
|
35
|
+
llm: body.llm,
|
36
|
+
model: body.model,
|
37
|
+
llm_key: key,
|
38
|
+
temperature: body.temperature,
|
39
|
+
max_tokens: body.max_tokens
|
40
|
+
}
|
41
|
+
|
42
|
+
if (body.context) {
|
43
|
+
json.system_context = body.context;
|
44
|
+
}
|
45
|
+
|
46
|
+
aiService.askllm(json).then((response) => {
|
47
|
+
winston.verbose("Askllm response: ", response);
|
48
|
+
res.status(200).send(response.data)
|
49
|
+
}).catch((err) => {
|
50
|
+
if (err.response?.data?.detail[0]) {
|
51
|
+
res.status(400).send({ success: false, error: err.response.data.detail[0]?.msg, detail: err.response.data.detail });
|
52
|
+
} else if (err.response?.data?.detail?.answer) {
|
53
|
+
res.status(400).send({ success: false, error: err.response.data.detail.answer, detail: err.response.data.detail });
|
54
|
+
} else {
|
55
|
+
res.status(500).send({ success: false, error: err.response.data });
|
56
|
+
}
|
57
|
+
})
|
58
|
+
|
59
|
+
})
|
60
|
+
|
61
|
+
module.exports = router;
|
package/routes/message.js
CHANGED
@@ -247,12 +247,6 @@ async (req, res) => {
|
|
247
247
|
});
|
248
248
|
}).catch(function (err) { //pubblica questo
|
249
249
|
winston.error('Error creating request: ' + JSON.stringify(err));
|
250
|
-
winston.log({
|
251
|
-
level: 'error',
|
252
|
-
message: 'Error creating request: ' + JSON.stringify(err) + " " + JSON.stringify(req.body),
|
253
|
-
label: req.projectid
|
254
|
-
});
|
255
|
-
// winston.error("Error creating message", err);
|
256
250
|
return res.status(500).send({ success: false, msg: 'Error creating request', err: err });
|
257
251
|
});
|
258
252
|
|
package/services/aiService.js
CHANGED
@@ -36,8 +36,29 @@ class AiService {
|
|
36
36
|
|
37
37
|
}
|
38
38
|
|
39
|
+
// LLM
|
40
|
+
askllm(data) {
|
41
|
+
winston.debug("[OPENAI SERVICE] llm endpoint: " + kb_endpoint);
|
39
42
|
|
40
|
-
|
43
|
+
return new Promise((resolve, reject) => {
|
44
|
+
|
45
|
+
axios({
|
46
|
+
url: kb_endpoint + "/ask",
|
47
|
+
headers: {
|
48
|
+
'Content-Type': 'application/json'
|
49
|
+
},
|
50
|
+
data: data,
|
51
|
+
method: 'POST'
|
52
|
+
}).then((resbody) => {
|
53
|
+
resolve(resbody)
|
54
|
+
}).catch((err) => {
|
55
|
+
reject(err)
|
56
|
+
})
|
57
|
+
})
|
58
|
+
}
|
59
|
+
|
60
|
+
|
61
|
+
// KB
|
41
62
|
checkStatus(data) {
|
42
63
|
winston.debug("[OPENAI SERVICE] kb endpoint: " + kb_endpoint);
|
43
64
|
|
@@ -93,7 +93,7 @@ class WebSocketServer {
|
|
93
93
|
token = token.replace('JWT ', '');
|
94
94
|
jwt.verify(token, configSecretOrPubicKay, function (err, decoded) { //pub_jwt pp_jwt
|
95
95
|
if (err) {
|
96
|
-
winston.error('WebSocket error verifing websocket jwt token ', err);
|
96
|
+
winston.error('WebSocket error verifing websocket jwt token: ' + token, err);
|
97
97
|
return cb(false, 401, 'Unauthorized');
|
98
98
|
} else {
|
99
99
|
// uncomment it
|