@tiledesk/tiledesk-tybot-connector 0.2.69 → 0.2.71

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 CHANGED
@@ -5,6 +5,14 @@
5
5
  available on:
6
6
  ▶️ https://www.npmjs.com/package/@tiledesk/tiledesk-tybot-connector
7
7
 
8
+ # v0.2.71
9
+ - Fix. DirReplyV2 "NoInput" bug. Refactored with the introduction of "timeout_id", an ID specific for each noInput timeout: this.chatbot.addParameter(TiledeskChatbotConst.USER_INPUT, timeout_id)
10
+
11
+ # v0.2.70
12
+ - added DirIfOnlineAgentsV2
13
+ - Fix. TiledeskChatbot: WRONG: await chatbot.addParameter("userInput", true); ====> FIXED: this.addParameter("userInput", true)
14
+ - Fix. Fixed WRONG addParameter(key, value) invocation in TiledeskChatbot with 3 (instead of key, value) parameters
15
+
8
16
  # v0.2.69
9
17
  - added flow attributes in reply action (original)
10
18
 
@@ -9,6 +9,7 @@ const { IntentForm } = require('./IntentForm.js');
9
9
  const { TiledeskChatbotUtil } = require('./TiledeskChatbotUtil.js');
10
10
  const { DirLockIntent } = require('../tiledeskChatbotPlugs/directives/DirLockIntent');
11
11
  const { DirUnlockIntent } = require('../tiledeskChatbotPlugs/directives/DirUnlockIntent');
12
+ const { TiledeskChatbotConst } = require('./TiledeskChatbotConst.js');
12
13
 
13
14
  class TiledeskChatbot {
14
15
 
@@ -53,11 +54,13 @@ class TiledeskChatbot {
53
54
  lead = message.request.lead;
54
55
  if (lead && lead.fullname) {
55
56
  if (this.log) {console.log("lead.fullname => params.userFullname:", lead.fullname)}
56
- await this.addParameter(this.requestId, "userFullname", lead.fullname);
57
+ // await this.addParameter(this.requestId, "userFullname", lead.fullname);
58
+ await this.addParameter("userFullname", lead.fullname);
57
59
  }
58
60
  if (lead && lead.email) {
59
61
  if (this.log) {console.log("lead.email => params.userEmail:", lead.email)}
60
- await this.addParameter(this.requestId, "userEmail", lead.email);
62
+ // await this.addParameter(this.requestId, "userEmail", lead.email);
63
+ await this.addParameter("userEmail", lead.email);
61
64
  }
62
65
  }
63
66
  if (this.log) {
@@ -81,7 +84,6 @@ class TiledeskChatbot {
81
84
  await this.unlockIntent(this.requestId);
82
85
  await this.unlockAction(this.requestId);
83
86
  // console.log("RESET LOCKED INTENT.");
84
- await chatbot.addParameter("userInput", true); // set userInput
85
87
  if (this.log) {console.log("RESET LOCKED INTENT. Intent was explicitly invoked with an action:", message.attributes.action);}
86
88
  }
87
89
  } catch(error) {
@@ -89,6 +91,18 @@ class TiledeskChatbot {
89
91
  }
90
92
  }
91
93
 
94
+ // resetting any noInput timeout setting userInput = true
95
+ // if (message.sender != "_tdinternal") {
96
+ // if (this.log) {console.log("resetting any noInput timeout setting userInput = (false?)", await this.getParameter(TiledeskChatbotConst.USER_INPUT) );}
97
+ // try {
98
+ // // await this.addParameter(TiledeskChatbotConst.USER_INPUT, true); // set userInput
99
+ // await this.deleteParameter(TiledeskChatbotConst.USER_INPUT); // reset userInput
100
+ // if (this.log) {console.log("userInput?", await this.getParameter(TiledeskChatbotConst.USER_INPUT) );}
101
+ // } catch(error) {
102
+ // console.error("Error resetting userInput:", error);
103
+ // }
104
+ // }
105
+
92
106
  // any external invocation restarts the steps counter
93
107
  try {
94
108
  if (message.sender != "_tdinternal") {
@@ -22,6 +22,7 @@ class TiledeskChatbotConst {
22
22
  static REQ_CHAT_CHANNEL = "chatChannel";
23
23
  static REQ_DECODED_JWT_KEY = "decodedCustomJWT";
24
24
  static REQ_REQUESTER_IS_AUTHENTICATED_KEY = "strongAuthenticated";
25
+ static USER_INPUT = "_userInput";
25
26
 
26
27
  // static REQ_DEPARTMENT_ID_KEY = "tdDepartmentId";
27
28
  // static REQ_PROJECT_ID_KEY = "projectId";
@@ -496,7 +496,8 @@ class TiledeskChatbotUtil {
496
496
  }
497
497
 
498
498
  if (message.text && message.sender !== "_tdinternal") {
499
- await chatbot.addParameter("userInput", true); // set userInput
499
+ // await chatbot.addParameter(TiledeskChatbotConst.USER_INPUT, true); // set userInput
500
+ await chatbot.deleteParameter(TiledeskChatbotConst.USER_INPUT); // set userInput
500
501
  await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_TEXT_KEY, message.text); // DEPRECATED
501
502
  await chatbot.addParameter(TiledeskChatbotConst.REQ_LAST_USER_TEXT_v2_KEY, message.text);
502
503
  if (message.channel) {
@@ -835,7 +836,7 @@ class TiledeskChatbotUtil {
835
836
  "userLeadId",
836
837
  "lastUserText",
837
838
  TiledeskChatbotConst.REQ_REQUESTER_IS_AUTHENTICATED_KEY,
838
- "userInput"
839
+ TiledeskChatbotConst.USER_INPUT
839
840
  ]
840
841
  let userParams = {};
841
842
  if (flowAttributes) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-tybot-connector",
3
- "version": "0.2.69",
3
+ "version": "0.2.71",
4
4
  "description": "Tiledesk Tybot connector",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -48,6 +48,7 @@ const { DirBrevo } = require('./directives/DirBrevo');
48
48
  const { DirAskGPTV2 } = require('./directives/DirAskGPTV2');
49
49
  const { DirAssistant } = require('./directives/DirAssistant');
50
50
  const { DirReplyV2 } = require('./directives/DirReplyV2');
51
+ const { DirIfOnlineAgentsV2 } = require('./directives/DirIfOnlineAgentsV2');
51
52
 
52
53
  class DirectivesChatbotPlug {
53
54
 
@@ -378,6 +379,19 @@ class DirectivesChatbotPlug {
378
379
  // this.process(next_dir);
379
380
  });
380
381
  }
382
+ else if (directive_name === Directives.IF_ONLINE_AGENTS_V2) {
383
+ // console.log("...DirIfOnlineAgents")
384
+ new DirIfOnlineAgentsV2(context).execute(directive, async (stop) => {
385
+ if (stop) {
386
+ if (context.log) { console.log("Stopping Actions on:", JSON.stringify(directive));}
387
+ this.theend();
388
+ }
389
+ else {
390
+ let next_dir = await this.nextDirective(this.directives);
391
+ this.process(next_dir);
392
+ }
393
+ });
394
+ }
381
395
  else if (directive_name === Directives.FUNCTION_VALUE) {
382
396
  // console.log("...DirAssignFromFunction")
383
397
  new DirAssignFromFunction(context).execute(directive, async () => {
@@ -0,0 +1,399 @@
1
+ // const { TiledeskClient } = require('@tiledesk/tiledesk-client');
2
+ const { rejects } = require('assert');
3
+ const { DirIntent } = require('./DirIntent');
4
+ const axios = require("axios").default;
5
+ let https = require("https");
6
+
7
+ class DirIfOnlineAgentsV2 {
8
+
9
+ constructor(context) {
10
+ if (!context) {
11
+ throw new Error('context object is mandatory.');
12
+ }
13
+ this.context = context;
14
+ this.chatbot = context.chatbot;
15
+ this.tdclient = context.tdclient;
16
+ this.intentDir = new DirIntent(context);
17
+ this.log = context.log;
18
+ }
19
+
20
+ execute(directive, callback) {
21
+ let action;
22
+ if (directive.action) {
23
+ action = directive.action
24
+ }
25
+ else {
26
+ callback();
27
+ return;
28
+ }
29
+ this.go(action, (stop) => {
30
+ callback(stop);
31
+ });
32
+ }
33
+
34
+ async go(action, callback) {
35
+ console.log("(DirIfOnlineAgents) action:", action);
36
+ if (!action.trueIntent && !action.falseIntent) {
37
+ if (this.log) {
38
+ console.log("Error DirIfOnlineAgents: missing both action.trueIntent & action.falseIntent");
39
+ }
40
+ callback();
41
+ return;
42
+ }
43
+ const trueIntent = action.trueIntent;
44
+ const falseIntent = action.falseIntent;
45
+ if (this.log) {
46
+ console.log("(DirIfOnlineAgents) IfOnlineAgents:trueIntent:", trueIntent);
47
+ console.log("(DirIfOnlineAgents) IfOnlineAgents:falseIntent:", falseIntent);
48
+ }
49
+ const trueIntentAttributes = action.trueIntentAttributes;
50
+ const falseIntentAttributes = action.falseIntentAttributes;
51
+ let stopOnConditionMet = true; //action.stopOnConditionMet;
52
+
53
+ try {
54
+ const result = await this.openNow();
55
+ if (result && result.isopen) {
56
+ const selectedOption = action.selectedOption;
57
+
58
+ let agents;
59
+ if (selectedOption === "currentDep") {
60
+ console.log("(DirIfOnlineAgents) selectedOption === currentDep. Current department:", this.context.departmentId);
61
+ agents = await this.getDepartmentAvailableAgents(this.context.departmentId);
62
+ console.log("(DirIfOnlineAgents) agents:", agents);
63
+ }
64
+ else if (selectedOption === "selectedDep") {
65
+ console.log("(DirIfOnlineAgents) selectedOption === selectedDep", action.selectedDepartmentId);
66
+ agents = await this.getDepartmentAvailableAgents(action.selectedDepartmentId);
67
+ console.log("(DirIfOnlineAgents) agents:", agents);
68
+ }
69
+ else { // if (checkAll) => go project-wide
70
+ console.log("(DirIfOnlineAgents) selectedOption === all");
71
+ agents = await this.getProjectAvailableAgents();
72
+ console.log("(DirIfOnlineAgents) agents:", agents);
73
+ }
74
+
75
+ if (agents && agents.length > 0) {
76
+ if (trueIntent) {
77
+ let intentDirective = DirIntent.intentDirectiveFor(trueIntent, trueIntentAttributes);
78
+ if (this.log) {console.log("agents (openHours) => trueIntent");}
79
+ this.intentDir.execute(intentDirective, () => {
80
+ callback(stopOnConditionMet);
81
+ });
82
+ }
83
+ else {
84
+ console.log("(DirIfOnlineAgents) No IfOnlineAgents trueIntent defined. callback()") // prod
85
+ this.chatbot.addParameter("flowError", "(If online Agents) No IfOnlineAgents success path defined.");
86
+ callback();
87
+ return;
88
+ }
89
+ }
90
+ else if (falseIntent) { // no agents available
91
+ let intentDirective = DirIntent.intentDirectiveFor(falseIntent, falseIntentAttributes);
92
+ if (this.log) {console.log("(DirIfOnlineAgents) !agents (openHours) => falseIntent", intentDirective);}
93
+ this.intentDir.execute(intentDirective, () => {
94
+ callback(stopOnConditionMet);
95
+ });
96
+ }
97
+ else {
98
+ if (this.log) {console.log("(DirIfOnlineAgents) Error: No falseIntent defined", intentDirective);}
99
+ this.chatbot.addParameter("flowError", "(If online Agents) No path for 'no available agents' defined.");
100
+ callback();
101
+ }
102
+ }
103
+ }
104
+ catch(err) {
105
+ console.error("(DirIfOnlineAgents) An error occurred:", err);
106
+ this.chatbot.addParameter("flowError", "(If online Agents) An error occurred: " + err);
107
+ callback();
108
+ }
109
+ }
110
+
111
+ async openNow() {
112
+ return new Promise( (resolve, reject) => {
113
+ this.tdclient.openNow(async (err, result) => {
114
+ if (this.log) {console.log("(DirIfOnlineAgents) openNow():", result);}
115
+ if (err) {
116
+ reject(err);
117
+ }
118
+ else {
119
+ resolve(result);
120
+ }
121
+ });
122
+ });
123
+ }
124
+
125
+ async getProjectAvailableAgents() {
126
+ return new Promise( (resolve, reject) => {
127
+ this.tdclient.getProjectAvailableAgents((err, agents) => {
128
+ if (err) {
129
+ reject(err);
130
+ }
131
+ else {
132
+ resolve(agents);
133
+ }
134
+ });
135
+ })
136
+ }
137
+
138
+ async getDepartmentAvailableAgents(depId) {
139
+ return new Promise( (resolve, reject) => {
140
+ this.tdclient.getDepartment(depId, async (error, dep) => {
141
+ if (error) {
142
+ reject(error);
143
+ }
144
+ else {
145
+ console.log("(DirIfOnlineAgents) got department:", JSON.stringify(dep));
146
+ const groupId = dep.id_group;
147
+ console.log("(DirIfOnlineAgents) department.groupId:", groupId);
148
+ try {
149
+ if (groupId) {
150
+ const group = await this.getGroup(groupId);
151
+ console.log("(DirIfOnlineAgents) got group info:", group);
152
+ if (group) {
153
+ if (group.members) {
154
+ console.log("(DirIfOnlineAgents) group members ids:", group.members);
155
+ // let group_members = await getTeammates(group.members);
156
+ // console.log("group members details:", group_members);
157
+ let all_teammates = await this.getAllTeammates();
158
+ console.log("(DirIfOnlineAgents) all teammates:", all_teammates);
159
+ if (all_teammates && all_teammates.length > 0){
160
+ // [
161
+ // {
162
+ // "user_available": false,
163
+ // ...
164
+ // "id_user": {
165
+ // "status": 100,
166
+ // "email": "michele@tiledesk.com",
167
+ // "firstname": "Michele",
168
+ // "lastname": "Pomposo",
169
+ // ...
170
+ // },
171
+ // "role": "admin",
172
+ // "tags": [],
173
+ // "presence": {
174
+ // "status": "offline",
175
+ // "changedAt": "2023-11-16T12:37:31.990Z"
176
+ // },
177
+ // "isBusy": false
178
+ // }, ... ]
179
+ // filter on availability
180
+ console.log("(DirIfOnlineAgents) filtering available agents for group:", groupId);
181
+ let available_agents = [];
182
+ all_teammates.forEach((agent) => {
183
+ console.log("Checking teammate:", agent.id_user._id, "(", agent.id_user.email ,") Available:", agent.user_available, ") with members:",group.members );
184
+ if (agent.user_available === true && group.members.includes(agent.id_user._id)) {
185
+ console.log("Adding teammate:", agent.id_user._id);
186
+ available_agents.push(agent);
187
+ }
188
+ });
189
+ console.log("(DirIfOnlineAgents) available agents in group:", available_agents);
190
+ resolve(available_agents);
191
+ }
192
+ }
193
+ else {
194
+ this.chatbot.addParameter("flowError", "(If online Agents) Empty group:" + groupId);
195
+ resolve([]);
196
+ }
197
+ }
198
+ else {
199
+ this.chatbot.addParameter("flowError", "(If online Agents) Error: no group for groupId:" + groupId);
200
+ resolve([]);
201
+ }
202
+ }
203
+ else {
204
+ // no group => assigned to all teammates
205
+ const agents = await this.getProjectAvailableAgents();
206
+ resolve(agents);
207
+ }
208
+ }
209
+ catch(error) {
210
+ console.error("(DirIfOnlineAgents) Error:", error);
211
+ reject(error);
212
+ }
213
+ }
214
+ });
215
+ });
216
+ }
217
+
218
+ // async getGroup(groupId, callback) {
219
+ // return new Promise ( (resolve, reject) => {
220
+ // const URL = `${this.APIURL}/${this.projectId}/groups/${groupId}`
221
+ // const HTTPREQUEST = {
222
+ // url: URL,
223
+ // headers: {
224
+ // 'Content-Type' : 'application/json',
225
+ // 'Authorization': this.context.token
226
+ // },
227
+ // method: 'GET',
228
+ // httpsOptions: this.httpsOptions
229
+ // };
230
+ // TiledeskClient.myrequest(
231
+ // HTTPREQUEST,
232
+ // function(err, resbody) {
233
+ // if (err) {
234
+ // reject(err);
235
+ // if (callback) {
236
+ // callback(err);
237
+ // }
238
+ // }
239
+ // else {
240
+ // resolve(resbody);
241
+ // if (callback) {
242
+ // callback(null, resbody);
243
+ // }
244
+ // }
245
+ // }, this.log
246
+ // );
247
+ // });
248
+ // }
249
+
250
+ async getGroup(groupId, callback) {
251
+ return new Promise ( (resolve, reject) => {
252
+ const URL = `${this.context.TILEDESK_APIURL}/${this.context.projectId}/groups/${groupId}`
253
+ const HTTPREQUEST = {
254
+ url: URL,
255
+ headers: {
256
+ 'Content-Type' : 'application/json',
257
+ 'Authorization': this.fixToken(this.context.token)
258
+ },
259
+ method: 'GET',
260
+ httpsOptions: this.httpsOptions
261
+ };
262
+ this.#myrequest(
263
+ HTTPREQUEST,
264
+ function(err, resbody) {
265
+ if (err) {
266
+ reject(err);
267
+ if (callback) {
268
+ callback(err);
269
+ }
270
+ }
271
+ else {
272
+ // {
273
+ // "members": [
274
+ // "62b317986993970035f0697e",
275
+ // "5aaa99024c3b110014b478f0"
276
+ // ],
277
+ // "_id": "65ddec23fd8dc3003295cdd7",
278
+ // "name": "Sales",
279
+ // "trashed": false,
280
+ // "id_project": "65203e12f8c0cf002cf4110b",
281
+ // "createdBy": "5e09d16d4d36110017506d7f",
282
+ // "createdAt": "2024-02-27T14:05:23.373Z",
283
+ // "updatedAt": "2024-02-27T14:05:29.137Z",
284
+ // "__v": 0
285
+ // }
286
+ resolve(resbody);
287
+ if (callback) {
288
+ callback(null, resbody);
289
+ }
290
+ }
291
+ }, this.log
292
+ );
293
+ });
294
+ }
295
+
296
+ async getAllTeammates(members, callback) {
297
+ return new Promise ( (resolve, reject) => {
298
+ const URL = `${this.context.TILEDESK_APIURL}/${this.context.projectId}/project_users`
299
+ const HTTPREQUEST = {
300
+ url: URL,
301
+ headers: {
302
+ 'Content-Type' : 'application/json',
303
+ 'Authorization': this.fixToken(this.context.token)
304
+ },
305
+ method: 'GET',
306
+ httpsOptions: this.httpsOptions
307
+ };
308
+ this.#myrequest(
309
+ HTTPREQUEST,
310
+ function(err, resbody) {
311
+ if (err) {
312
+ reject(err);
313
+ if (callback) {
314
+ callback(err);
315
+ }
316
+ }
317
+ else {
318
+ // {
319
+ // "members": [
320
+ // "62b317986993970035f0697e",
321
+ // "5aaa99024c3b110014b478f0"
322
+ // ],
323
+ // "_id": "65ddec23fd8dc3003295cdd7",
324
+ // "name": "Sales",
325
+ // "trashed": false,
326
+ // "id_project": "65203e12f8c0cf002cf4110b",
327
+ // "createdBy": "5e09d16d4d36110017506d7f",
328
+ // "createdAt": "2024-02-27T14:05:23.373Z",
329
+ // "updatedAt": "2024-02-27T14:05:29.137Z",
330
+ // "__v": 0
331
+ // }
332
+ resolve(resbody);
333
+ if (callback) {
334
+ callback(null, resbody);
335
+ }
336
+ }
337
+ }, this.log
338
+ );
339
+ });
340
+ }
341
+
342
+ #myrequest(options, callback) {
343
+ if (this.log) {
344
+ console.log("API URL:", options.url);
345
+ console.log("** Options:", JSON.stringify(options));
346
+ }
347
+ let axios_options = {
348
+ url: options.url,
349
+ method: options.method,
350
+ params: options.params,
351
+ headers: options.headers
352
+ }
353
+ if (options.json !== null) {
354
+ axios_options.data = options.json
355
+ }
356
+ if (this.log) {
357
+ console.log("axios_options:", JSON.stringify(axios_options));
358
+ }
359
+ if (options.url.startsWith("https:")) {
360
+ const httpsAgent = new https.Agent({
361
+ rejectUnauthorized: false,
362
+ });
363
+ axios_options.httpsAgent = httpsAgent;
364
+ }
365
+ axios(axios_options)
366
+ .then((res) => {
367
+ if (this.log) {
368
+ console.log("Response for url:", options.url);
369
+ console.log("Response headers:\n", JSON.stringify(res.headers));
370
+ }
371
+ if (res && res.status == 200 && res.data) {
372
+ if (callback) {
373
+ callback(null, res.data);
374
+ }
375
+ }
376
+ else {
377
+ if (callback) {
378
+ callback(new Error("Response status is not 200"), null);
379
+ }
380
+ }
381
+ })
382
+ .catch((error) => {
383
+ if (callback) {
384
+ callback(error, null);
385
+ }
386
+ });
387
+ }
388
+
389
+ fixToken(token) {
390
+ if (token.startsWith('JWT ')) {
391
+ return token
392
+ }
393
+ else {
394
+ return 'JWT ' + token
395
+ }
396
+ }
397
+ }
398
+
399
+ module.exports = { DirIfOnlineAgentsV2 };
@@ -3,8 +3,9 @@ const { TiledeskChatbot } = require('../../models/TiledeskChatbot');
3
3
  const { TiledeskChatbotConst } = require('../../models/TiledeskChatbotConst');
4
4
  const { TiledeskChatbotUtil } = require('../../models/TiledeskChatbotUtil');
5
5
  const { DirIntent } = require("./DirIntent");
6
- const { defaultOptions } = require('liquidjs');
6
+ // const { defaultOptions } = require('liquidjs');
7
7
  const { DirMessageToBot } = require('./DirMessageToBot');
8
+ const { v4: uuidv4 } = require('uuid');
8
9
 
9
10
  class DirReplyV2 {
10
11
 
@@ -84,13 +85,15 @@ class DirReplyV2 {
84
85
  const noInputIntent = action.noInputIntent;
85
86
  const noInputTimeout = action.noInputTimeout;
86
87
  if (this.log) { console.log("noInputTimeout found:", noInputTimeout); }
87
- if (noInputTimeout > 0 && noInputTimeout < 300000) {
88
- await this.chatbot.addParameter("userInput", false); // control variable. On each user input is set to true
89
- if (this.log) { console.log("Set userInput: false, checking...", await this.chatbot.getParameter("userInput")); }
88
+ if (noInputTimeout > 0 && noInputTimeout < 7776000) {
89
+ const timeout_id = uuidv4();
90
+ await this.chatbot.addParameter(TiledeskChatbotConst.USER_INPUT, timeout_id); // control variable. On each user input is removed
91
+ if (this.log) { console.log("Set userInput: false, checking...", await this.chatbot.getParameter(TiledeskChatbotConst.USER_INPUT)); }
90
92
  setTimeout(async () => {
91
93
  if (this.log) { console.log("noinput timeout triggered!"); }
92
- let userInput = await this.chatbot.getParameter("userInput");
93
- if (!userInput) {
94
+ const userInput = await this.chatbot.getParameter(TiledeskChatbotConst.USER_INPUT);
95
+ if (this.log) { console.log("got 'userInput':", userInput); }
96
+ if (userInput && userInput === timeout_id) {
94
97
  if (this.log) { console.log("no 'userInput'. Executing noinput action:", noInputIntent); }
95
98
  await this.chatbot.unlockIntent(this.requestId);
96
99
  await this.chatbot.unlockAction(this.requestId);
@@ -100,6 +103,9 @@ class DirReplyV2 {
100
103
  if (this.log) { console.log("noinput action invoked", noinput_action); }
101
104
  });
102
105
  }
106
+ else {
107
+ if (this.log) { console.log("skipping noinput action because of userInput", userInput); }
108
+ }
103
109
  }, noInputTimeout);
104
110
  }
105
111
  }
@@ -48,6 +48,7 @@ class Directives {
48
48
  static PLAY_PROMPT = 'play_prompt';
49
49
  static GPT_ASSISTANT = 'gpt_assistant';
50
50
  static REPLY_V2 = 'replyv2';
51
+ static IF_ONLINE_AGENTS_V2 = "ifonlineagentsv2";
51
52
 
52
53
  // static WHEN_ONLINE_MOVE_TO_AGENT = "whenonlinemovetoagent"; // DEPRECATED?
53
54
  // static WHEN_OFFLINE_HOURS = "whenofflinehours"; // DEPRECATED // adds a message on top of the original message when offline hours opts: --replace