@tiledesk/tiledesk-server 2.7.26 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
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;