@tiledesk/tiledesk-tybot-connector 2.0.10-rc1 → 2.0.10-rc11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-tybot-connector",
3
- "version": "2.0.10-rc1",
3
+ "version": "2.0.10-rc11",
4
4
  "description": "Tiledesk Tybot connector",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -15,7 +15,7 @@
15
15
  "@tiledesk/tiledesk-chatbot-client": "^0.5.30",
16
16
  "@tiledesk/tiledesk-chatbot-util": "^0.8.39",
17
17
  "@tiledesk/tiledesk-client": "^0.10.13",
18
- "@tiledesk/tiledesk-multi-worker": "^0.3.1-rc10",
18
+ "@tiledesk/tiledesk-multi-worker": "^0.3.1-rc12",
19
19
  "accept-language-parser": "^1.5.0",
20
20
  "app-root-path": "^3.1.0",
21
21
  "axios": "^1.7.7",
@@ -57,6 +57,7 @@ const { DirReplaceBotV3 } = require('./directives/DirReplaceBotV3');
57
57
  const { DirAiTask, DirAiPrompt } = require('./directives/DirAiPrompt');
58
58
  const { DirWebResponse } = require('./directives/DirWebResponse');
59
59
  const { DirConnectBlock } = require('./directives/DirConnectBlock');
60
+ const { DirAddKbContent } = require('./directives/DirAddKbContent');
60
61
 
61
62
  const winston = require('../utils/winston');
62
63
  const { DirFlowLog } = require('./directives/DirFlowLog');
@@ -721,6 +722,12 @@ class DirectivesChatbotPlug {
721
722
  this.process(next_dir);
722
723
  })
723
724
  }
725
+ else if (directive_name === Directives.ADD_KB_CONTENT) {
726
+ new DirAddKbContent(context).execute(directive, async () => {
727
+ let next_dir = await this.nextDirective(this.directives);
728
+ this.process(next_dir);
729
+ });
730
+ }
724
731
  else {
725
732
  let next_dir = await this.nextDirective(this.directives);
726
733
  this.process(next_dir);
@@ -0,0 +1,332 @@
1
+ const axios = require("axios").default;
2
+ const { TiledeskChatbot } = require('../../engine/TiledeskChatbot');
3
+ const { Filler } = require('../Filler');
4
+ let https = require("https");
5
+ const { DirIntent } = require("./DirIntent");
6
+ const { TiledeskChatbotConst } = require("../../engine/TiledeskChatbotConst");
7
+ const { TiledeskChatbotUtil } = require("../../utils/TiledeskChatbotUtil");
8
+ const assert = require("assert");
9
+ require('dotenv').config();
10
+ const winston = require('../../utils/winston');
11
+ const httpUtils = require("../../utils/HttpUtils");
12
+ const integrationService = require("../../services/IntegrationService");
13
+ const { Logger } = require("../../Logger");
14
+
15
+ class DirAddKbContent {
16
+
17
+ constructor(context) {
18
+ if (!context) {
19
+ throw new Error('context object is mandatory');
20
+ }
21
+ this.context = context;
22
+ this.chatbot = context.chatbot;
23
+ this.tdcache = this.context.tdcache;
24
+ this.requestId = this.context.requestId;
25
+ this.projectId = this.context.projectId;
26
+ this.token = this.context.token;
27
+ this.intentDir = new DirIntent(context);
28
+ this.API_ENDPOINT = this.context.API_ENDPOINT;
29
+ this.log = context.log;
30
+ this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft });
31
+ }
32
+
33
+ execute(directive, callback) {
34
+ this.logger.info("Execute AskKnowledgeBase action")
35
+ winston.debug("DirAskGPTV2 directive: ", directive);
36
+ let action;
37
+ if (directive.action) {
38
+ action = directive.action;
39
+ }
40
+ else {
41
+ this.logger.error("Incorrect action for ", directive.name, directive)
42
+ winston.debug("DirAskGPTV2 Incorrect directive: ", directive);
43
+ callback();
44
+ return;
45
+ }
46
+ this.go(action, (stop) => {
47
+ this.logger.info("Acion AskKnowledgeBase completed");
48
+ callback(stop);
49
+ })
50
+ }
51
+
52
+ async go(action, callback) {
53
+ winston.debug("[DirAddKbContent] action:", action);
54
+ if (!this.tdcache) {
55
+ winston.error("[DirAddKbContent] Error: tdcache is mandatory");
56
+ callback();
57
+ return;
58
+ }
59
+
60
+ let publicKey = false;
61
+ let type = action.type;
62
+ let name = action.name;
63
+ let content = action.content;
64
+ let engine;
65
+
66
+ // default values
67
+ let namespace = this.context.projectId;
68
+
69
+ if (action.namespace) {
70
+ namespace = action.namespace;
71
+ }
72
+
73
+ let requestVariables = null;
74
+ requestVariables =
75
+ await TiledeskChatbot.allParametersStatic(
76
+ this.tdcache, this.requestId
77
+ );
78
+
79
+ const filler = new Filler();
80
+ const filled_content = filler.fill(content, requestVariables);
81
+ const filled_name = filler.fill(name, requestVariables);
82
+
83
+ const kb_endpoint = process.env.API_ENDPOINT;
84
+ winston.verbose("[DirAddKbContent] KbEndpoint URL: " + kb_endpoint);
85
+
86
+ let key = await integrationService.getKeyFromIntegrations(this.projectId, 'openai', this.token);
87
+ if (!key) {
88
+ this.logger.debug("[DirAddKbContent] OpenAI key not found in Integration. Using shared OpenAI key");
89
+ winston.verbose("[DirAddKbContent] - Key not found in Integrations. Searching in kb settings...");
90
+ key = await this.getKeyFromKbSettings();
91
+ }
92
+
93
+ if (!key) {
94
+ winston.verbose("[DirAddKbContent] - Retrieve public gptkey")
95
+ key = process.env.GPTKEY;
96
+ publicKey = true;
97
+ } else {
98
+ this.logger.debug("[DirAddKbContent] use your own OpenAI key")
99
+ }
100
+
101
+ if (!key) {
102
+ winston.info("[DirAddKbContent] Error: gptkey is mandatory");
103
+ await this.chatbot.addParameter("flowError", "[DirAddKbContent] Error: gptkey is mandatory");
104
+ callback();
105
+ return;
106
+ }
107
+
108
+ if (publicKey === true) {
109
+ let keep_going = await this.checkQuoteAvailability();
110
+ if (keep_going === false) {
111
+ this.logger.warn("[DirAddKbContent] Tokens quota exceeded. Skip the action")
112
+ winston.verbose("[DirAddKbContent] - Quota exceeded for tokens. Skip the action")
113
+ await this.chatbot.addParameter("flowError", "[DirAddKbContent] Error: tokens quota exceeded");
114
+ callback(true);
115
+ return;
116
+ }
117
+ }
118
+
119
+ let ns;
120
+
121
+ if (action.namespaceAsName) {
122
+ // Namespace could be an attribute
123
+ const filled_namespace = filler.fill(action.namespace, requestVariables)
124
+ this.logger.debug("[DirAddKbContent] Searching namespace by name ", filled_namespace);
125
+ ns = await this.getNamespace(filled_namespace, null);
126
+ namespace = ns?.id;
127
+ winston.verbose("[DirAddKbContent] - Retrieved namespace id from name " + namespace);
128
+ } else {
129
+ this.logger.debug("[DirAddKbContent] Searching namespace by id ", namespace);
130
+ ns = await this.getNamespace(null, namespace);
131
+ }
132
+
133
+ if (!ns) {
134
+ this.logger.error("[DirAddKbContent] Namespace not found");
135
+ await this.chatbot.addParameter("flowError", "[DirAddKbContent] Error: namespace not found");
136
+ callback();
137
+ return;
138
+ }
139
+
140
+ if (ns.engine) {
141
+ engine = ns.engine;
142
+ } else {
143
+ engine = await this.setDefaultEngine()
144
+ }
145
+
146
+ if (!namespace) {
147
+ this.logger.error("[DirAddKbContent] Namespace is undefined")
148
+ winston.verbose("[DirAddKbContent] - Error: namespace is undefined")
149
+ await this.chatbot.addParameter("flowError", "[DirAddKbContent] Error: namespace is undefined");
150
+ callback(true);
151
+ return;
152
+ }
153
+
154
+ let json = {
155
+ content: filled_content,
156
+ namespace: namespace,
157
+ type: type,
158
+ name: filled_name,
159
+ source: filled_name
160
+ };
161
+
162
+ winston.debug("[DirAddKbContent] json:", json);
163
+
164
+ const HTTPREQUEST = {
165
+ url: kb_endpoint + "/" + this.projectId + "/kb",
166
+ headers: {
167
+ 'Content-Type': 'application/json',
168
+ 'Authorization': 'JWT ' + this.context.token
169
+ },
170
+ json: json,
171
+ method: "POST"
172
+ }
173
+ winston.debug("[DirAddKbContent] HttpRequest: ", HTTPREQUEST);
174
+
175
+ httpUtils.request(
176
+ HTTPREQUEST, async (err, resbody) => {
177
+
178
+ if (err) {
179
+ this.logger.error("[DirAddKbContent] error: " + JSON.stringify(err?.response));
180
+ winston.error("[DirAddKbContent] error: ", err?.response);
181
+ if (callback) {
182
+ callback();
183
+ return;
184
+ }
185
+ }
186
+ else if (resbody.success === true) {
187
+ winston.debug("[DirAddKbContent] resbody: ", resbody);
188
+ callback();
189
+ return;
190
+ } else {
191
+ callback();
192
+ return;
193
+ }
194
+ }
195
+ )
196
+ }
197
+
198
+ async getKeyFromKbSettings() {
199
+ return new Promise((resolve) => {
200
+
201
+ const KB_HTTPREQUEST = {
202
+ url: this.API_ENDPOINT + "/" + this.context.projectId + "/kbsettings",
203
+ headers: {
204
+ 'Content-Type': 'application/json',
205
+ 'Authorization': 'JWT ' + this.context.token
206
+ },
207
+ method: "GET"
208
+ }
209
+ winston.debug("DirAskGPTV2 KB HttpRequest", KB_HTTPREQUEST);
210
+
211
+ httpUtils.request(
212
+ KB_HTTPREQUEST, async (err, resbody) => {
213
+ if (err) {
214
+ winston.error("DirAskGPTV2 Get kb settings error ", err?.response?.data);
215
+ resolve(null);
216
+ } else {
217
+ if (!resbody.gptkey) {
218
+ resolve(null);
219
+ } else {
220
+ resolve(resbody.gptkey);
221
+ }
222
+ }
223
+ }
224
+ )
225
+ })
226
+ }
227
+
228
+ async checkQuoteAvailability() {
229
+ return new Promise((resolve) => {
230
+
231
+ const HTTPREQUEST = {
232
+ url: this.API_ENDPOINT + "/" + this.context.projectId + "/quotes/tokens",
233
+ headers: {
234
+ 'Content-Type': 'application/json',
235
+ 'Authorization': 'JWT ' + this.context.token
236
+ },
237
+ method: "GET"
238
+ }
239
+ winston.debug("DirAskGPTV2 check quote availability HttpRequest", HTTPREQUEST);
240
+
241
+ httpUtils.request(
242
+ HTTPREQUEST, async (err, resbody) => {
243
+ if (err) {
244
+ winston.error("DirAskGPTV2 Check quote availability err: ", err);
245
+ resolve(true)
246
+ } else {
247
+ if (resbody.isAvailable === true) {
248
+ resolve(true)
249
+ } else {
250
+ resolve(false)
251
+ }
252
+ }
253
+ }
254
+ )
255
+ })
256
+ }
257
+
258
+ async updateQuote(tokens_usage) {
259
+ return new Promise((resolve, reject) => {
260
+
261
+ const HTTPREQUEST = {
262
+ url: this.API_ENDPOINT + "/" + this.context.projectId + "/quotes/incr/tokens",
263
+ headers: {
264
+ 'Content-Type': 'application/json',
265
+ 'Authorization': 'JWT ' + this.context.token
266
+ },
267
+ json: tokens_usage,
268
+ method: "POST"
269
+ }
270
+ winston.debug("DirAskGPTV2 update quote HttpRequest ", HTTPREQUEST);
271
+
272
+ httpUtils.request(
273
+ HTTPREQUEST, async (err, resbody) => {
274
+ if (err) {
275
+ winston.error("DirAskGPTV2 Increment tokens quote err: ", err);
276
+ reject(false)
277
+ } else {
278
+ resolve(true);
279
+ }
280
+ }
281
+ )
282
+ })
283
+ }
284
+
285
+ async getNamespace(name, id) {
286
+ return new Promise((resolve) => {
287
+ const HTTPREQUEST = {
288
+ url: this.API_ENDPOINT + "/" + this.context.projectId + "/kb/namespace/all",
289
+ headers: {
290
+ 'Content-Type': 'application/json',
291
+ 'Authorization': 'JWT ' + this.context.token
292
+ },
293
+ method: "GET"
294
+ }
295
+ winston.debug("DirAskGPTV2 get all namespaces HttpRequest", HTTPREQUEST);
296
+ httpUtils.request(
297
+ HTTPREQUEST, async (err, namespaces) => {
298
+ if (err) {
299
+ winston.error("DirAskGPTV2 get all namespaces err: ", err);
300
+ resolve(null)
301
+ } else {
302
+ winston.debug("DirAskGPTV2 get all namespaces resbody: ", namespaces);
303
+ if (name) {
304
+ let namespace = namespaces.find(n => n.name === name);
305
+ resolve(namespace);
306
+ } else {
307
+ let namespace = namespaces.find(n => n.id === id);
308
+ resolve(namespace);
309
+ }
310
+
311
+ }
312
+ }
313
+ )
314
+ })
315
+ }
316
+
317
+ async setDefaultEngine() {
318
+ return new Promise((resolve) => {
319
+ let engine = {
320
+ name: "pinecone",
321
+ type: process.env.PINECONE_TYPE,
322
+ apikey: "",
323
+ vector_size: 1536,
324
+ index_name: process.env.PINECONE_INDEX
325
+ }
326
+ resolve(engine);
327
+ })
328
+ }
329
+
330
+ }
331
+
332
+ module.exports = { DirAddKbContent }
@@ -25,7 +25,7 @@ class DirAddTags {
25
25
  this.requestId = this.context.requestId;
26
26
  this.API_ENDPOINT = this.context.API_ENDPOINT;
27
27
  this.log = context.log;
28
- this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft });
28
+ this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft, intent_id: this.context.reply.attributes.intent_info.intent_id });
29
29
 
30
30
  this.tdClient = new TiledeskClient({
31
31
  projectId: this.context.projectId,
@@ -29,7 +29,7 @@ class DirAiPrompt {
29
29
  this.intentDir = new DirIntent(context);
30
30
  this.API_ENDPOINT = this.context.API_ENDPOINT;
31
31
  this.log = context.log;
32
- this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft });
32
+ this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft, intent_id: this.context.reply.attributes.intent_info.intent_id });
33
33
  }
34
34
 
35
35
  execute(directive, callback) {
@@ -27,11 +27,11 @@ class DirAskGPTV2 {
27
27
  this.intentDir = new DirIntent(context);
28
28
  this.API_ENDPOINT = this.context.API_ENDPOINT;
29
29
  this.log = context.log;
30
- this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft });
30
+ this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft, intent_id: this.context.reply.attributes.intent_info.intent_id });
31
31
  }
32
32
 
33
33
  execute(directive, callback) {
34
- this.logger.error("Execute AskKnowledgeBase action")
34
+ this.logger.info("Execute AskKnowledgeBase action")
35
35
  winston.debug("DirAskGPTV2 directive: ", directive);
36
36
  let action;
37
37
  if (directive.action) {
@@ -1,7 +1,10 @@
1
1
 
2
2
 
3
3
  const { Logger } = require('../../Logger');
4
+ const { TiledeskChatbot } = require('../../engine/TiledeskChatbot');
5
+ const { Filler } = require('../Filler');
4
6
  const winston = require('../../utils/winston');
7
+
5
8
  let levels = ['error', 'warn', 'info', 'debug'];
6
9
 
7
10
  class DirFlowLog {
@@ -38,7 +41,6 @@ class DirFlowLog {
38
41
 
39
42
  async go(action, callback) {
40
43
  winston.debug("(DirFlowLog) Action: ", action);
41
- console.log("(DirFlowLog) Action: ", action);
42
44
 
43
45
  let level = action.level || 'info';
44
46
  if (!levels.includes(level)) {
@@ -52,21 +54,31 @@ class DirFlowLog {
52
54
  callback();
53
55
  }
54
56
 
57
+ let requestVariables = null;
58
+ requestVariables =
59
+ await TiledeskChatbot.allParametersStatic(
60
+ this.tdcache, this.requestId
61
+ );
62
+
63
+ const filler = new Filler();
64
+ const filled_log = filler.fill(action.log, requestVariables);
65
+ winston.debug("(DirFlowLog) fille log: ", filled_log);
66
+
55
67
  if (level === 'error') {
56
- winston.info("Adding log " + action.log + " with level " + level);
57
- this.logger.error(action.log);
68
+ winston.info("Adding log '" + filled_log + "' with level " + level);
69
+ this.logger.error(filled_log);
58
70
  }
59
71
  else if (level === 'warn') {
60
- winston.info("Adding log " + action.log + " with level " + level);
61
- this.logger.warn(action.log);
72
+ winston.info("Adding log '" + filled_log + "' with level " + level);
73
+ this.logger.warn(filled_log);
62
74
  }
63
75
  else if (level === 'info') {
64
- winston.info("Adding log " + action.log + " with level " + level);
65
- this.logger.info(action.log);
76
+ winston.info("Adding log '" + filled_log + "' with level " + level);
77
+ this.logger.info(filled_log);
66
78
  }
67
79
  else if (level === 'debug') {
68
- winston.info("Adding log " + action.log + " with level " + level);
69
- this.logger.debug(action.log);
80
+ winston.info("Adding log '" + filled_log + "' with level " + level);
81
+ this.logger.debug(filled_log);
70
82
  }
71
83
 
72
84
  callback();
@@ -18,7 +18,7 @@ class DirReply {
18
18
  this.token = context.token;
19
19
  this.tdcache = context.tdcache;
20
20
  this.supportRequest = this.context.supportRequest;
21
- this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft });
21
+ this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft, intent_id: this.context.reply.attributes.intent_info.intent_id });
22
22
 
23
23
  this.API_ENDPOINT = context.API_ENDPOINT;
24
24
  this.tdClient = new TiledeskClient({
@@ -18,7 +18,7 @@ class DirWebRequestV2 {
18
18
  this.chatbot = context.chatbot;
19
19
  this.intentDir = new DirIntent(context);
20
20
  this.log = context.log;
21
- this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft });
21
+ this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft, intent_id: this.context.reply.attributes.intent_info.intent_id });
22
22
  }
23
23
 
24
24
  execute(directive, callback) {
@@ -54,10 +54,10 @@ class DirWebRequestV2 {
54
54
  let trueIntentAttributes = action.trueIntentAttributes;
55
55
  let falseIntentAttributes = action.falseIntentAttributes;
56
56
 
57
- winston.debug("DirWebRequestV2 trueIntent " + trueIntent)
58
- winston.debug("DirWebRequestV2 falseIntent " + falseIntent)
59
- winston.debug("DirWebRequestV2 trueIntentAttributes " + trueIntentAttributes)
60
- winston.debug("DirWebRequestV2 falseIntentAttributes " + falseIntentAttributes)
57
+ winston.debug("DirWebRequestV2 trueIntent " + trueIntent)
58
+ winston.debug("DirWebRequestV2 falseIntent " + falseIntent)
59
+ winston.debug("DirWebRequestV2 trueIntentAttributes " + trueIntentAttributes)
60
+ winston.debug("DirWebRequestV2 falseIntentAttributes " + falseIntentAttributes)
61
61
 
62
62
  let requestAttributes = null;
63
63
  requestAttributes =
@@ -139,6 +139,7 @@ class DirWebRequestV2 {
139
139
  }
140
140
  else {
141
141
  this.logger.warn("WebRequest status ", status);
142
+ this.logger.error("WebRequest error ", error);
142
143
  if (falseIntent) {
143
144
  await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
144
145
  callback(true);
@@ -16,7 +16,7 @@ class DirWebResponse {
16
16
  this.requestId = context.requestId;
17
17
  this.token = context.token;
18
18
  this.tdcache = context.tdcache;
19
- this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft });
19
+ this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft, intent_id: this.context.reply.attributes.intent_info.intent_id });
20
20
  }
21
21
 
22
22
  execute(directive, callback) {
@@ -61,6 +61,7 @@ class Directives {
61
61
  static WEBHOOK = 'webhook';
62
62
  static WEB_RESPONSE = "web_response";
63
63
  static FLOW_LOG = "flow_log";
64
+ static ADD_KB_CONTENT = "add_kb_content";
64
65
 
65
66
  // static WHEN_ONLINE_MOVE_TO_AGENT = "whenonlinemovetoagent"; // DEPRECATED?
66
67
  // static WHEN_OFFLINE_HOURS = "whenofflinehours"; // DEPRECATED // adds a message on top of the original message when offline hours opts: --replace