@tiledesk/tiledesk-server 2.15.7 → 2.16.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/CHANGELOG.md +10 -1
- package/event/messageEvent.js +24 -0
- package/models/kb_setting.js +5 -0
- package/models/request.js +1 -0
- package/package.json +2 -2
- package/pubmodules/queue/reconnect.js +16 -0
- package/pubmodules/routing-queue/listenerQueued.js +22 -3
- package/pubmodules/scheduler/tasks/closeAgentUnresponsiveRequestTask.js +2 -1
- package/pubmodules/scheduler/tasks/closeBotUnresponsiveRequestTask.js +2 -1
- package/routes/kb.js +278 -120
- package/routes/request.js +174 -92
- package/services/aiManager.js +72 -3
- package/test/fixtures/example-kb-faqs.csv +2 -2
- package/test/fixtures/exported_namespace.json +2 -1
- package/test/kbRoute.js +125 -12
- package/utils/arrayUtil.js +35 -1
package/test/kbRoute.js
CHANGED
|
@@ -273,7 +273,7 @@ describe('KbRoute', () => {
|
|
|
273
273
|
chai.request(server)
|
|
274
274
|
.post('/' + savedProject._id + '/kb/namespace/import/' + namespace_id)
|
|
275
275
|
.auth(email, pwd)
|
|
276
|
-
|
|
276
|
+
//.set('Content-Type', 'text/plain')
|
|
277
277
|
.attach('uploadFile', fs.readFileSync(path.resolve(__dirname, './fixtures/exported_namespace.json')), 'exported_namespace.json')
|
|
278
278
|
.end((err, res) => {
|
|
279
279
|
|
|
@@ -285,7 +285,28 @@ describe('KbRoute', () => {
|
|
|
285
285
|
expect(res.body.success).to.equal(true);
|
|
286
286
|
expect(res.body.message).to.equal("Contents imported successfully");
|
|
287
287
|
|
|
288
|
-
|
|
288
|
+
chai.request(server)
|
|
289
|
+
.get('/' + savedProject._id + '/kb/?namespace=' + namespace_id)
|
|
290
|
+
.auth(email, pwd)
|
|
291
|
+
.end((err, res) => {
|
|
292
|
+
if (err) { console.error("err: ", err); }
|
|
293
|
+
if (log) { console.log("get namespace res.body: ", res.body); }
|
|
294
|
+
|
|
295
|
+
res.should.have.status(200);
|
|
296
|
+
res.body.should.be.a('object');
|
|
297
|
+
expect(res.body.count).to.equal(3);
|
|
298
|
+
expect(res.body.kbs.length).to.equal(3);
|
|
299
|
+
|
|
300
|
+
let content_with_tags = res.body.kbs.find(kb => kb.source === 'Example content');
|
|
301
|
+
expect(content_with_tags.tags.length).to.equal(2);
|
|
302
|
+
expect(content_with_tags.tags[0]).to.equal('tag1');
|
|
303
|
+
expect(content_with_tags.tags[1]).to.equal('tag2');
|
|
304
|
+
|
|
305
|
+
let content_without_tags = res.body.kbs.find(kb => kb.source !== 'Example content');
|
|
306
|
+
expect(content_without_tags.tags).to.equal(undefined);
|
|
307
|
+
|
|
308
|
+
done();
|
|
309
|
+
})
|
|
289
310
|
|
|
290
311
|
})
|
|
291
312
|
|
|
@@ -514,7 +535,8 @@ describe('KbRoute', () => {
|
|
|
514
535
|
type: "url",
|
|
515
536
|
source: "https://www.exampleurl5.com",
|
|
516
537
|
content: "",
|
|
517
|
-
namespace: namespace_id
|
|
538
|
+
namespace: namespace_id,
|
|
539
|
+
tags: ["test", "example"]
|
|
518
540
|
}
|
|
519
541
|
|
|
520
542
|
chai.request(server)
|
|
@@ -539,6 +561,9 @@ describe('KbRoute', () => {
|
|
|
539
561
|
expect(realResponse.value.type).to.equal("url")
|
|
540
562
|
expect(realResponse.value.source).to.equal("https://www.exampleurl5.com")
|
|
541
563
|
expect(realResponse.value.status).to.equal(-1)
|
|
564
|
+
expect(realResponse.value.tags.length).to.equal(2);
|
|
565
|
+
expect(realResponse.value.tags[0]).to.equal("test");
|
|
566
|
+
expect(realResponse.value.tags[1]).to.equal("example");
|
|
542
567
|
should.not.exist(realResponse.engine)
|
|
543
568
|
should.not.exist(realResponse.value.engine)
|
|
544
569
|
should.not.exist(realResponse.embedding)
|
|
@@ -549,6 +574,9 @@ describe('KbRoute', () => {
|
|
|
549
574
|
expect(scheduleJson.type).to.equal("url")
|
|
550
575
|
expect(scheduleJson.source).to.equal("https://www.exampleurl5.com")
|
|
551
576
|
expect(scheduleJson.hybrid).to.equal(false);
|
|
577
|
+
expect(scheduleJson.tags.length).to.equal(2);
|
|
578
|
+
expect(scheduleJson.tags[0]).to.equal("test");
|
|
579
|
+
expect(scheduleJson.tags[1]).to.equal("example");
|
|
552
580
|
should.exist(scheduleJson.engine)
|
|
553
581
|
should.exist(scheduleJson.embedding)
|
|
554
582
|
|
|
@@ -587,7 +615,8 @@ describe('KbRoute', () => {
|
|
|
587
615
|
type: "text",
|
|
588
616
|
source: "example_text1",
|
|
589
617
|
content: "Example text",
|
|
590
|
-
namespace: namespace_id
|
|
618
|
+
namespace: namespace_id,
|
|
619
|
+
tags: ["test", "example"]
|
|
591
620
|
}
|
|
592
621
|
|
|
593
622
|
chai.request(server)
|
|
@@ -603,6 +632,7 @@ describe('KbRoute', () => {
|
|
|
603
632
|
res.body.should.be.a('object');
|
|
604
633
|
|
|
605
634
|
let realResponse = res.body.data;
|
|
635
|
+
console.log("realResponse: ", realResponse);
|
|
606
636
|
expect(realResponse.value.id_project).to.equal(namespace_id)
|
|
607
637
|
expect(realResponse.value.name).to.equal("example_text1")
|
|
608
638
|
expect(realResponse.value.type).to.equal("text")
|
|
@@ -610,7 +640,10 @@ describe('KbRoute', () => {
|
|
|
610
640
|
expect(realResponse.value.status).to.equal(-1)
|
|
611
641
|
expect(typeof realResponse.value.scrape_type === "undefined").to.be.true;
|
|
612
642
|
expect(typeof realResponse.value.scrape_options === "undefined").to.be.true;
|
|
613
|
-
|
|
643
|
+
expect(realResponse.value.tags.length).to.equal(2);
|
|
644
|
+
expect(realResponse.value.tags[0]).to.equal("test");
|
|
645
|
+
expect(realResponse.value.tags[1]).to.equal("example");
|
|
646
|
+
|
|
614
647
|
done();
|
|
615
648
|
})
|
|
616
649
|
})
|
|
@@ -885,6 +918,66 @@ describe('KbRoute', () => {
|
|
|
885
918
|
})
|
|
886
919
|
}).timeout(20000)
|
|
887
920
|
|
|
921
|
+
it('add-single-faq-success', (done) => {
|
|
922
|
+
var email = "test-signup-" + Date.now() + "@email.com";
|
|
923
|
+
var pwd = "pwd";
|
|
924
|
+
|
|
925
|
+
userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) {
|
|
926
|
+
projectService.create("test-faqkb-create", savedUser._id).then(function (savedProject) {
|
|
927
|
+
|
|
928
|
+
chai.request(server)
|
|
929
|
+
.get('/' + savedProject._id + '/kb/namespace/all')
|
|
930
|
+
.auth(email, pwd)
|
|
931
|
+
.end((err, res) => {
|
|
932
|
+
if (err) { console.error("err: ", err); }
|
|
933
|
+
if (log) { console.log("res.body: ", res.body) }
|
|
934
|
+
|
|
935
|
+
res.should.have.status(200);
|
|
936
|
+
expect(res.body.length).to.equal(1);
|
|
937
|
+
|
|
938
|
+
let namespace_id = res.body[0].id;
|
|
939
|
+
|
|
940
|
+
let content = {
|
|
941
|
+
name: "Sample question",
|
|
942
|
+
source: "Sample question",
|
|
943
|
+
content: "Sample question\nSample answer",
|
|
944
|
+
type: "faq",
|
|
945
|
+
tags: ["tag1", "tag2"],
|
|
946
|
+
namespace: namespace_id
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
chai.request(server)
|
|
950
|
+
.post('/' + savedProject._id + '/kb')
|
|
951
|
+
.auth(email, pwd)
|
|
952
|
+
.send(content)
|
|
953
|
+
.end((err, res) => {
|
|
954
|
+
if (err) { console.error("err: ", err); }
|
|
955
|
+
if (log) { console.log("res.body: ", res.body) }
|
|
956
|
+
|
|
957
|
+
res.should.have.status(200);
|
|
958
|
+
res.body.should.be.a('object');
|
|
959
|
+
|
|
960
|
+
let realResponse = res.body.data;
|
|
961
|
+
expect(realResponse.value.namespace).to.equal(namespace_id);
|
|
962
|
+
expect(realResponse.value.type).to.equal("faq");
|
|
963
|
+
expect(realResponse.value.source).to.equal("Sample question");
|
|
964
|
+
expect(realResponse.value.content).to.equal("Sample question\nSample answer");
|
|
965
|
+
expect(realResponse.value.tags.length).to.equal(2);
|
|
966
|
+
expect(realResponse.value.tags[0]).to.equal("tag1");
|
|
967
|
+
expect(realResponse.value.tags[1]).to.equal("tag2");
|
|
968
|
+
|
|
969
|
+
done();
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
});
|
|
973
|
+
|
|
974
|
+
});
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
})
|
|
978
|
+
});
|
|
979
|
+
})
|
|
980
|
+
|
|
888
981
|
it('add-multiple-faqs-with-csv', (done) => {
|
|
889
982
|
|
|
890
983
|
var email = "test-signup-" + Date.now() + "@email.com";
|
|
@@ -916,14 +1009,15 @@ describe('KbRoute', () => {
|
|
|
916
1009
|
chai.request(server)
|
|
917
1010
|
.post('/' + savedProject._id + '/kb/csv?namespace=' + namespace_id)
|
|
918
1011
|
.auth(email, pwd)
|
|
919
|
-
|
|
920
|
-
.attach('uploadFile', fs.readFileSync(path.resolve(__dirname, './fixtures/example-kb-faqs.csv')), 'example-kb-faqs.csv')
|
|
1012
|
+
//.set('Content-Type', 'text/csv')
|
|
921
1013
|
.field('delimiter', ';')
|
|
1014
|
+
.field('tags', JSON.stringify(['tag1', 'tag2']))
|
|
1015
|
+
.attach('uploadFile', fs.readFileSync(path.resolve(__dirname, './fixtures/example-kb-faqs.csv')), 'example-kb-faqs.csv')
|
|
922
1016
|
.end((err, res) => {
|
|
923
1017
|
|
|
924
1018
|
if (err) { console.error("err: ", err); }
|
|
925
1019
|
if (log) { console.log("res.body: ", res.body) }
|
|
926
|
-
|
|
1020
|
+
console.log("res.body: ", res.body)
|
|
927
1021
|
res.should.have.status(200);
|
|
928
1022
|
res.body.should.be.a('object');
|
|
929
1023
|
expect(res.body.success).to.equal(true);
|
|
@@ -931,6 +1025,7 @@ describe('KbRoute', () => {
|
|
|
931
1025
|
|
|
932
1026
|
let realResponse = res.body.data;
|
|
933
1027
|
realResponse.should.be.a('array');
|
|
1028
|
+
console.log("realResponse: ", realResponse[0]);
|
|
934
1029
|
expect(realResponse.length).to.equal(2);
|
|
935
1030
|
expect(realResponse[0].namespace).to.equal(namespace_id);
|
|
936
1031
|
expect(realResponse[0].type).to.equal('faq');
|
|
@@ -983,7 +1078,7 @@ describe('KbRoute', () => {
|
|
|
983
1078
|
chai.request(server)
|
|
984
1079
|
.post('/' + savedProject._id + '/kb/multi?namespace=123456')
|
|
985
1080
|
.auth(email, pwd)
|
|
986
|
-
|
|
1081
|
+
//.set('Content-Type', 'text/plain')
|
|
987
1082
|
.attach('uploadFile', fs.readFileSync(path.resolve(__dirname, './fixtures/kbUrlsList.txt')), 'kbUrlsList.txt')
|
|
988
1083
|
.end((err, res) => {
|
|
989
1084
|
|
|
@@ -1030,7 +1125,7 @@ describe('KbRoute', () => {
|
|
|
1030
1125
|
chai.request(server)
|
|
1031
1126
|
.post('/' + savedProject._id + '/kb/multi?namespace=fakenamespaceid')
|
|
1032
1127
|
.auth(email, pwd)
|
|
1033
|
-
|
|
1128
|
+
//.set('Content-Type', 'text/plain')
|
|
1034
1129
|
.attach('uploadFile', fs.readFileSync(path.resolve(__dirname, './fixtures/kbUrlsList.txt')), 'kbUrlsList.txt')
|
|
1035
1130
|
.end((err, res) => {
|
|
1036
1131
|
|
|
@@ -1077,8 +1172,14 @@ describe('KbRoute', () => {
|
|
|
1077
1172
|
chai.request(server)
|
|
1078
1173
|
.post('/' + savedProject._id + '/kb/multi?namespace=' + namespace_id)
|
|
1079
1174
|
.auth(email, pwd)
|
|
1080
|
-
.
|
|
1081
|
-
.
|
|
1175
|
+
.field('refresh_rate', 'never')
|
|
1176
|
+
.field('scrape_type', '2')
|
|
1177
|
+
.field('tags', JSON.stringify(['tag1', 'tag2']))
|
|
1178
|
+
.attach(
|
|
1179
|
+
'uploadFile',
|
|
1180
|
+
fs.readFileSync(path.resolve(__dirname, './fixtures/kbUrlsList.txt')),
|
|
1181
|
+
'kbUrlsList.txt'
|
|
1182
|
+
)
|
|
1082
1183
|
.end((err, res) => {
|
|
1083
1184
|
|
|
1084
1185
|
if (err) { console.error("err: ", err); }
|
|
@@ -1090,15 +1191,24 @@ describe('KbRoute', () => {
|
|
|
1090
1191
|
expect(realResponse.length).to.equal(4);
|
|
1091
1192
|
expect(realResponse[0].namespace).to.equal(namespace_id);
|
|
1092
1193
|
expect(realResponse[0].source).to.equal('https://gethelp.tiledesk.com/articles/article1');
|
|
1194
|
+
expect(realResponse[0].tags.length).to.equal(2);
|
|
1195
|
+
expect(realResponse[0].tags[0]).to.equal('tag1');
|
|
1196
|
+
expect(realResponse[0].tags[1]).to.equal('tag2');
|
|
1093
1197
|
should.not.exist(realResponse[0].engine);
|
|
1094
1198
|
should.not.exist(realResponse[0].embedding);
|
|
1095
1199
|
expect(realResponse[1].namespace).to.equal(namespace_id);
|
|
1096
1200
|
expect(realResponse[1].source).to.equal('https://gethelp.tiledesk.com/articles/article2');
|
|
1201
|
+
expect(realResponse[1].tags.length).to.equal(2);
|
|
1202
|
+
expect(realResponse[1].tags[0]).to.equal('tag1');
|
|
1203
|
+
expect(realResponse[1].tags[1]).to.equal('tag2');
|
|
1097
1204
|
|
|
1098
1205
|
let scheduleJson = res.body.schedule_json;
|
|
1099
1206
|
expect(scheduleJson.length).to.equal(4);
|
|
1100
1207
|
expect(scheduleJson[0].namespace).to.equal(namespace_id);
|
|
1101
1208
|
expect(scheduleJson[0].source).to.equal('https://gethelp.tiledesk.com/articles/article1');
|
|
1209
|
+
expect(scheduleJson[0].tags.length).to.equal(2);
|
|
1210
|
+
expect(scheduleJson[0].tags[0]).to.equal('tag1');
|
|
1211
|
+
expect(scheduleJson[0].tags[1]).to.equal('tag2');
|
|
1102
1212
|
should.exist(scheduleJson[0].engine);
|
|
1103
1213
|
should.exist(scheduleJson[0].embedding);
|
|
1104
1214
|
expect(scheduleJson[0].engine.index_name).to.equal(namespace.engine.index_name);
|
|
@@ -1107,6 +1217,9 @@ describe('KbRoute', () => {
|
|
|
1107
1217
|
|
|
1108
1218
|
expect(scheduleJson[1].namespace).to.equal(namespace_id);
|
|
1109
1219
|
expect(scheduleJson[1].source).to.equal('https://gethelp.tiledesk.com/articles/article2');
|
|
1220
|
+
expect(scheduleJson[1].tags.length).to.equal(2);
|
|
1221
|
+
expect(scheduleJson[1].tags[0]).to.equal('tag1');
|
|
1222
|
+
expect(scheduleJson[1].tags[1]).to.equal('tag2');
|
|
1110
1223
|
|
|
1111
1224
|
done();
|
|
1112
1225
|
|
package/utils/arrayUtil.js
CHANGED
|
@@ -13,4 +13,38 @@ function arraysEqual(a, b) {
|
|
|
13
13
|
if (a[i] !== b[i]) return false;
|
|
14
14
|
}
|
|
15
15
|
return true;
|
|
16
|
-
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Parse a field as an array of strings.
|
|
20
|
+
* Returns the array if valid, otherwise undefined.
|
|
21
|
+
*/
|
|
22
|
+
function parseStringArrayField(field) {
|
|
23
|
+
if (!field) return undefined;
|
|
24
|
+
|
|
25
|
+
let arr;
|
|
26
|
+
|
|
27
|
+
if (typeof field === 'string') {
|
|
28
|
+
try {
|
|
29
|
+
arr = JSON.parse(field); // prova a parsare come JSON
|
|
30
|
+
} catch {
|
|
31
|
+
return undefined; // se malformato, skippa
|
|
32
|
+
}
|
|
33
|
+
} else if (Array.isArray(field)) {
|
|
34
|
+
arr = field;
|
|
35
|
+
} else {
|
|
36
|
+
return undefined; // non stringa né array
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// controlla che tutti gli elementi siano stringhe
|
|
40
|
+
if (Array.isArray(arr) && arr.every(e => typeof e === 'string')) {
|
|
41
|
+
return arr;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return undefined; // non è un array di stringhe
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = {
|
|
48
|
+
arraysEqual,
|
|
49
|
+
parseStringArrayField
|
|
50
|
+
};
|