@tiledesk/tiledesk-tybot-connector 2.0.5 → 2.0.7-rc1

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.5",
3
+ "version": "2.0.7-rc1",
4
4
  "description": "Tiledesk Tybot connector",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -4,38 +4,63 @@ let API_ENDPOINT = process.env.API_ENDPOINT;
4
4
 
5
5
  class IntegrationService {
6
6
 
7
- constructor() {}
8
-
9
- async getKeyFromIntegrations(id_project, integration_name, token) {
10
- return new Promise((resolve) => {
11
-
12
- const INTEGRATIONS_HTTPREQUEST = {
13
- url: API_ENDPOINT + "/" + id_project + "/integration/name/" + integration_name,
14
- headers: {
15
- 'Content-Type': 'application/json',
16
- 'Authorization': 'JWT ' + token
17
- },
18
- method: "GET"
7
+ constructor() { }
8
+
9
+ async getKeyFromIntegrations(id_project, integration_name, token) {
10
+ return new Promise((resolve) => {
11
+
12
+ const INTEGRATIONS_HTTPREQUEST = {
13
+ url: API_ENDPOINT + "/" + id_project + "/integration/name/" + integration_name,
14
+ headers: {
15
+ 'Content-Type': 'application/json',
16
+ 'Authorization': 'JWT ' + token
17
+ },
18
+ method: "GET"
19
+ }
20
+ winston.debug("Integration HttpRequest ", INTEGRATIONS_HTTPREQUEST)
21
+
22
+ httpUtils.request(
23
+ INTEGRATIONS_HTTPREQUEST, async (err, integration) => {
24
+ if (err) {
25
+ resolve(null);
26
+ } else {
27
+
28
+ if (integration &&
29
+ integration.value) {
30
+ resolve(integration.value.apikey)
31
+ }
32
+ else {
33
+ resolve(null)
34
+ }
19
35
  }
20
- winston.debug("Integration HttpRequest ", INTEGRATIONS_HTTPREQUEST)
21
-
22
- httpUtils.request(
23
- INTEGRATIONS_HTTPREQUEST, async (err, integration) => {
24
- if (err) {
25
- resolve(null);
26
- } else {
27
-
28
- if (integration &&
29
- integration.value) {
30
- resolve(integration.value.apikey)
31
- }
32
- else {
33
- resolve(null)
34
- }
35
- }
36
- })
37
36
  })
37
+ })
38
+ }
39
+
40
+ async getIntegration(id_project, integration_name, token) {
41
+
42
+ return new Promise((resolve) => {
43
+
44
+ const INTEGRATIONS_HTTPREQUEST = {
45
+ url: API_ENDPOINT + "/" + id_project + "/integration/name/" + integration_name,
46
+ headers: {
47
+ 'Content-Type': 'application/json',
48
+ 'Authorization': 'JWT ' + token
49
+ },
50
+ method: "GET"
38
51
  }
52
+ winston.debug("Integration HttpRequest ", INTEGRATIONS_HTTPREQUEST)
53
+
54
+ httpUtils.request(
55
+ INTEGRATIONS_HTTPREQUEST, async (err, integration) => {
56
+ if (err) {
57
+ resolve(null);
58
+ } else {
59
+ resolve(integration)
60
+ }
61
+ })
62
+ })
63
+ }
39
64
 
40
65
  }
41
66
 
@@ -222,14 +222,13 @@ class DirectivesChatbotPlug {
222
222
  directive_name = directive.name.toLowerCase();
223
223
  }
224
224
  if (directive && directive.action) {
225
- const action_id = directive.action["_tdActionId"];
226
- const locked_action_id = await this.chatbot.currentLockedAction(this.supportRequest.request_id);
227
- if ( locked_action_id && (locked_action_id !== action_id) ) {
228
- let next_dir = await this.nextDirective(this.directives);
229
- this.process(next_dir);
230
- return;
231
- }
232
-
225
+ const action_id = directive.action["_tdActionId"];
226
+ const locked_action_id = await this.chatbot.currentLockedAction(this.supportRequest.request_id);
227
+ if ( locked_action_id && (locked_action_id !== action_id) ) {
228
+ let next_dir = await this.nextDirective(this.directives);
229
+ this.process(next_dir);
230
+ return;
231
+ }
233
232
  }
234
233
  if (directive == null || (directive !== null && directive["name"] === undefined)) {
235
234
  winston.debug("(DirectivesChatbotPlug) stop process(). directive is (null?): ", directive);
@@ -701,6 +700,19 @@ class DirectivesChatbotPlug {
701
700
  }
702
701
  });
703
702
  }
703
+ else if (directive_name === Directives.WEBHOOK) {
704
+ // console.log(".....DirIntent")
705
+ new DirIntent(context).execute(directive, async (stop) => {
706
+ if (stop) {
707
+ if (context.log) { console.log("Stopping Actions on:", JSON.stringify(directive));}
708
+ this.theend();
709
+ }
710
+ else {
711
+ let next_dir = await this.nextDirective(this.directives);
712
+ this.process(next_dir);
713
+ }
714
+ });
715
+ }
704
716
  else if (directive_name === Directives.WEB_RESPONSE) {
705
717
  new DirWebResponse(context).execute(directive, async () => {
706
718
  let next_dir = await this.nextDirective(this.directives);
@@ -100,21 +100,43 @@ class DirAiPrompt {
100
100
  }
101
101
  }
102
102
 
103
- const AI_endpoint = process.env.AI_ENDPOINT
103
+ let AI_endpoint = process.env.AI_ENDPOINT;
104
104
  winston.verbose("DirAiPrompt AI_endpoint " + AI_endpoint);
105
105
 
106
- let key = await integrationService.getKeyFromIntegrations(this.projectId, action.llm, this.token);
107
-
108
- if (!key) {
109
- winston.error("Error: DirAiPrompt llm key not found in integrations");
110
- await this.chatbot.addParameter("flowError", "AiPrompt Error: missing key for llm " + action.llm);
111
- if (falseIntent) {
112
- await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
113
- callback(true);
106
+ let headers = {
107
+ 'Content-Type': 'application/json'
108
+ }
109
+
110
+ let key;
111
+ let ollama_integration;
112
+
113
+ if (action.llm === 'ollama') {
114
+ ollama_integration = await integrationService.getIntegration(this.projectId, action.llm, this.token).catch( async (err) => {
115
+ winston.error("DirAiPrompt Error getting ollama integration: ", err);
116
+ await this.chatbot.addParameter("flowError", "Ollama integration not found");
117
+ if (falseIntent) {
118
+ await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
119
+ callback(true);
120
+ return;
121
+ }
122
+ callback();
123
+ return;
124
+ });
125
+
126
+ } else {
127
+ key = await integrationService.getKeyFromIntegrations(this.projectId, action.llm, this.token);
128
+
129
+ if (!key) {
130
+ winston.error("Error: DirAiPrompt llm key not found in integrations");
131
+ await this.chatbot.addParameter("flowError", "AiPrompt Error: missing key for llm " + action.llm);
132
+ if (falseIntent) {
133
+ await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
134
+ callback(true);
135
+ return;
136
+ }
137
+ callback();
114
138
  return;
115
139
  }
116
- callback();
117
- return;
118
140
  }
119
141
 
120
142
  let json = {
@@ -133,13 +155,22 @@ class DirAiPrompt {
133
155
  json.chat_history_dict = await this.transcriptToLLM(transcript);
134
156
  }
135
157
 
158
+ if (action.llm === 'ollama') {
159
+ json.llm_key = "";
160
+ json.model = {
161
+ name: action.model,
162
+ url: ollama_integration.value.url,
163
+ token: ollama_integration.value.token
164
+ }
165
+ json.stream = false
166
+
167
+ }
168
+
136
169
  winston.debug("DirAiPrompt json: ", json);
137
170
 
138
171
  const HTTPREQUEST = {
139
- url: AI_endpoint + '/ask',
140
- headers: {
141
- 'Content-Type': 'application/json'
142
- },
172
+ url: AI_endpoint + "/ask",
173
+ headers: headers,
143
174
  json: json,
144
175
  method: 'POST'
145
176
  }
@@ -148,7 +179,7 @@ class DirAiPrompt {
148
179
  httpUtils.request(
149
180
  HTTPREQUEST, async (err, resbody) => {
150
181
  if (err) {
151
- winston.error("DirAiPrompt openai err:", err.response.data);
182
+ winston.error("DirAiPrompt openai err: ", err);
152
183
  await this.#assignAttributes(action, answer);
153
184
  let error;
154
185
  if (err.response?.data?.detail[0]) {
@@ -62,10 +62,12 @@ class DirIntent {
62
62
  "recipient": requestId,
63
63
  "text": intent_command,
64
64
  "id_project": projectId,
65
- "request": {
66
- "request_id": requestId,
67
- "id_project": projectId
68
- }
65
+ "request": this.supportRequest,
66
+ // "request": {
67
+ // "request_id": requestId,
68
+ // "id_project": projectId
69
+ // // "bot_id": botId
70
+ // }
69
71
  },
70
72
  "token": this.token
71
73
  }
@@ -18,6 +18,7 @@ class DirReply {
18
18
  this.token = context.token;
19
19
  this.tdcache = context.tdcache;
20
20
  this.log = context.log;
21
+ this.supportRequest = this.context.supportRequest;
21
22
  this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest.draft });
22
23
 
23
24
  this.API_ENDPOINT = context.API_ENDPOINT;
@@ -44,10 +45,10 @@ class DirReply {
44
45
  callback();
45
46
  return;
46
47
  }
47
- this.logger.info("1 Execute action reply for " + directive.action.text)
48
+ this.logger.info("Executing Action Reply ", directive.action)
48
49
 
49
50
  this.go(action, () => {
50
- this.logger.info("6 End of action reply " + directive.action.text + " -> callback")
51
+ this.logger.info("Action Reply terminated")
51
52
  callback();
52
53
  });
53
54
  }
@@ -68,15 +69,16 @@ class DirReply {
68
69
  const filler = new Filler();
69
70
  // fill text attribute
70
71
  message.text = filler.fill(message.text, requestAttributes);
71
- this.logger.info("2 Sending reply " + message.text);
72
72
 
73
73
  if (message.metadata) {
74
74
  winston.debug("DirReply filling message 'metadata':", message.metadata);
75
75
  if (message.metadata.src) {
76
76
  message.metadata.src = filler.fill(message.metadata.src, requestAttributes);
77
+ this.logger.debug("Filled metadata.src with ", message.metadata.src);
77
78
  }
78
79
  if (message.metadata.name) {
79
80
  message.metadata.name = filler.fill(message.metadata.name, requestAttributes);
81
+ this.logger.debug("Filled metadata.name with ", message.metadata.name);
80
82
  }
81
83
  }
82
84
  winston.debug("DirReply filling commands'. Message:", message);
@@ -89,6 +91,7 @@ class DirReply {
89
91
  let command = commands[i];
90
92
  if (command.type === 'message' && command.message && command.message.text) {
91
93
  command.message.text = filler.fill(command.message.text, requestAttributes);
94
+ this.logger.debug("Filled message.text with ", command.message.text)
92
95
  TiledeskChatbotUtil.fillCommandAttachments(command, requestAttributes, this.log);
93
96
  winston.debug("DirReply command filled: " + command.message.text);
94
97
  }
@@ -143,15 +146,6 @@ class DirReply {
143
146
  }
144
147
 
145
148
  let cleanMessage = message;
146
- this.logger.info("3 Sending reply (text) " + cleanMessage.text);
147
- this.logger.info("4 Sending reply with clean message " + JSON.stringify(cleanMessage));
148
- // cleanMessage = TiledeskChatbotUtil.removeEmptyReplyCommands(message);
149
- // if (!TiledeskChatbotUtil.isValidReply(cleanMessage)) {
150
- // console.log("invalid message", cleanMessage);
151
- // callback(); // cancel reply operation
152
- // return;
153
- // }
154
-
155
149
  cleanMessage.senderFullname = this.context.chatbot.bot.name;
156
150
  winston.debug("DirReply reply with clean message: ", cleanMessage);
157
151
 
@@ -162,10 +156,8 @@ class DirReply {
162
156
  (err) => {
163
157
  if (err) {
164
158
  winston.error("DirReply Error sending reply: ", err);
165
- this.logger.error("Error sending reply: " + err);
166
159
  }
167
160
  winston.verbose("DirReply reply message sent")
168
- this.logger.info("5 Reply message sent");
169
161
  const delay = TiledeskChatbotUtil.totalMessageWait(cleanMessage);
170
162
  if (delay > 0 && delay <= 30000) { // prevent long delays
171
163
  setTimeout(() => {
@@ -38,25 +38,24 @@ class DirWebResponse {
38
38
  async go(action, callback) {
39
39
  winston.debug("DirWebResponse action: ", action);
40
40
 
41
- let requestAttributes = null;
42
- let status = null;
43
- if (this.tdcache) {
44
- requestAttributes =
45
- await TiledeskChatbot.allParametersStatic(this.tdcache, this.requestId);
46
- const filler = new Filler();
47
-
48
- try {
49
- status = filler.fill(action.status, requestAttributes);
50
- }
51
- catch(e) {
52
- winston.error("DirWebResponse Error: ", e)
53
- }
54
-
41
+ if (!this.tdcache) {
42
+ winston.error("DirWebResponse Error: tdcache is mandatory");
43
+ callback();
44
+ return;
55
45
  }
56
-
46
+
47
+ let requestAttributes = null;
48
+ requestAttributes =
49
+ await TiledeskChatbot.allParametersStatic(
50
+ this.tdcache, this.requestId
51
+ );
52
+
53
+ const filler = new Filler();
54
+ const filled_status = filler.fill(action.status, requestAttributes);
57
55
  const json = await this.getJsonFromAction(action, filler, requestAttributes)
56
+
58
57
  let webResponse = {
59
- status: status,
58
+ status: filled_status,
60
59
  payload: json
61
60
  }
62
61
 
@@ -97,42 +96,4 @@ class DirWebResponse {
97
96
 
98
97
  }
99
98
 
100
-
101
-
102
- /**
103
- * A stub to send message to the "ext/botId" endpoint, hosted by tilebot on:
104
- * /${TILEBOT_ROUTE}/ext/${botId}
105
- *
106
- * @param {Object} webResponse. The webhook response to send back
107
- * @param {Object} projectId. The projectId
108
- * @param {string} botId. Tiledesk botId
109
- * @param {string} token. User token
110
- */
111
- // function sendResponse(webResponse, projectId, botId, callback) {
112
- // const url = `${WEBHOOK_URL}/${projectId}/${botId}`;
113
- // const HTTPREQUEST = {
114
- // url: url,
115
- // headers: {
116
- // 'Content-Type': 'application/json'
117
- // },
118
- // json: webResponse,
119
- // method: 'POST'
120
- // };
121
- // myrequest(
122
- // HTTPREQUEST,
123
- // function (err, resbody) {
124
- // if (err) {
125
- // if (callback) {
126
- // callback(err);
127
- // }
128
- // }
129
- // else {
130
- // if (callback) {
131
- // callback(null, resbody);
132
- // }
133
- // }
134
- // }, false
135
- // );
136
- // }
137
-
138
99
  module.exports = { DirWebResponse };
@@ -58,6 +58,7 @@ class Directives {
58
58
  static MOVE_TO_UNASSIGNED = "move_to_unassigned";
59
59
  static CONNECT_BLOCK = "connect_block";
60
60
  static ADD_TAGS = 'add_tags'
61
+ static WEBHOOK = 'webhook';
61
62
  static WEB_RESPONSE = "web_response";
62
63
 
63
64
  // static WHEN_ONLINE_MOVE_TO_AGENT = "whenonlinemovetoagent"; // DEPRECATED?
@@ -319,55 +319,31 @@ class TiledeskChatbotUtil {
319
319
  json_buttons.forEach(button => {
320
320
  if (button.value && button.type === "action" && button.action) {
321
321
  button.show_echo = true;
322
- // console.log("pushing:", button)
323
322
  final_buttons.push(button);
324
323
  }
325
324
  else if (button.value && button.type === "text") {
326
325
  button.show_echo = true;
327
- // console.log("pushing:", button)
328
326
  final_buttons.push(button);
329
327
  }
330
328
  else if (button.value && button.type === "url" && button.link) {
331
329
  button.show_echo = true;
332
- // console.log("pushing:", button)
333
330
  final_buttons.push(button);
334
331
  }
335
332
  else {
336
- console.log("Invalid button. Skipping:", JSON.stringify(button) );
333
+ winston.verbose("Invalid button. Skipping:", button);
337
334
  }
338
335
  });
339
336
  }
340
-
341
- // "buttons": [
342
- // {
343
- // "type": "action",
344
- // "value": "Button1", // obbligatorio sempre
345
- // "action": "#bb347206-d639-4926-94c9-e94930623dce", // mandatory
346
- // "show_echo": true, // lo inserisco sempre
347
- // "alias": "button1 alias"
348
- // },
349
- // {
350
- // "type": "text",
351
- // "value": "Button2 text", // obbligatorio sempre
352
- // "show_echo": true // lo inserisco sempre
353
- // },
354
- // {
355
- // "type": "url",
356
- // "value": "Button3 link", // obbligatorio sempre
357
- // "link": "http://", // obbligatorio
358
- // "show_echo": true // lo inserisco sempre
359
- // }
360
- // ]
361
337
  }
362
338
  catch(error) {
363
- console.error("Invalid json_buttons:", error)
339
+ winston.warn("Invalid json_buttons:", error)
364
340
  }
365
341
  if (final_buttons && final_buttons.length > 0) {
366
342
  command.message.attributes.attachment.buttons = final_buttons;
367
343
  delete command.message.attributes.attachment.json_buttons;
368
344
  }
369
345
  else {
370
- console.log("Invalid json_buttons. Skipping")
346
+ winston.verbose("Invalid json_buttons. Skipping...")
371
347
  }
372
348
  }
373
349
  }