@tiledesk/tiledesk-server 2.7.26 → 2.8.0

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/routes/kb.js CHANGED
@@ -1,4 +1,5 @@
1
1
  var express = require('express');
2
+ var { Namespace } = require('../models/kb_setting');
2
3
  var { KB } = require('../models/kb_setting');
3
4
  var router = express.Router();
4
5
  var winston = require('../config/winston');
@@ -9,6 +10,11 @@ const JobManager = require('../utils/jobs-worker-queue-manager/JobManagerV2');
9
10
  const { Scheduler } = require('../services/Scheduler');
10
11
  var configGlobal = require('../config/global');
11
12
  const Sitemapper = require('sitemapper');
13
+ var mongoose = require('mongoose');
14
+ const faq = require('../models/faq');
15
+ const faq_kb = require('../models/faq_kb');
16
+
17
+ const { MODELS_MULTIPLIER } = require('../utils/aiUtils');
12
18
 
13
19
  const AMQP_MANAGER_URL = process.env.AMQP_MANAGER_URL;
14
20
  const JOB_TOPIC_EXCHANGE = process.env.JOB_TOPIC_EXCHANGE_TRAIN || 'tiledesk-trainer';
@@ -16,719 +22,1123 @@ const KB_WEBHOOK_TOKEN = process.env.KB_WEBHOOK_TOKEN || 'kbcustomtoken';
16
22
  const apiUrl = process.env.API_URL || configGlobal.apiUrl;
17
23
 
18
24
  let jobManager = new JobManager(AMQP_MANAGER_URL, {
19
- debug: false,
20
- topic: JOB_TOPIC_EXCHANGE,
21
- exchange: JOB_TOPIC_EXCHANGE
25
+ debug: false,
26
+ topic: JOB_TOPIC_EXCHANGE,
27
+ exchange: JOB_TOPIC_EXCHANGE
22
28
  })
23
29
 
24
30
  jobManager.connectAndStartPublisher(() => {
25
- winston.info("ConnectPublisher done");
31
+ winston.info("ConnectPublisher done");
26
32
  })
27
33
 
28
- router.get('/', async (req, res) => {
34
+ let default_preview_settings = {
35
+ model: 'gpt-3.5-turbo',
36
+ max_tokens: 128,
37
+ temperature: 0.7,
38
+ top_k: 4,
39
+ context: "You are an awesome AI Assistant."
40
+ }
29
41
 
30
- let project_id = req.projectid;
31
- let status;
32
- let type;
33
- let limit = 200;
34
- let page = 0;
35
- let direction = -1;
36
- let sortField = "updatedAt";
37
- let text;
38
-
39
- let query = {};
40
- query["id_project"] = project_id;
41
-
42
- if (req.query.status) {
43
- status = parseInt(req.query.status);
44
- query["status"] = status;
45
- winston.debug("Get kb status: " + status)
46
- }
42
+ /**
43
+ * ****************************************
44
+ * Proxy Section - Start
45
+ * ****************************************
46
+ */
47
+ router.post('/scrape/single', async (req, res) => {
47
48
 
48
- if (req.query.type) {
49
- type = req.query.type;
50
- query["type"] = type;
51
- winston.debug("Get kb type: " + type);
52
- }
49
+ let project_id = req.projectid;
53
50
 
54
- if (req.query.limit) {
55
- limit = parseInt(req.query.limit);
56
- winston.debug("Get kb limit: " + limit)
57
- }
51
+ let data = req.body;
52
+ winston.debug("/scrape/single data: ", data);
58
53
 
59
- if (req.query.page) {
60
- page = parseInt(req.query.page);
61
- winston.debug("Get kb page: " + page)
62
- }
54
+ let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
55
+ winston.error("find namespaces error: ", err)
56
+ res.status(500).send({ success: false, error: err })
57
+ })
58
+
59
+ if (!namespaces || namespaces.length == 0) {
60
+ let alert = "No namespace found for the selected project " + project_id + ". Cannot add content to a non-existent namespace."
61
+ winston.warn(alert);
62
+ res.status(403).send(alert);
63
+ }
63
64
 
64
- let skip = page * limit;
65
- winston.debug("Get kb skip page: " + skip);
65
+ let namespaceIds = namespaces.map(namespace => namespace.id);
66
66
 
67
- if (req.query.direction) {
68
- direction = parseInt(req.query.direction)
69
- winston.debug("Get kb direction: " + direction)
67
+ KB.findById(data.id, (err, kb) => {
68
+ if (err) {
69
+ winston.error("findById error: ", err);
70
+ return res.status(500).send({ success: false, error: err });
70
71
  }
71
72
 
72
- if (req.query.sortField) {
73
- sortField = req.query.sortField;
74
- winston.debug("Get kb sortField: " + sortField)
73
+ else if (!kb) {
74
+ return res.status(404).send({ success: false, error: "Unable to find the kb requested" })
75
75
  }
76
+ else {
77
+
78
+ if (!namespaceIds.includes(kb.namespace)) {
79
+ return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
80
+ }
81
+
82
+ let json = {
83
+ id: kb._id,
84
+ type: kb.type,
85
+ source: kb.source,
86
+ content: "",
87
+ namespace: kb.namespace
88
+ }
89
+
90
+ if (kb.content) {
91
+ json.content = kb.content;
92
+ }
93
+
94
+ startScrape(json).then((response) => {
95
+ winston.verbose("startScrape response: ", response);
96
+ res.status(200).send(response);
97
+ }).catch((err) => {
98
+ winston.error("startScrape err: ", err);
99
+ res.status(500).send({ success: false, error: err });
100
+ })
76
101
 
77
- if (req.query.search) {
78
- text = req.query.search;
79
- query['source'] = new RegExp(text);
80
- winston.debug("Get kb text: " + text);
81
102
  }
103
+ })
82
104
 
83
- let sortQuery = {};
84
- sortQuery[sortField] = direction;
85
- winston.debug("Get kb sortQuery: " + sortQuery);
105
+ })
86
106
 
87
- KB.countDocuments(query, (err, kbs_count) => {
88
- if (err) {
89
- winston.error("Find all kbs error: ", err);
90
- }
91
- winston.debug("KBs count: ", kbs_count);
92
-
93
- KB.find(query)
94
- .skip(skip)
95
- .limit(limit)
96
- .sort(sortQuery)
97
- .exec((err, kbs) => {
98
- if (err) {
99
- winston.error("Find all kbs error: ", err);
100
- return res.status(500).send({ success: false, error: err });
101
- }
102
-
103
- winston.debug("KBs found: ", kbs);
104
-
105
- let response = {
106
- count: kbs_count,
107
- query: {},
108
- kbs: kbs
109
- }
110
- if (status) {
111
- response.query.status = status;
112
- }
113
- if (limit) {
114
- response.query.limit = limit;
115
- }
116
- if (status) {
117
- response.query.page = page;
118
- }
119
- if (sortField) {
120
- response.query.sortField = sortField;
121
- }
122
- if (direction) {
123
- response.query.direction = direction;
124
- }
125
- if (text) {
126
- response.query.search = text;
127
- }
128
-
129
-
130
- return res.status(200).send(response);
131
- })
107
+ router.post('/scrape/status', async (req, res) => {
132
108
 
133
- })
109
+ let data = req.body;
110
+ winston.debug("/scrapeStatus req.body: ", req.body);
134
111
 
112
+ let returnObject = false;
135
113
 
136
- })
114
+ if (req.query &&
115
+ req.query.returnObject &&
116
+ (req.query.returnObject === true || req.query.returnObject === 'true')) {
117
+ returnObject = true;
118
+ }
137
119
 
138
- router.get('/:kb_id', async (req, res) => {
120
+ openaiService.scrapeStatus(data).then(async (response) => {
139
121
 
140
- let kb_id = req.params.kb_id;
122
+ winston.debug("scrapeStatus response.data: ", response.data);
141
123
 
142
- KB.findById(kb_id, (err, kb) => {
143
- if (err) {
144
- winston.error("Find kb by id error: ", err);
145
- return res.status(500).send({ success: false, error: err });
124
+ let update = {};
125
+
126
+ if (response.data.status_code) {
127
+ // update.status = response.data.status_code;
128
+ update.status = await statusConverter(response.data.status_code)
129
+
130
+ }
131
+
132
+ KB.findByIdAndUpdate(data.id, update, { new: true }, (err, savedKb) => {
133
+
134
+ if (err) {
135
+ winston.verbose("Status was successfully recovered, but the update on the db failed");
136
+ winston.error("find kb by id and updated error: ", err);
137
+
138
+ if (returnObject) {
139
+ return res.status(206).send({ warning: "Unable to udpate content on db", message: "The original reply was forwarded", data: response.data });
140
+ } else {
141
+ return res.status(200).send(response.data);
146
142
  }
143
+ }
147
144
 
148
- return res.status(200).send(kb);
145
+ if (returnObject) {
146
+ return res.status(200).send(savedKb);
147
+ } else {
148
+ return res.status(200).send(response.data);
149
+ }
149
150
  })
151
+
152
+ }).catch((err) => {
153
+ winston.error("scrapeStatus err: ", err);
154
+ let status = err.response.status;
155
+ res.status(status).send({ statusText: err.response.statusText, error: err.response.data.detail });
156
+ })
150
157
  })
151
158
 
152
- router.post('/', async (req, res) => {
159
+ router.post('/qa', async (req, res) => {
153
160
 
161
+ let project_id = req.projectid;
162
+ let publicKey = false;
163
+ let data = req.body;
154
164
 
155
- let project_id = req.projectid;
156
- let body = req.body;
165
+ let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
166
+ winston.error("find namespaces error: ", err)
167
+ res.status(500).send({ success: false, error: err })
168
+ })
157
169
 
158
- // add or override namespace value if it is passed for security reason
159
- body.namespace = project_id;
170
+ if (!namespaces || namespaces.length == 0) {
171
+ let alert = "No namespace found for the selected project " + project_id + ". Cannot add content to a non-existent namespace."
172
+ winston.warn(alert);
173
+ res.status(403).send(alert);
174
+ }
160
175
 
161
- // if (req.body.namespace) {
162
- // if (req.body.namespace != req.projectid) {
163
- // return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project."})
164
- // }
165
- // }
176
+ let namespaceIds = namespaces.map(namespace => namespace.id);
166
177
 
167
- let quoteManager = req.app.get('quote_manager');
168
- let limits = await quoteManager.getPlanLimits(req.project);
169
- let kbs_limit = limits.kbs;
170
- winston.verbose("Limit of kbs for current plan: " + kbs_limit);
178
+ if (!namespaceIds.includes(data.namespace)) {
179
+ return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
180
+ }
171
181
 
172
- let kbs_count = await KB.countDocuments({ id_project: project_id }).exec();
173
- winston.verbose("Kbs count: " + kbs_count);
182
+ winston.debug("/qa data: ", data);
174
183
 
175
- if (kbs_count >= kbs_limit) {
176
- return res.status(403).send({ success: false, error: "Maximum number of resources reached for the current plan", plan_limit: kbs_limit })
184
+ if (!data.gptkey) {
185
+ let gptkey = process.env.GPTKEY;
186
+ if (!gptkey) {
187
+ return res.status(403).send({ success: false, error: "GPT apikey undefined" })
177
188
  }
189
+ data.gptkey = gptkey;
190
+ publicKey = true;
191
+ }
192
+
193
+ let obj = { createdAt: new Date() };
178
194
 
179
- let total_count = kbs_count + 1;
180
- if (total_count > kbs_limit) {
181
- return res.status(403).send({ success: false, error: "Cannot exceed the number of resources in the current plan", plan_limit: kbs_limit })
195
+ let quoteManager = req.app.get('quote_manager');
196
+ if (publicKey === true) {
197
+ let isAvailable = await quoteManager.checkQuote(req.project, obj, 'tokens');
198
+ if (isAvailable === false) {
199
+ return res.status(403).send({ success: false, message: "Tokens quota exceeded", error_code: 13001})
182
200
  }
183
- let new_kb = {
184
- id_project: project_id,
185
- name: body.name,
186
- type: body.type,
187
- source: body.source,
188
- content: body.content,
189
- namespace: body.namespace,
190
- status: -1
201
+ }
202
+
203
+ if (data.system_context) {
204
+ data.system_context = data.system_context + " {context}";
205
+ }
206
+
207
+ openaiService.askNamespace(data).then((resp) => {
208
+ winston.debug("qa resp: ", resp.data);
209
+ let answer = resp.data;
210
+
211
+ let id = answer.id;
212
+ let index = id.indexOf("#");
213
+ if (index != -1) {
214
+ id = id.substring(index + 1);
215
+ }
216
+
217
+ KB.findById(id, (err, resource) => {
218
+
219
+ let multiplier = MODELS_MULTIPLIER[data.model];
220
+ if (!multiplier) {
221
+ multiplier = 1;
222
+ winston.info("No multiplier found for AI model")
223
+ }
224
+ obj.multiplier = multiplier;
225
+ obj.tokens = answer.prompt_token_size;
226
+
227
+ let incremented_key = quoteManager.incrementTokenCount(req.project, obj);
228
+ winston.verbose("incremented_key: ", incremented_key);
229
+
230
+ if (err) {
231
+ winston.error("Unable to find resource with id " + id + " in namespace " + answer.namespace + ". The standard answer is returned.")
232
+ return res.status(200).send(resp.data);
233
+ }
234
+
235
+ if (!resource) {
236
+ winston.error("Resource with id " + id + " not found in namespace " + answer.namespace + ". The standard answer is returned.")
237
+ return res.status(200).send(resp.data);
238
+ }
239
+
240
+ answer.source = resource.name;
241
+ return res.status(200).send(answer);
242
+ })
243
+
244
+
245
+ }).catch((err) => {
246
+ winston.error("qa err: ", err);
247
+ winston.error("qa err.response: ", err.response);
248
+ if (err.response && err.response.status) {
249
+ let status = err.response.status;
250
+ res.status(status).send({ success: false, statusText: err.response.statusText, error: err.response.data.detail });
191
251
  }
192
- if (!new_kb.namespace) {
193
- new_kb.namespace = project_id;
252
+ else {
253
+ res.status(500).send({ success: false, error: err });
194
254
  }
195
- winston.debug("adding kb: ", new_kb);
196
255
 
197
- KB.findOneAndUpdate({ id_project: project_id, type: 'url', source: new_kb.source }, new_kb, { upsert: true, new: true, rawResult: true }, async (err, raw) => {
198
- if (err) {
199
- winston.error("findOneAndUpdate with upsert error: ", err);
200
- res.status(500).send({ success: false, error: err });
201
- }
202
- else {
256
+ })
257
+ })
203
258
 
204
- res.status(200).send(raw);
259
+ router.delete('/delete', async (req, res) => {
205
260
 
206
- let webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
207
-
208
- let json = {
209
- id: raw.value._id,
210
- type: raw.value.type,
211
- source: raw.value.source,
212
- content: "",
213
- namespace: raw.value.namespace,
214
- webhook: webhook
215
- }
216
- winston.debug("json: ", json);
261
+ let project_id = req.projectid;
262
+ let data = req.body;
263
+ winston.debug("/delete data: ", data);
217
264
 
218
- if (raw.value.content) {
219
- json.content = raw.value.content;
220
- }
265
+ let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
266
+ winston.error("find namespaces error: ", err)
267
+ res.status(500).send({ success: false, error: err })
268
+ })
221
269
 
222
- let resources = [];
270
+ if (!namespaces || namespaces.length == 0) {
271
+ let alert = "No namespace found for the selected project " + project_id + ". Cannot add content to a non-existent namespace."
272
+ winston.warn(alert);
273
+ res.status(403).send(alert);
274
+ }
223
275
 
224
- resources.push(json);
225
- scheduleScrape(resources);
276
+ let namespaceIds = namespaces.map(namespace => namespace.id);
226
277
 
227
- // startScrape(json).then((response) => {
228
- // winston.verbose("startScrape response: ", response);
229
- // }).catch((err) => {
230
- // winston.error("startScrape err: ", err);
231
- // })
278
+ if (!namespaceIds.includes(data.namespace)) {
279
+ return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
280
+ }
232
281
 
233
- }
234
- })
282
+ openaiService.deleteIndex(data).then((resp) => {
283
+ winston.debug("delete resp: ", resp.data);
284
+ res.status(200).send(resp.data);
285
+ }).catch((err) => {
286
+ winston.error("delete err: ", err);
287
+ let status = err.response.status;
288
+ res.status(status).send({ statusText: err.response.statusText, error: err.response.data.detail });
289
+ })
235
290
 
236
291
  })
237
292
 
238
- router.post('/multi', upload.single('uploadFile'), async (req, res) => {
293
+ router.delete('/deleteall', async (req, res) => {
239
294
 
240
- let list;
241
- if (req.file) {
242
- file_string = req.file.buffer.toString('utf-8');
243
- list = file_string.trim().split('\n');
244
- } else {
245
- list = req.body.list;
246
- }
295
+ let project_id = req.projectid;
296
+ let data = req.body;
297
+ winston.debug('/delete all data: ', data);
298
+
299
+ let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
300
+ winston.error("find namespaces error: ", err)
301
+ res.status(500).send({ success: false, error: err })
302
+ })
303
+
304
+ if (!namespaces || namespaces.length == 0) {
305
+ let alert = "No namespace found for the selected project " + project_id + ". Cannot add content to a non-existent namespace."
306
+ winston.warn(alert);
307
+ res.status(403).send(alert);
308
+ }
309
+
310
+ let namespaceIds = namespaces.map(namespace => namespace.id);
311
+
312
+ if (!namespaceIds.includes(data.namespace)) {
313
+ return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
314
+ }
315
+
316
+ openaiService.deleteNamespace(data).then((resp) => {
317
+ winston.debug("delete namespace resp: ", resp.data);
318
+ res.status(200).send(resp.data);
319
+ }).catch((err) => {
320
+ winston.error("delete namespace err: ", err);
321
+ let status = err.response.status;
322
+ res.status(status).send({ statusText: err.response.statusText, error: err.response.data.detail });
323
+ })
324
+ })
325
+ /**
326
+ * ****************************************
327
+ * Proxy Section - Start
328
+ * ****************************************
329
+ */
247
330
 
248
- let project_id = req.projectid;
249
331
 
250
- let quoteManager = req.app.get('quote_manager');
251
- let limits = await quoteManager.getPlanLimits(req.project);
252
- let kbs_limit = limits.kbs;
253
- winston.verbose("Limit of kbs for current plan: " + kbs_limit);
332
+ //----------------------------------------
254
333
 
255
- let kbs_count = await KB.countDocuments({ id_project: project_id }).exec();
256
- winston.verbose("Kbs count: " + kbs_count);
257
334
 
258
- if (kbs_count >= kbs_limit) {
259
- return res.status(403).send({ success: false, error: "Maximum number of resources reached for the current plan", plan_limit: kbs_limit })
260
- }
335
+ /**
336
+ * ****************************************
337
+ * Namespace Section - Start
338
+ * ****************************************
339
+ */
340
+ router.get('/namespace/all', async (req, res) => {
261
341
 
262
- let total_count = kbs_count + list.length;
263
- if (total_count > kbs_limit) {
264
- return res.status(403).send({ success: false, error: "Cannot exceed the number of resources in the current plan", plan_limit: kbs_limit })
265
- }
342
+ let project_id = req.projectid;
343
+
344
+ Namespace.find({ id_project: project_id }).lean().exec((err, namespaces) => {
266
345
 
267
- if (list.length > 300) {
268
- winston.error("Too many urls. Can't index more than 300 urls at a time.");
269
- return res.status(403).send({ success: false, error: "Too many urls. Can't index more than 300 urls at a time."})
346
+ if (err) {
347
+ winston.error("find namespaces error: ", err);
348
+ return res.status(500).send({ success: false, error: err });
270
349
  }
350
+ else if (namespaces.length == 0) {
271
351
 
272
- let webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
273
-
274
- let kbs = [];
275
- list.forEach(url => {
276
- kbs.push({
277
- id_project: project_id,
278
- name: url,
279
- source: url,
280
- type: 'url',
281
- content: "",
282
- namespace: project_id,
283
- status: -1
284
- })
285
- })
352
+ // Create Default Namespace
353
+ let new_namespace = new Namespace({
354
+ id_project: project_id,
355
+ id: project_id,
356
+ name: "Default",
357
+ preview_settings: default_preview_settings,
358
+ default: true
359
+ })
286
360
 
287
- let operations = kbs.map(doc => {
288
- return {
289
- updateOne: {
290
- filter: { id_project: doc.id_project, type: 'url', source: doc.source },
291
- update: doc,
292
- upsert: true,
293
- returnOriginal: false
294
- }
361
+ new_namespace.save((err, savedNamespace) => {
362
+ if (err) {
363
+ winston.error("create default namespace error: ", err);
364
+ return res.status(500).send({ success: false, error: err });
295
365
  }
296
- })
297
366
 
298
- saveBulk(operations, kbs, project_id).then((result) => {
367
+ let namespaceObj = savedNamespace.toObject();
368
+ delete namespaceObj._id;
369
+ delete namespaceObj.__v;
299
370
 
300
- let resources = result.map(({ name, status, __v, createdAt, updatedAt, id_project, ...keepAttrs }) => keepAttrs)
301
- resources = resources.map(({ _id, ...rest }) => {
302
- return { id: _id, webhook: webhook, ...rest };
303
- });
304
- winston.verbose("resources to be sent to worker: ", resources);
305
- scheduleScrape(resources);
306
- res.status(200).send(result);
371
+ let namespaces = [];
372
+ namespaces.push(namespaceObj);
307
373
 
308
- }).catch((err) => {
309
- winston.error("Unable to save kbs in bulk ", err)
310
- res.status(500).send(err);
311
- })
374
+ return res.status(200).send(namespaces);
375
+
376
+ })
312
377
 
378
+ } else {
379
+
380
+ const namespaceObjArray = namespaces.map(({ _id, __v, ...keepAttrs }) => keepAttrs)
381
+ winston.debug("namespaceObjArray: ", namespaceObjArray);
382
+ return res.status(200).send(namespaceObjArray);
383
+ }
384
+ })
313
385
  })
314
386
 
315
- router.post('/sitemap', async (req, res) => {
387
+ router.get('/namespace/:id/chatbots', async (req, res) => {
388
+
389
+ let project_id = req.projectid;
390
+ let namespace_id = req.params.id;
391
+
392
+ let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
393
+ winston.error("find namespaces error: ", err)
394
+ res.status(500).send({ success: false, error: err })
395
+ })
396
+
397
+ let namespaceIds = namespaces.map(namespace => namespace.id);
398
+ if (!namespaceIds.includes(namespace_id)) {
399
+ return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
400
+ }
401
+
402
+ let intents = await faq.find({ id_project: project_id, 'actions.namespace': namespace_id }).catch((err) => {
403
+ winston.error("Error find intents: ", err);
404
+ return res.status(500).send({ success: false, message: 'Unable to retrieve intents using the selected namespace', error: err });
405
+ })
406
+
407
+ if (!intents || intents.length == 0) {
408
+ winston.verbose("No intents found for the selected chatbot")
409
+ return res.status(200).send({ success: false, message: "No intents found for the selected chatbot" });
410
+ }
411
+
412
+ let chatbots = intents.map(i => i.id_faq_kb);
413
+ let uniqueChatbots = [...new Set(chatbots)];
414
+
415
+ let chatbotsArray = [];
416
+ let chatbotPromises = uniqueChatbots.map(async (c_id) => {
417
+ try {
418
+ let chatbot = await faq_kb.findById(c_id);
419
+ if (chatbot) {
420
+ let data = {
421
+ _id: chatbot._id,
422
+ name: chatbot.name
423
+ }
424
+ chatbotsArray.push(data);
425
+ }
426
+ } catch (err) {
427
+ winston.error("error getting chatbot: ", err);
428
+ }
429
+ });
316
430
 
317
- let sitemap_url = req.body.sitemap;
318
-
319
- const sitemap = new Sitemapper({
320
- url: sitemap_url,
321
- timeout: 15000
322
- });
431
+ await Promise.all(chatbotPromises);
323
432
 
324
- sitemap.fetch().then((data) => {
325
- winston.debug("data: ", data);
326
- res.status(200).send(data);
327
- }).catch((err) => {
328
- console.error("err ", err)
329
- res.status(500).send({ success: false, error: err });
330
- })
433
+ winston.debug("chatbotsArray: ", chatbotsArray);
331
434
 
435
+ res.status(200).send(chatbotsArray);
332
436
  })
333
437
 
334
- router.put('/:kb_id', async (req, res) => {
438
+ router.post('/namespace', async (req, res) => {
439
+
440
+ let project_id = req.projectid;
441
+ let body = req.body;
442
+ winston.debug("add namespace body: ", body);
443
+
444
+ var namespace_id = mongoose.Types.ObjectId();
445
+ let new_namespace = new Namespace({
446
+ id_project: project_id,
447
+ id: namespace_id,
448
+ name: body.name,
449
+ preview_settings: default_preview_settings,
450
+ })
451
+
452
+ let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
453
+ winston.error("find namespaces error: ", err)
454
+ //res.status(500).send({ success: false, error: err })
455
+ })
456
+ if (!namespaces || namespaces.length == 0) {
457
+ new_namespace.default = true;
458
+ }
459
+
460
+ new_namespace.save((err, savedNamespace) => {
461
+ if (err) {
462
+ winston.error("create namespace error: ", err);
463
+ return res.status(500).send({ success: false, error: err });
464
+ }
335
465
 
336
- let kb_id = req.params.kb_id;
337
- winston.verbose("update kb_id " + kb_id);
466
+ let namespaceObj = savedNamespace.toObject();
467
+ delete namespaceObj._id;
468
+ delete namespaceObj.__v;
469
+ return res.status(200).send(namespaceObj);
470
+ })
471
+ })
338
472
 
339
- let update = {};
473
+ router.put('/namespace/:id', async (req, res) => {
474
+
475
+ let namespace_id = req.params.id;
476
+ let body = req.body;
477
+ winston.debug("update namespace body: ", body);
340
478
 
341
- if (req.body.name != undefined) {
342
- update.name = req.body.name;
479
+ let update = {};
480
+
481
+ if (body.name) {
482
+ update.name = body.name;
483
+ }
484
+ if (body.preview_settings) {
485
+ update.preview_settings = body.preview_settings;
486
+ }
487
+
488
+ Namespace.findOneAndUpdate({ id: namespace_id }, update, { new: true, upsert: true }, (err, updatedNamespace) => {
489
+ if (err) {
490
+ winston.error("update namespace error: ", err);
491
+ return res.status(500).send({ success: false, error: err });
343
492
  }
344
493
 
345
- if (req.body.status != undefined) {
346
- update.status = req.body.status;
494
+ let namespaceObj = updatedNamespace.toObject();
495
+ delete namespaceObj._id;
496
+ delete namespaceObj.__v;
497
+ res.status(200).send(namespaceObj);
498
+ })
499
+ })
500
+
501
+ router.delete('/namespace/:id', async (req, res) => {
502
+
503
+ let id_project = req.projectid;
504
+ let namespace_id = req.params.id;
505
+
506
+ let data = {
507
+ namespace: namespace_id
508
+ }
509
+
510
+ if (req.query.contents_only && (req.query.contents_only === true || req.query.contents_only === 'true')) {
511
+
512
+ openaiService.deleteNamespace(data).then(async (resp) => {
513
+ winston.debug("delete namespace resp: ", resp.data);
514
+
515
+ let deleteResponse = await KB.deleteMany({ id_project: id_project, namespace: namespace_id }).catch((err) => {
516
+ winston.error("deleteMany error: ", err);
517
+ return res.status(500).send({ success: false, error: err });
518
+ })
519
+ winston.debug("delete all contents response: ", deleteResponse);
520
+
521
+ return res.status(200).send({ success: true, message: "All contents deleted successfully" })
522
+
523
+ }).catch((err) => {
524
+
525
+ winston.error("deleteNamespace err: ", err);
526
+ winston.error("deleteNamespace err.response: ", err.response);
527
+ if (err.response && err.response.status) {
528
+ let status = err.response.status;
529
+ res.status(status).send({ success: false, statusText: err.response.statusText, error: err.response.data.detail });
530
+ } else {
531
+ res.status(500).send({ success: false, message: "Unable to delete namespace", error: err })
532
+ }
533
+ })
534
+
535
+ } else {
536
+
537
+ let namespace = await Namespace.findOne({ id: namespace_id }).catch((err) => {
538
+ winston.error("findOne namespace error: ", err);
539
+ return res.status(500).send({ success: false, error: err });
540
+ })
541
+ if (namespace.default === true) {
542
+ winston.error("Default namespace cannot be deleted");
543
+ return res.status(403).send({ success: false, error: "Default namespace cannot be deleted" });
347
544
  }
348
545
 
349
- winston.debug("kb update: ", update);
546
+ openaiService.deleteNamespace(data).then(async (resp) => {
547
+ winston.debug("delete namespace resp: ", resp.data);
350
548
 
351
- KB.findByIdAndUpdate(kb_id, update, { new: true }, (err, savedKb) => {
549
+ let deleteResponse = await KB.deleteMany({ id_project: id_project, namespace: namespace_id }).catch((err) => {
550
+ winston.error("deleteMany error: ", err);
551
+ return res.status(500).send({ success: false, error: err });
552
+ })
553
+ winston.debug("delete all contents response: ", deleteResponse);
352
554
 
353
- if (err) {
354
- winston.error("KB findByIdAndUpdate error: ", err);
355
- return res.status(500).send({ success: false, error: err });
356
- }
555
+ let deleteNamespaceResponse = await Namespace.findOneAndDelete({ id: namespace_id }).catch((err) => {
556
+ winston.error("deleteOne namespace error: ", err);
557
+ return res.status(500).send({ success: false, error: err });
558
+ })
559
+ winston.debug("delete namespace response: ", deleteNamespaceResponse);
357
560
 
358
- if (!savedKb) {
359
- winston.debug("Try to updating a non-existing kb");
360
- return res.status(400).send({ success: false, message: "Content not found" })
361
- }
561
+ return res.status(200).send({ success: true, message: "Namespace deleted succesfully" })
362
562
 
363
- res.status(200).send(savedKb)
563
+ }).catch((err) => {
564
+ let status = 400;
565
+ if (err.response && err.response.status) {
566
+ status = err.response.status;
567
+ }
568
+ return res.status(status).send({ success: false, error: "Unable to delete namespace" })
364
569
  })
365
570
 
571
+ }
572
+
573
+
574
+
366
575
  })
576
+ /**
577
+ * ****************************************
578
+ * Namespace Section - End
579
+ * ****************************************
580
+ */
367
581
 
368
- // PROXY PUGLIA AI V2 - START
369
- router.post('/scrape/single', async (req, res) => {
370
582
 
371
- let data = req.body;
372
- winston.debug("/scrape/single data: ", data);
583
+ //----------------------------------------
584
+
373
585
 
374
- KB.findById(data.id, (err, kb) => {
586
+ /**
587
+ * ****************************************
588
+ * Content Section - Start
589
+ * ****************************************
590
+ */
591
+ router.get('/', async (req, res) => {
592
+
593
+ let project_id = req.projectid;
594
+ let namespace = req.query.namespace;
595
+ if (!namespace) {
596
+ return res.status(400).send({ success: false, error: "queryParam 'namespace' is not defined" })
597
+ }
598
+ let status;
599
+ let type;
600
+ let limit = 200;
601
+ let page = 0;
602
+ let direction = -1;
603
+ let sortField = "updatedAt";
604
+ let text;
605
+
606
+ let query = {};
607
+ query["id_project"] = project_id;
608
+ query["namespace"] = namespace;
609
+
610
+ if (req.query.status) {
611
+ status = parseInt(req.query.status);
612
+ query["status"] = status;
613
+ winston.debug("Get kb status: " + status)
614
+ }
615
+
616
+ if (req.query.type) {
617
+ type = req.query.type;
618
+ query["type"] = type;
619
+ winston.debug("Get kb type: " + type);
620
+ }
621
+
622
+ if (req.query.limit) {
623
+ limit = parseInt(req.query.limit);
624
+ winston.debug("Get kb limit: " + limit)
625
+ }
626
+
627
+ if (req.query.page) {
628
+ page = parseInt(req.query.page);
629
+ winston.debug("Get kb page: " + page)
630
+ }
631
+
632
+ let skip = page * limit;
633
+ winston.debug("Get kb skip page: " + skip);
634
+
635
+ if (req.query.direction) {
636
+ direction = parseInt(req.query.direction)
637
+ winston.debug("Get kb direction: " + direction)
638
+ }
639
+
640
+ if (req.query.sortField) {
641
+ sortField = req.query.sortField;
642
+ winston.debug("Get kb sortField: " + sortField)
643
+ }
644
+
645
+ if (req.query.search) {
646
+ text = req.query.search;
647
+ query['source'] = new RegExp(text);
648
+ winston.debug("Get kb text: " + text);
649
+ }
650
+
651
+ let sortQuery = {};
652
+ sortQuery[sortField] = direction;
653
+ winston.debug("Get kb sortQuery: " + sortQuery);
654
+
655
+ KB.countDocuments(query, (err, kbs_count) => {
656
+ if (err) {
657
+ winston.error("Find all kbs error: ", err);
658
+ }
659
+ winston.debug("KBs count: ", kbs_count);
660
+
661
+ KB.find(query)
662
+ .skip(skip)
663
+ .limit(limit)
664
+ .sort(sortQuery)
665
+ .exec((err, kbs) => {
375
666
  if (err) {
376
- winston.error("findById error: ", err);
377
- return res.status(500).send({ success: false, error: err });
667
+ winston.error("Find all kbs error: ", err);
668
+ return res.status(500).send({ success: false, error: err });
378
669
  }
379
670
 
380
- else if (!kb) {
381
- return res.status(404).send({ success: false, error: "Unable to find the kb requested" })
382
- }
383
- else {
384
-
385
- let json = {
386
- id: kb._id,
387
- type: kb.type,
388
- source: kb.source,
389
- content: "",
390
- namespace: kb.namespace
391
- }
392
-
393
- if (kb.content) {
394
- json.content = kb.content;
395
- }
396
-
397
- startScrape(json).then((response) => {
398
- winston.verbose("startScrape response: ", response);
399
- res.status(200).send(response);
400
- }).catch((err) => {
401
- winston.error("startScrape err: ", err);
402
- res.status(500).send({ success: false, error: err });
403
- })
671
+ winston.debug("KBs found: ", kbs);
404
672
 
673
+ let response = {
674
+ count: kbs_count,
675
+ query: {},
676
+ kbs: kbs
677
+ }
678
+ if (status) {
679
+ response.query.status = status;
680
+ }
681
+ if (limit) {
682
+ response.query.limit = limit;
683
+ }
684
+ if (status) {
685
+ response.query.page = page;
686
+ }
687
+ if (sortField) {
688
+ response.query.sortField = sortField;
689
+ }
690
+ if (direction) {
691
+ response.query.direction = direction;
692
+ }
693
+ if (text) {
694
+ response.query.search = text;
405
695
  }
406
- })
407
696
 
408
- })
409
697
 
410
- router.post('/scrape/status', async (req, res) => {
698
+ return res.status(200).send(response);
699
+ })
700
+
701
+ })
411
702
 
412
- let data = req.body;
413
- winston.debug("/scrapeStatus req.body: ", req.body);
414
703
 
415
- let returnObject = false;
704
+ })
705
+
706
+ router.get('/:kb_id', async (req, res) => {
416
707
 
417
- if (req.query &&
418
- req.query.returnObject &&
419
- (req.query.returnObject === true || req.query.returnObject === 'true')) {
420
- returnObject = true;
708
+ let kb_id = req.params.kb_id;
709
+
710
+ KB.findById(kb_id, (err, kb) => {
711
+ if (err) {
712
+ winston.error("Find kb by id error: ", err);
713
+ return res.status(500).send({ success: false, error: err });
421
714
  }
422
715
 
423
- openaiService.scrapeStatus(data).then( async (response) => {
716
+ return res.status(200).send(kb);
717
+ })
718
+ })
424
719
 
425
- winston.debug("scrapeStatus response.data: ", response.data);
720
+ router.post('/', async (req, res) => {
426
721
 
427
- let update = {};
722
+ let project_id = req.projectid;
723
+ let body = req.body;
724
+
725
+ if (!body.namespace) {
726
+ return res.status(400).send({ success: false, error: "parameter 'namespace' is not defined" });
727
+ }
728
+
729
+ let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
730
+ winston.error("find namespaces error: ", err)
731
+ res.status(500).send({ success: false, error: err })
732
+ })
733
+
734
+ if (!namespaces || namespaces.length == 0) {
735
+ let alert = "No namespace found for the selected project " + project_id + ". Cannot add content to a non-existent namespace."
736
+ winston.warn(alert);
737
+ res.status(403).send(alert);
738
+ }
739
+
740
+ let namespaceIds = namespaces.map(namespace => namespace.id);
741
+
742
+ if (!namespaceIds.includes(body.namespace)) {
743
+ return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
744
+ }
745
+
746
+ let quoteManager = req.app.get('quote_manager');
747
+ let limits = await quoteManager.getPlanLimits(req.project);
748
+ let kbs_limit = limits.kbs;
749
+ winston.verbose("Limit of kbs for current plan: " + kbs_limit);
750
+
751
+ let kbs_count = await KB.countDocuments({ id_project: project_id }).exec();
752
+ winston.verbose("Kbs count: " + kbs_count);
753
+
754
+ if (kbs_count >= kbs_limit) {
755
+ return res.status(403).send({ success: false, error: "Maximum number of resources reached for the current plan", plan_limit: kbs_limit })
756
+ }
757
+
758
+ let total_count = kbs_count + 1;
759
+ if (total_count > kbs_limit) {
760
+ return res.status(403).send({ success: false, error: "Cannot exceed the number of resources in the current plan", plan_limit: kbs_limit })
761
+ }
762
+ let new_kb = {
763
+ id_project: project_id,
764
+ name: body.name,
765
+ type: body.type,
766
+ source: body.source,
767
+ content: body.content,
768
+ namespace: body.namespace,
769
+ status: -1
770
+ }
771
+ if (!new_kb.namespace) {
772
+ new_kb.namespace = project_id;
773
+ }
774
+ winston.debug("adding kb: ", new_kb);
775
+
776
+ KB.findOneAndUpdate({ id_project: project_id, type: 'url', source: new_kb.source }, new_kb, { upsert: true, new: true, rawResult: true }, async (err, raw) => {
777
+ if (err) {
778
+ winston.error("findOneAndUpdate with upsert error: ", err);
779
+ res.status(500).send({ success: false, error: err });
780
+ }
781
+ else {
428
782
 
429
- if (response.data.status_code) {
430
- // update.status = response.data.status_code;
431
- update.status = await statusConverter(response.data.status_code)
432
-
433
- }
783
+ res.status(200).send(raw);
434
784
 
435
- KB.findByIdAndUpdate(data.id, update, { new: true }, (err, savedKb) => {
785
+ let webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
436
786
 
437
- if (err) {
438
- winston.verbose("Status was successfully recovered, but the update on the db failed");
439
- winston.error("find kb by id and updated error: ", err);
787
+ let json = {
788
+ id: raw.value._id,
789
+ type: raw.value.type,
790
+ source: raw.value.source,
791
+ content: "",
792
+ namespace: raw.value.namespace,
793
+ webhook: webhook
794
+ }
795
+ winston.debug("json: ", json);
440
796
 
441
- if (returnObject) {
442
- return res.status(206).send({ warning: "Unable to udpate content on db", message: "The original reply was forwarded", data: response.data });
443
- } else {
444
- return res.status(200).send(response.data);
445
- }
446
- }
797
+ if (raw.value.content) {
798
+ json.content = raw.value.content;
799
+ }
447
800
 
448
- if (returnObject) {
449
- return res.status(200).send(savedKb);
450
- } else {
451
- return res.status(200).send(response.data);
452
- }
453
- })
801
+ let resources = [];
454
802
 
455
- }).catch((err) => {
456
- winston.error("scrapeStatus err: ", err);
457
- let status = err.response.status;
458
- res.status(status).send({ statusText: err.response.statusText, error: err.response.data.detail });
459
- })
460
- })
803
+ resources.push(json);
804
+ scheduleScrape(resources);
461
805
 
462
- router.post('/qa', async (req, res) => {
463
- let data = req.body;
464
- // add or override namespace value if it is passed for security reason
465
- data.namespace = req.projectid;
466
- winston.debug("/qa data: ", data);
467
-
468
- // if (req.body.namespace != req.projectid) {
469
- // return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project."})
470
- // }
471
-
472
- if (!data.gptkey) {
473
- let gptkey = process.env.GPTKEY;
474
- if (!gptkey) {
475
- return res.status(403).send({ success: false, error: "GPT apikey undefined" })
476
- }
477
- data.gptkey = gptkey;
478
806
  }
807
+ })
808
+
809
+ })
479
810
 
480
- openaiService.askNamespace(data).then((resp) => {
481
- winston.debug("qa resp: ", resp.data);
482
- let answer = resp.data;
811
+ router.post('/multi', upload.single('uploadFile'), async (req, res) => {
483
812
 
484
- let id = answer.id;
485
- let index = id.indexOf("#");
486
- if (index != -1) {
487
- id = id.substring(index + 1);
488
- }
813
+ let list;
814
+ if (req.file) {
815
+ file_string = req.file.buffer.toString('utf-8');
816
+ list = file_string.trim().split('\n');
817
+ } else {
818
+ list = req.body.list;
819
+ }
820
+
821
+ let project_id = req.projectid;
822
+
823
+ let namespace_id = req.query.namespace;
824
+ if (!namespace_id) {
825
+ return res.status(400).send({ success: false, error: "queryParam 'namespace' is not defined" })
826
+ }
827
+
828
+ let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
829
+ winston.error("find namespaces error: ", err)
830
+ res.status(500).send({ success: false, error: err })
831
+ })
832
+
833
+ if (!namespaces || namespaces.length == 0) {
834
+ let alert = "No namespace found for the selected project " + project_id + ". Cannot add content to a non-existent namespace."
835
+ winston.warn(alert);
836
+ res.status(403).send({ success: false, error: alert });
837
+ }
838
+
839
+ let namespaceIds = namespaces.map(namespace => namespace.id);
840
+
841
+ if (!namespaceIds.includes(namespace_id)) {
842
+ return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
843
+ }
844
+
845
+ let quoteManager = req.app.get('quote_manager');
846
+ let limits = await quoteManager.getPlanLimits(req.project);
847
+ let kbs_limit = limits.kbs;
848
+ winston.verbose("Limit of kbs for current plan: " + kbs_limit);
849
+
850
+ let kbs_count = await KB.countDocuments({ id_project: project_id }).exec();
851
+ winston.verbose("Kbs count: " + kbs_count);
852
+
853
+ if (kbs_count >= kbs_limit) {
854
+ return res.status(403).send({ success: false, error: "Maximum number of resources reached for the current plan", plan_limit: kbs_limit })
855
+ }
856
+
857
+ let total_count = kbs_count + list.length;
858
+ if (total_count > kbs_limit) {
859
+ return res.status(403).send({ success: false, error: "Cannot exceed the number of resources in the current plan", plan_limit: kbs_limit })
860
+ }
861
+
862
+ if (list.length > 300) {
863
+ winston.error("Too many urls. Can't index more than 300 urls at a time.");
864
+ return res.status(403).send({ success: false, error: "Too many urls. Can't index more than 300 urls at a time." })
865
+ }
866
+
867
+ let webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
868
+
869
+ let kbs = [];
870
+ list.forEach(url => {
871
+ kbs.push({
872
+ id_project: project_id,
873
+ name: url,
874
+ source: url,
875
+ type: 'url',
876
+ content: "",
877
+ namespace: namespace_id,
878
+ status: -1
879
+ })
880
+ })
881
+
882
+ let operations = kbs.map(doc => {
883
+ return {
884
+ updateOne: {
885
+ filter: { id_project: doc.id_project, type: 'url', source: doc.source },
886
+ update: doc,
887
+ upsert: true,
888
+ returnOriginal: false
889
+ }
890
+ }
891
+ })
489
892
 
490
- KB.findById(id, (err, resource) => {
893
+ saveBulk(operations, kbs, project_id).then((result) => {
491
894
 
492
- if (err) {
493
- winston.error("Unable to find resource with id " + id + " in namespace " + answer.namespace + ". The standard answer is returned.")
494
- return res.status(200).send(resp.data);
495
- }
895
+ let resources = result.map(({ name, status, __v, createdAt, updatedAt, id_project, ...keepAttrs }) => keepAttrs)
896
+ resources = resources.map(({ _id, ...rest }) => {
897
+ return { id: _id, webhook: webhook, ...rest };
898
+ });
899
+ winston.verbose("resources to be sent to worker: ", resources);
900
+ scheduleScrape(resources);
901
+ res.status(200).send(result);
496
902
 
497
- answer.source = resource.name;
498
- return res.status(200).send(answer);
499
- })
500
-
903
+ }).catch((err) => {
904
+ winston.error("Unable to save kbs in bulk ", err)
905
+ res.status(500).send(err);
906
+ })
501
907
 
502
- }).catch((err) => {
503
- winston.error("qa err: ", err);
504
- console.log(err.response)
505
- if (err.response
506
- && err.response.status) {
507
- let status = err.response.status;
508
- res.status(status).send({ success: false, statusText: err.response.statusText, error: err.response.data.detail });
509
- }
510
- else {
511
- res.status(500).send({ success: false, error: err });
512
- }
513
-
514
- })
515
908
  })
516
909
 
517
- router.delete('/delete', async (req, res) => {
910
+ router.post('/sitemap', async (req, res) => {
518
911
 
519
- let data = req.body;
520
- winston.debug("/delete data: ", data);
912
+ let sitemap_url = req.body.sitemap;
521
913
 
522
- openaiService.deleteIndex(data).then((resp) => {
523
- winston.debug("delete resp: ", resp.data);
524
- res.status(200).send(resp.data);
525
- }).catch((err) => {
526
- winston.error("delete err: ", err);
527
- let status = err.response.status;
528
- res.status(status).send({ statusText: err.response.statusText, error: err.response.data.detail });
529
- })
914
+ const sitemap = new Sitemapper({
915
+ url: sitemap_url,
916
+ timeout: 15000
917
+ });
918
+
919
+ sitemap.fetch().then((data) => {
920
+ winston.debug("data: ", data);
921
+ res.status(200).send(data);
922
+ }).catch((err) => {
923
+ console.error("err ", err)
924
+ res.status(500).send({ success: false, error: err });
925
+ })
530
926
 
531
927
  })
532
928
 
533
- router.delete('/deleteall', async (req, res) => {
929
+ router.put('/:kb_id', async (req, res) => {
534
930
 
535
- let data = req.body;
536
- winston.debug('/delete all data: ', data);
931
+ let kb_id = req.params.kb_id;
932
+ winston.verbose("update kb_id " + kb_id);
933
+
934
+ let update = {};
935
+
936
+ if (req.body.name != undefined) {
937
+ update.name = req.body.name;
938
+ }
939
+
940
+ if (req.body.status != undefined) {
941
+ update.status = req.body.status;
942
+ }
943
+
944
+ winston.debug("kb update: ", update);
945
+
946
+ KB.findByIdAndUpdate(kb_id, update, { new: true }, (err, savedKb) => {
947
+
948
+ if (err) {
949
+ winston.error("KB findByIdAndUpdate error: ", err);
950
+ return res.status(500).send({ success: false, error: err });
951
+ }
952
+
953
+ if (!savedKb) {
954
+ winston.debug("Try to updating a non-existing kb");
955
+ return res.status(400).send({ success: false, message: "Content not found" })
956
+ }
957
+
958
+ res.status(200).send(savedKb)
959
+ })
537
960
 
538
- openaiService.deleteNamespace(data).then((resp) => {
539
- winston.debug("delete namespace resp: ", resp.data);
540
- res.status(200).send(resp.data);
541
- }).catch((err) => {
542
- winston.error("delete namespace err: ", err);
543
- let status = err.response.status;
544
- res.status(status).send({ statusText: err.response.statusText, error: err.response.data.detail });
545
- })
546
961
  })
547
- // PROXY PUGLIA AI V2 - END
548
962
 
549
963
  router.delete('/:kb_id', async (req, res) => {
550
964
 
551
- let project_id = req.projectid;
552
- let kb_id = req.params.kb_id;
553
- winston.verbose("delete kb_id " + kb_id);
965
+ let project_id = req.projectid;
966
+ let kb_id = req.params.kb_id;
967
+ winston.verbose("delete kb_id " + kb_id);
554
968
 
555
- let data = {
556
- id: kb_id,
557
- namespace: project_id
558
- }
969
+ let data = {
970
+ id: kb_id,
971
+ namespace: project_id
972
+ }
973
+
974
+ openaiService.deleteIndex(data).then((resp) => {
975
+ winston.debug("delete resp: ", resp.data);
559
976
 
560
- openaiService.deleteIndex(data).then((resp) => {
561
- winston.debug("delete resp: ", resp.data);
977
+ if (resp.data.success === true) {
978
+ KB.findByIdAndDelete(kb_id, (err, deletedKb) => {
562
979
 
563
- if (resp.data.success === true) {
564
- KB.findByIdAndDelete(kb_id, (err, deletedKb) => {
980
+ if (err) {
981
+ winston.error("Delete kb error: ", err);
982
+ return res.status(500).send({ success: false, error: err });
983
+ }
984
+ res.status(200).send(deletedKb);
985
+ })
565
986
 
566
- if (err) {
567
- winston.error("Delete kb error: ", err);
568
- return res.status(500).send({ success: false, error: err });
569
- }
570
- res.status(200).send(deletedKb);
571
- })
987
+ } else {
988
+ winston.verbose("resp.data: ", resp.data);
572
989
 
990
+ KB.findOneAndDelete({ _id: kb_id, status: { $in: [-1, 3, 4, 100, 300, 400] } }, (err, deletedKb) => {
991
+ if (err) {
992
+ winston.error("findOneAndDelete err: ", err);
993
+ return res.status(500).send({ success: false, error: "Unable to delete the content due to an error" })
994
+ }
995
+ else if (!deletedKb) {
996
+ winston.verbose("Unable to delete the content in indexing status")
997
+ return res.status(500).send({ success: false, error: "Unable to delete the content in indexing status" })
573
998
  } else {
574
- winston.verbose("resp.data: ", resp.data);
575
-
576
- KB.findOneAndDelete({ _id: kb_id, status: { $in: [-1, 3, 4, 100, 300, 400] } }, (err, deletedKb) => {
577
- if (err) {
578
- winston.error("findOneAndDelete err: ", err);
579
- return res.status(500).send({ success: false, error: "Unable to delete the content due to an error" })
580
- }
581
- else if (!deletedKb) {
582
- winston.verbose("Unable to delete the content in indexing status")
583
- return res.status(500).send({ success: false, error: "Unable to delete the content in indexing status" })
584
- } else {
585
- res.status(200).send(deletedKb);
586
- }
587
- })
999
+ res.status(200).send(deletedKb);
588
1000
  }
1001
+ })
1002
+ }
589
1003
 
590
- }).catch((err) => {
591
- let status = err.response.status;
592
- res.status(status).send({ success: false, statusText: err.response.statusText, error: err.response.data.detail });
593
- })
1004
+ }).catch((err) => {
1005
+ let status = err.response.status;
1006
+ res.status(status).send({ success: false, statusText: err.response.statusText, error: err.response.data.detail });
1007
+ })
594
1008
 
595
1009
  })
596
1010
 
597
- router.delete('/namespace/:namespace_id', async (req, res) => {
598
-
599
- let id_project = req.projectid;
600
- let namespace_id = req.params.namespace_id;
1011
+ /**
1012
+ * ****************************************
1013
+ * Content Section - End
1014
+ * ****************************************
1015
+ */
601
1016
 
602
- let data = {
603
- namespace: namespace_id
604
- }
605
1017
 
606
- openaiService.deleteNamespace(data).then((resp) => {
607
- winston.debug("delete namespace resp: ", resp.data);
1018
+ //----------------------------------------
608
1019
 
609
- KB.deleteMany({ id_project: id_project, namespace: namespace_id }, (err, deleteResponse) => {
610
- if (err) {
611
- winston.error("deleteMany error: ", err);
612
- return res.status(500).send({ success: false, error: "Unable to delete namespace due to an error" })
613
- }
614
- winston.debug("deleteResponse: ", deleteResponse);
615
- res.status(200).send({ success: true, message: "Namespace deleted succesfully" })
616
- })
617
1020
 
618
- }).catch((err) => {
619
- let status = err.response.status;
620
- res.status(status).send({ success: false, error: "Unable to delete namespace"})
621
- })
622
- })
1021
+ /**
1022
+ * ****************************************
1023
+ * Utils Methods Section - Start
1024
+ * ****************************************
1025
+ */
623
1026
 
624
1027
  async function saveBulk(operations, kbs, project_id) {
625
1028
 
626
- return new Promise((resolve, reject) => {
627
- KB.bulkWrite(operations, { ordered: false }).then((result) => {
628
- winston.verbose("bulkWrite operations result: ", result);
629
-
630
- KB.find({ id_project: project_id, source: { $in: kbs.map(kb => kb.source) } }).lean().then((documents) => {
631
- winston.debug("documents: ", documents);
632
- resolve(documents)
633
- }).catch((err) => {
634
- winston.error("Error finding documents ", err)
635
- reject(err);
636
- })
637
-
638
- }).catch((err) => {
639
- reject(err);
640
- })
1029
+ return new Promise((resolve, reject) => {
1030
+ KB.bulkWrite(operations, { ordered: false }).then((result) => {
1031
+ winston.verbose("bulkWrite operations result: ", result);
1032
+
1033
+ KB.find({ id_project: project_id, source: { $in: kbs.map(kb => kb.source) } }).lean().then((documents) => {
1034
+ winston.debug("documents: ", documents);
1035
+ resolve(documents)
1036
+ }).catch((err) => {
1037
+ winston.error("Error finding documents ", err)
1038
+ reject(err);
1039
+ })
1040
+
1041
+ }).catch((err) => {
1042
+ reject(err);
641
1043
  })
1044
+ })
642
1045
 
643
1046
  }
644
1047
 
645
1048
  async function statusConverter(status) {
646
- return new Promise((resolve) => {
647
-
648
- let td_status;
649
- switch(status) {
650
- case 0:
651
- td_status = -1;
652
- break;
653
- case 2:
654
- td_status = 200;
655
- break;
656
- case 3:
657
- td_status = 300;
658
- break;
659
- case 4:
660
- td_status = 400;
661
- break;
662
- default:
663
- td_status = -1
664
- }
665
- resolve(td_status);
666
- })
1049
+ return new Promise((resolve) => {
1050
+
1051
+ let td_status;
1052
+ switch (status) {
1053
+ case 0:
1054
+ td_status = -1;
1055
+ break;
1056
+ case 2:
1057
+ td_status = 200;
1058
+ break;
1059
+ case 3:
1060
+ td_status = 300;
1061
+ break;
1062
+ case 4:
1063
+ td_status = 400;
1064
+ break;
1065
+ default:
1066
+ td_status = -1
1067
+ }
1068
+ resolve(td_status);
1069
+ })
667
1070
  }
668
1071
 
669
1072
  async function updateStatus(id, status) {
670
- return new Promise((resolve) => {
671
-
672
- KB.findByIdAndUpdate(id, { status: status }, { new: true }, (err, updatedKb) => {
673
- if (err) {
674
- resolve(false)
675
- } else if (!updatedKb) {
676
- winston.verbose("Unable to update status. Data source not found.")
677
- resolve(false)
678
- } else {
679
- winston.debug("updatedKb: ", updatedKb)
680
- resolve(true);
681
- }
682
- })
1073
+ return new Promise((resolve) => {
1074
+
1075
+ KB.findByIdAndUpdate(id, { status: status }, { new: true }, (err, updatedKb) => {
1076
+ if (err) {
1077
+ resolve(false)
1078
+ } else if (!updatedKb) {
1079
+ winston.verbose("Unable to update status. Data source not found.")
1080
+ resolve(false)
1081
+ } else {
1082
+ winston.debug("updatedKb: ", updatedKb)
1083
+ resolve(true);
1084
+ }
683
1085
  })
1086
+ })
684
1087
  }
685
1088
 
686
1089
  async function scheduleScrape(resources) {
687
1090
 
688
- // let data = {
689
- // resources: resources
690
- // }
691
- let scheduler = new Scheduler({ jobManager: jobManager });
692
-
693
- resources.forEach(r => {
694
- winston.debug("Schedule job with following data: ", r);
695
- scheduler.trainSchedule(r, async (err, result) => {
696
- let error_code = 100;
697
- if (err) {
698
- winston.error("Scheduling error: ", err);
699
- error_code = 400;
700
- } else {
701
- winston.info("Scheduling result: ", result);
702
- }
703
- await updateStatus(r.id, error_code);
704
- });
705
- })
1091
+ // let data = {
1092
+ // resources: resources
1093
+ // }
1094
+ let scheduler = new Scheduler({ jobManager: jobManager });
1095
+
1096
+ resources.forEach(r => {
1097
+ winston.debug("Schedule job with following data: ", r);
1098
+ scheduler.trainSchedule(r, async (err, result) => {
1099
+ let error_code = 100;
1100
+ if (err) {
1101
+ winston.error("Scheduling error: ", err);
1102
+ error_code = 400;
1103
+ } else {
1104
+ winston.info("Scheduling result: ", result);
1105
+ }
1106
+ await updateStatus(r.id, error_code);
1107
+ });
1108
+ })
706
1109
 
707
1110
 
708
- return true;
1111
+ return true;
709
1112
  }
710
1113
 
711
1114
  async function startScrape(data) {
712
1115
 
713
- if (!data.gptkey) {
714
- let gptkey = process.env.GPTKEY;
715
- if (!gptkey) {
716
- return { error: "GPT apikey undefined" }
717
- }
718
- data.gptkey = gptkey;
1116
+ if (!data.gptkey) {
1117
+ let gptkey = process.env.GPTKEY;
1118
+ if (!gptkey) {
1119
+ return { error: "GPT apikey undefined" }
719
1120
  }
720
-
721
- return new Promise((resolve, reject) => {
722
- openaiService.singleScrape(data).then(async (resp) => {
723
- winston.debug("singleScrape resp: ", resp.data);
724
- let status_updated = await updateStatus(data.id, 100);
725
- winston.verbose("status of kb " + data.id + " updated: " + status_updated);
726
- resolve(resp.data);
727
- }).catch((err) => {
728
- winston.error("singleScrape err: ", err);
729
- reject(err);
730
- })
1121
+ data.gptkey = gptkey;
1122
+ }
1123
+
1124
+ return new Promise((resolve, reject) => {
1125
+ openaiService.singleScrape(data).then(async (resp) => {
1126
+ winston.debug("singleScrape resp: ", resp.data);
1127
+ let status_updated = await updateStatus(data.id, 100);
1128
+ winston.verbose("status of kb " + data.id + " updated: " + status_updated);
1129
+ resolve(resp.data);
1130
+ }).catch((err) => {
1131
+ winston.error("singleScrape err: ", err);
1132
+ reject(err);
731
1133
  })
1134
+ })
732
1135
  }
1136
+ /**
1137
+ * ****************************************
1138
+ * Utils Methods Section - End
1139
+ * ****************************************
1140
+ */
1141
+
1142
+
733
1143
 
734
1144
  module.exports = router;