@tiledesk/tiledesk-tybot-connector 2.1.2 → 2.1.5
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/AnalyticsClient.js +21 -3
- package/CHANGELOG.md +3 -0
- package/TiledeskWhenExpression.js +541 -0
- package/engine/TiledeskChatbot.js +12 -9
- package/index.js +11 -9
- package/logs/app1.log +2971 -0
- package/package.json +1 -1
- package/services/DataTablesService.js +180 -0
- package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +38 -19
- package/tiledeskChatbotPlugs/directives/DirAiCondition.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirAiPrompt.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirAskGPT.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirAskGPTV2.js +1 -1
- package/tiledeskChatbotPlugs/directives/DirDataTables.js +293 -0
- package/tiledeskChatbotPlugs/directives/DirJSONConditionV2.js +154 -0
- package/tiledeskChatbotPlugs/directives/DirMoveToAgent.js +13 -10
- package/tiledeskChatbotPlugs/directives/DirReplaceBotV2.js +10 -7
- package/tiledeskChatbotPlugs/directives/DirReplaceBotV3.js +10 -7
- package/tiledeskChatbotPlugs/directives/Directives.js +2 -1
package/package.json
CHANGED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
const httpUtils = require('../utils/HttpUtils');
|
|
2
|
+
const winston = require('../utils/winston');
|
|
3
|
+
const API_ENDPOINT = process.env.API_ENDPOINT;
|
|
4
|
+
|
|
5
|
+
class DataTablesService {
|
|
6
|
+
|
|
7
|
+
constructor() { }
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* GET /{projectId}/tables/{tableId}/rows/list
|
|
11
|
+
* @param {string} projectId
|
|
12
|
+
* @param {string} tableId
|
|
13
|
+
* @param {string} token
|
|
14
|
+
* @param {object} [options]
|
|
15
|
+
* @param {'all'|'any'} [options.must_match]
|
|
16
|
+
* @param {'all'|'any'} [options.match] - alias di must_match
|
|
17
|
+
* @param {Array<{column: string, operator: string, value?: *}>} [options.conditions]
|
|
18
|
+
*/
|
|
19
|
+
async listRows(projectId, tableId, token, options = {}) {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
const params = {};
|
|
22
|
+
if (options.must_match) {
|
|
23
|
+
params.must_match = options.must_match;
|
|
24
|
+
}
|
|
25
|
+
if (options.match) {
|
|
26
|
+
params.match = options.match;
|
|
27
|
+
}
|
|
28
|
+
if (options.conditions && options.conditions.length > 0) {
|
|
29
|
+
params.conditions = JSON.stringify(options.conditions);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const http_request = {
|
|
33
|
+
url: `${API_ENDPOINT}/${projectId}/tables/${tableId}/rows/list`,
|
|
34
|
+
headers: {
|
|
35
|
+
'Content-Type': 'application/json',
|
|
36
|
+
'Authorization': 'JWT ' + token
|
|
37
|
+
},
|
|
38
|
+
params,
|
|
39
|
+
method: 'GET'
|
|
40
|
+
};
|
|
41
|
+
winston.debug('DataTablesService listRows', http_request);
|
|
42
|
+
|
|
43
|
+
httpUtils.request(http_request, (err, response) => {
|
|
44
|
+
if (err) {
|
|
45
|
+
winston.error('DataTablesService listRows error:', err?.response?.data || err);
|
|
46
|
+
reject(err);
|
|
47
|
+
} else {
|
|
48
|
+
resolve(response);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* POST /{projectId}/tables/{tableId}/row/insert
|
|
56
|
+
* @param {string} projectId
|
|
57
|
+
* @param {string} tableId
|
|
58
|
+
* @param {string} token
|
|
59
|
+
* @param {{ data: object, id_row?: string }} body
|
|
60
|
+
*/
|
|
61
|
+
async insertRow(projectId, tableId, token, body) {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
const http_request = {
|
|
64
|
+
url: `${API_ENDPOINT}/${projectId}/tables/${tableId}/row/insert`,
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
'Authorization': 'JWT ' + token
|
|
68
|
+
},
|
|
69
|
+
json: body,
|
|
70
|
+
method: 'POST'
|
|
71
|
+
};
|
|
72
|
+
winston.debug('DataTablesService insertRow', http_request);
|
|
73
|
+
|
|
74
|
+
httpUtils.request(http_request, (err, response) => {
|
|
75
|
+
if (err) {
|
|
76
|
+
winston.error('DataTablesService insertRow error:', err?.response?.data || err);
|
|
77
|
+
reject(err);
|
|
78
|
+
} else {
|
|
79
|
+
resolve(response);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* PUT /{projectId}/tables/{tableId}/row/update
|
|
87
|
+
* @param {string} projectId
|
|
88
|
+
* @param {string} tableId
|
|
89
|
+
* @param {string} token
|
|
90
|
+
* @param {{ id_row?: string, must_match?: string, match?: string, conditions?: Array, data: object }} body
|
|
91
|
+
*/
|
|
92
|
+
async updateRow(projectId, tableId, token, body) {
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
const http_request = {
|
|
95
|
+
url: `${API_ENDPOINT}/${projectId}/tables/${tableId}/row/update`,
|
|
96
|
+
headers: {
|
|
97
|
+
'Content-Type': 'application/json',
|
|
98
|
+
'Authorization': 'JWT ' + token
|
|
99
|
+
},
|
|
100
|
+
json: body,
|
|
101
|
+
method: 'PUT'
|
|
102
|
+
};
|
|
103
|
+
winston.debug('DataTablesService updateRow', http_request);
|
|
104
|
+
|
|
105
|
+
httpUtils.request(http_request, (err, response) => {
|
|
106
|
+
if (err) {
|
|
107
|
+
winston.error('DataTablesService updateRow error:', err?.response?.data || err);
|
|
108
|
+
reject(err);
|
|
109
|
+
} else {
|
|
110
|
+
resolve(response);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* PUT /{projectId}/tables/{tableId}/row/upsert
|
|
118
|
+
* @param {string} projectId
|
|
119
|
+
* @param {string} tableId
|
|
120
|
+
* @param {string} token
|
|
121
|
+
* @param {{ id_row?: string, must_match?: string, match?: string, conditions?: Array, data: object, multi?: boolean }} body
|
|
122
|
+
*/
|
|
123
|
+
async upsertRow(projectId, tableId, token, body) {
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
const http_request = {
|
|
126
|
+
url: `${API_ENDPOINT}/${projectId}/tables/${tableId}/row/upsert`,
|
|
127
|
+
headers: {
|
|
128
|
+
'Content-Type': 'application/json',
|
|
129
|
+
'Authorization': 'JWT ' + token
|
|
130
|
+
},
|
|
131
|
+
json: body,
|
|
132
|
+
method: 'PUT'
|
|
133
|
+
};
|
|
134
|
+
winston.debug('DataTablesService upsertRow', http_request);
|
|
135
|
+
|
|
136
|
+
httpUtils.request(http_request, (err, response) => {
|
|
137
|
+
if (err) {
|
|
138
|
+
winston.error('DataTablesService upsertRow error:', err?.response?.data || err);
|
|
139
|
+
reject(err);
|
|
140
|
+
} else {
|
|
141
|
+
resolve(response);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* PUT /{projectId}/tables/{tableId}/row/delete
|
|
149
|
+
* @param {string} projectId
|
|
150
|
+
* @param {string} tableId
|
|
151
|
+
* @param {string} token
|
|
152
|
+
* @param {{ id_row?: string, must_match?: string, match?: string, conditions?: Array }} body
|
|
153
|
+
*/
|
|
154
|
+
async deleteRow(projectId, tableId, token, body) {
|
|
155
|
+
return new Promise((resolve, reject) => {
|
|
156
|
+
const http_request = {
|
|
157
|
+
url: `${API_ENDPOINT}/${projectId}/tables/${tableId}/row/delete`,
|
|
158
|
+
headers: {
|
|
159
|
+
'Content-Type': 'application/json',
|
|
160
|
+
'Authorization': 'JWT ' + token
|
|
161
|
+
},
|
|
162
|
+
json: body,
|
|
163
|
+
method: 'PUT'
|
|
164
|
+
};
|
|
165
|
+
winston.debug('DataTablesService deleteRow', http_request);
|
|
166
|
+
|
|
167
|
+
httpUtils.request(http_request, (err, response) => {
|
|
168
|
+
if (err) {
|
|
169
|
+
winston.error('DataTablesService deleteRow error:', err?.response?.data || err);
|
|
170
|
+
reject(err);
|
|
171
|
+
} else {
|
|
172
|
+
resolve(response);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const dataTablesService = new DataTablesService();
|
|
180
|
+
module.exports = dataTablesService;
|
|
@@ -22,6 +22,7 @@ const { DirIfOpenHours } = require('./directives/DirIfOpenHours');
|
|
|
22
22
|
const { DirAssignFromFunction } = require('./directives/DirAssignFromFunction');
|
|
23
23
|
const { DirCondition } = require('./directives/DirCondition');
|
|
24
24
|
const { DirJSONCondition } = require('./directives/DirJSONCondition');
|
|
25
|
+
const { DirJSONConditionV2 } = require('./directives/DirJSONConditionV2');
|
|
25
26
|
const { DirAssign } = require('./directives/DirAssign');
|
|
26
27
|
const { DirSetAttribute } = require('./directives/DirSetAttribute');
|
|
27
28
|
const { DirSetAttributeV2 } = require('./directives/DirSetAttributeV2');
|
|
@@ -64,6 +65,7 @@ const { DirFlowLog } = require('./directives/DirFlowLog');
|
|
|
64
65
|
const { DirAddKbContent } = require('./directives/DirAddKbContent');
|
|
65
66
|
const { DirIteration } = require('./directives/DirIteration');
|
|
66
67
|
const { AnalyticsClient } = require('../AnalyticsClient');
|
|
68
|
+
const { DirDataTables } = require('./directives/DirDataTables');
|
|
67
69
|
|
|
68
70
|
class DirectivesChatbotPlug {
|
|
69
71
|
|
|
@@ -182,14 +184,17 @@ class DirectivesChatbotPlug {
|
|
|
182
184
|
const go_on = await TiledeskChatbot.checkStep(this.context.tdcache, this.context.requestId, this.chatbot?.MAX_STEPS, this.chatbot?.MAX_EXECUTION_TIME);
|
|
183
185
|
|
|
184
186
|
if (go_on.error) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
187
|
+
// Only track published (production) runs (root/draft copy has no root_id).
|
|
188
|
+
if (this.chatbot?.bot.root_id) {
|
|
189
|
+
AnalyticsClient.track('agent.flow_error', this.context.projectId, {
|
|
190
|
+
agent_id: this.chatbot?.bot.root_id,
|
|
191
|
+
error_type: go_on.error_code || 'runtime_error',
|
|
192
|
+
error_message: go_on.error || null,
|
|
193
|
+
step_count: go_on.step_count || 0,
|
|
194
|
+
intent_name: this.context.reply?.attributes?.intent_info?.intent_name || null,
|
|
195
|
+
request_id: this.context.requestId || null
|
|
196
|
+
});
|
|
197
|
+
}
|
|
193
198
|
winston.debug("(DirectivesChatbotPlug) go_on == false! nextDirective() Stopped!");
|
|
194
199
|
return this.errorMessage(go_on.error); //"Request error: anomaly detection. MAX ACTIONS exeeded.");
|
|
195
200
|
}
|
|
@@ -261,6 +266,7 @@ class DirectivesChatbotPlug {
|
|
|
261
266
|
[Directives.IF_ONLINE_AGENTS_V2]: DirIfOnlineAgentsV2,
|
|
262
267
|
[Directives.FUNCTION_VALUE]: DirAssignFromFunction,
|
|
263
268
|
[Directives.JSON_CONDITION]: DirJSONCondition,
|
|
269
|
+
[Directives.JSON_CONDITION_2]: DirJSONConditionV2, // NEW: JSON Condition V2 (tipo dedicato dal DS); V1 dispatch invariato
|
|
264
270
|
[Directives.ASSIGN]: DirAssign,
|
|
265
271
|
[Directives.SET_ATTRIBUTE]: DirSetAttribute,
|
|
266
272
|
[Directives.SET_ATTRIBUTE_V2]: DirSetAttributeV2,
|
|
@@ -304,6 +310,7 @@ class DirectivesChatbotPlug {
|
|
|
304
310
|
[Directives.WEB_RESPONSE]: DirWebResponse,
|
|
305
311
|
[Directives.FLOW_LOG]: DirFlowLog,
|
|
306
312
|
[Directives.ITERATION]: DirIteration,
|
|
313
|
+
[Directives.DATA_TABLES]: DirDataTables,
|
|
307
314
|
};
|
|
308
315
|
|
|
309
316
|
const HandlerClass = handlers[directive_name];
|
|
@@ -318,17 +325,29 @@ class DirectivesChatbotPlug {
|
|
|
318
325
|
|
|
319
326
|
const blockStart = Date.now();
|
|
320
327
|
handler.execute(directive, async (stop) => {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
328
|
+
// [analytics-debug] Trace the block_executed decision per directive so we can
|
|
329
|
+
// see whether the event is emitted and why (missing root_id, draft, etc.).
|
|
330
|
+
winston.debug("(DirectivesChatbotPlug) [analytics] block_executed decision:" +
|
|
331
|
+
" directive_type=" + (directive.name || 'unknown') +
|
|
332
|
+
" block_id=" + (directive.action?.["_tdActionId"] || '<empty>') +
|
|
333
|
+
" root_id=" + (this.context.chatbot?.bot?.root_id || '<none>') +
|
|
334
|
+
" draft=" + (this.context.supportRequest?.draft) +
|
|
335
|
+
" stop=" + stop +
|
|
336
|
+
" willEmit=" + (!!this.context.chatbot?.bot?.root_id));
|
|
337
|
+
// Only track published (production) runs (root/draft copy has no root_id).
|
|
338
|
+
if (this.context.chatbot?.bot.root_id) {
|
|
339
|
+
AnalyticsClient.track('agent.block_executed', this.context.projectId, {
|
|
340
|
+
agent_id: this.context.chatbot?.bot.root_id,
|
|
341
|
+
block_id: directive.action?.["_tdActionId"] || '',
|
|
342
|
+
block_name: directive.action?.["_tdActionTitle"] || directive.action?.name || 'unnamed',
|
|
343
|
+
directive_type: directive.name || 'unknown',
|
|
344
|
+
intent_id: this.context.chatbot?._lastIntentId || '',
|
|
345
|
+
intent_name: this.context.reply?.attributes?.intent_info?.intent_name || null,
|
|
346
|
+
duration_ms: Date.now() - blockStart,
|
|
347
|
+
success: !stop,
|
|
348
|
+
request_id: this.context.requestId || null
|
|
349
|
+
});
|
|
350
|
+
}
|
|
332
351
|
if (stop) {
|
|
333
352
|
winston.debug(`(DirectivesChatbotPlug) Stopping Actions on:`, directive);
|
|
334
353
|
return this.theend();
|
|
@@ -195,7 +195,7 @@ class DirAiCondition {
|
|
|
195
195
|
max_tokens: action.max_tokens,
|
|
196
196
|
id_project: this.projectId,
|
|
197
197
|
request_id: this.requestId,
|
|
198
|
-
agent_id: this.chatbot?.bot.root_id ||
|
|
198
|
+
agent_id: this.chatbot?.bot.root_id || null
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
if (action.context) {
|
|
@@ -256,7 +256,7 @@ class DirAiPrompt {
|
|
|
256
256
|
max_tokens: action.max_tokens,
|
|
257
257
|
id_project: this.projectId,
|
|
258
258
|
request_id: this.requestId,
|
|
259
|
-
agent_id: this.chatbot?.bot.root_id ||
|
|
259
|
+
agent_id: this.chatbot?.bot.root_id || null
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
if (action.context) {
|
|
@@ -133,7 +133,7 @@ class DirAskGPT {
|
|
|
133
133
|
question: filled_question,
|
|
134
134
|
kbid: action.kbid,
|
|
135
135
|
gptkey: key,
|
|
136
|
-
agent_id: this.chatbot?.bot.root_id ||
|
|
136
|
+
agent_id: this.chatbot?.bot.root_id || null,
|
|
137
137
|
id_project: this.projectId,
|
|
138
138
|
request_id: this.requestId
|
|
139
139
|
};
|
|
@@ -296,7 +296,7 @@ class DirAskGPTV2 {
|
|
|
296
296
|
stream: false,
|
|
297
297
|
id_project: this.projectId,
|
|
298
298
|
request_id: this.requestId,
|
|
299
|
-
agent_id: this.chatbot?.bot.root_id ||
|
|
299
|
+
agent_id: this.chatbot?.bot.root_id || null,
|
|
300
300
|
};
|
|
301
301
|
if (top_k) {
|
|
302
302
|
json.top_k = top_k;
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
const { TiledeskChatbot } = require("../../engine/TiledeskChatbot");
|
|
2
|
+
const { Filler } = require("../Filler");
|
|
3
|
+
const { DirIntent } = require("./DirIntent");
|
|
4
|
+
const winston = require('../../utils/winston');
|
|
5
|
+
const { Logger } = require("../../Logger");
|
|
6
|
+
const dataTablesService = require("../../services/DataTablesService");
|
|
7
|
+
|
|
8
|
+
const SUPPORTED_OPERATIONS = ['get', 'insert', 'update', 'delete', 'upsert'];
|
|
9
|
+
const ROW_DOCUMENT_OPERATIONS = ['insert', 'update', 'delete', 'upsert'];
|
|
10
|
+
|
|
11
|
+
class DirDataTables {
|
|
12
|
+
|
|
13
|
+
constructor(context) {
|
|
14
|
+
if (!context) {
|
|
15
|
+
throw new Error('context object is mandatory.');
|
|
16
|
+
}
|
|
17
|
+
this.context = context;
|
|
18
|
+
this.chatbot = context.chatbot;
|
|
19
|
+
this.tdcache = context.tdcache;
|
|
20
|
+
this.requestId = context.requestId;
|
|
21
|
+
this.projectId = context.projectId;
|
|
22
|
+
this.token = context.token;
|
|
23
|
+
this.API_ENDPOINT = context.API_ENDPOINT;
|
|
24
|
+
|
|
25
|
+
this.intentDir = new DirIntent(context);
|
|
26
|
+
this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest?.draft, intent_id: this.context.reply?.intent_id || this.context.reply?.attributes?.intent_info?.intent_id });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
execute(directive, callback) {
|
|
30
|
+
winston.debug("DirDataTables directive: ", directive);
|
|
31
|
+
let action;
|
|
32
|
+
if (directive.action) {
|
|
33
|
+
action = directive.action;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.logger.error("Incorrect action for ", directive.name, directive);
|
|
37
|
+
winston.debug("DirDataTables Incorrect directive: ", directive);
|
|
38
|
+
callback();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.go(action, (stop) => {
|
|
42
|
+
this.logger.native("[DataTables] Executed");
|
|
43
|
+
callback(stop);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async go(action, callback) {
|
|
48
|
+
winston.debug("DirDataTables action: ", action);
|
|
49
|
+
if (!this.tdcache) {
|
|
50
|
+
winston.error("DirDataTables Error: tdcache is mandatory");
|
|
51
|
+
callback();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const trueIntent = action.trueIntent;
|
|
56
|
+
const falseIntent = action.falseIntent;
|
|
57
|
+
const trueIntentAttributes = action.trueIntentAttributes;
|
|
58
|
+
const falseIntentAttributes = action.falseIntentAttributes;
|
|
59
|
+
|
|
60
|
+
const requestVariables = await TiledeskChatbot.allParametersStatic(this.tdcache, this.requestId);
|
|
61
|
+
const filler = new Filler();
|
|
62
|
+
|
|
63
|
+
const tableId = filler.fill(action.tableId, requestVariables);
|
|
64
|
+
const operation = action.operation;
|
|
65
|
+
|
|
66
|
+
if (!tableId) {
|
|
67
|
+
const error = "tableId is required";
|
|
68
|
+
this.logger.error("[DataTables] " + error);
|
|
69
|
+
await this.#assignAttributes(action, null, error);
|
|
70
|
+
if (falseIntent) {
|
|
71
|
+
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
72
|
+
callback(true);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
callback();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!operation || !SUPPORTED_OPERATIONS.includes(operation)) {
|
|
80
|
+
const error = `operation must be one of: ${SUPPORTED_OPERATIONS.join(', ')}`;
|
|
81
|
+
this.logger.error("[DataTables] " + error);
|
|
82
|
+
await this.#assignAttributes(action, null, error);
|
|
83
|
+
if (falseIntent) {
|
|
84
|
+
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
85
|
+
callback(true);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
callback();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
let result;
|
|
94
|
+
switch (operation) {
|
|
95
|
+
case 'get':
|
|
96
|
+
result = await dataTablesService.listRows(this.projectId, tableId, this.token, {
|
|
97
|
+
must_match: action.must_match,
|
|
98
|
+
conditions: this.#fillConditions(action.conditions, filler, requestVariables)
|
|
99
|
+
});
|
|
100
|
+
break;
|
|
101
|
+
case 'insert':
|
|
102
|
+
result = await dataTablesService.insertRow(this.projectId, tableId, this.token, {
|
|
103
|
+
data: this.#fillData(action.data, filler, requestVariables),
|
|
104
|
+
...(action.id_row ? { id_row: filler.fill(action.id_row, requestVariables) } : {})
|
|
105
|
+
});
|
|
106
|
+
break;
|
|
107
|
+
case 'update':
|
|
108
|
+
result = await dataTablesService.updateRow(this.projectId, tableId, this.token, this.#buildMutationBody(action, filler, requestVariables));
|
|
109
|
+
break;
|
|
110
|
+
case 'delete':
|
|
111
|
+
result = await dataTablesService.deleteRow(this.projectId, tableId, this.token, this.#buildDeleteBody(action, filler, requestVariables));
|
|
112
|
+
break;
|
|
113
|
+
case 'upsert':
|
|
114
|
+
result = await dataTablesService.upsertRow(this.projectId, tableId, this.token, {
|
|
115
|
+
...this.#buildMutationBody(action, filler, requestVariables),
|
|
116
|
+
...(action.multi !== undefined ? { multi: action.multi } : {})
|
|
117
|
+
});
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.logger.native("[DataTables] operation " + operation + " completed");
|
|
122
|
+
await this.#assignAttributes(action, this.#normalizeResult(result, operation), null);
|
|
123
|
+
if (trueIntent) {
|
|
124
|
+
await this.#executeCondition(true, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
125
|
+
callback(true);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
callback();
|
|
129
|
+
} catch (err) {
|
|
130
|
+
const error = this.#extractError(err);
|
|
131
|
+
this.logger.error("[DataTables] " + operation + " error: ", error);
|
|
132
|
+
winston.error("DirDataTables error:", err?.response?.data || err);
|
|
133
|
+
await this.#assignAttributes(action, null, error);
|
|
134
|
+
if (falseIntent) {
|
|
135
|
+
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
136
|
+
callback(true);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
callback();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#fillConditions(conditions, filler, requestVariables) {
|
|
144
|
+
if (!conditions || !Array.isArray(conditions) || conditions.length === 0) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
return conditions.map((condition) => {
|
|
148
|
+
const filled = { ...condition };
|
|
149
|
+
if (filled.value !== undefined && filled.value !== null) {
|
|
150
|
+
filled.value = filler.fill(String(filled.value), requestVariables);
|
|
151
|
+
}
|
|
152
|
+
return filled;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
#fillData(data, filler, requestVariables) {
|
|
157
|
+
if (!data || typeof data !== 'object') {
|
|
158
|
+
return {};
|
|
159
|
+
}
|
|
160
|
+
const filled = {};
|
|
161
|
+
for (const [key, value] of Object.entries(data)) {
|
|
162
|
+
if (value === null || value === undefined) {
|
|
163
|
+
filled[key] = value;
|
|
164
|
+
} else if (typeof value === 'string') {
|
|
165
|
+
filled[key] = filler.fill(value, requestVariables);
|
|
166
|
+
} else {
|
|
167
|
+
filled[key] = value;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return filled;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
#buildMutationBody(action, filler, requestVariables) {
|
|
174
|
+
const body = {
|
|
175
|
+
data: this.#fillData(action.data, filler, requestVariables)
|
|
176
|
+
};
|
|
177
|
+
if (action.id_row) {
|
|
178
|
+
body.id_row = filler.fill(action.id_row, requestVariables);
|
|
179
|
+
}
|
|
180
|
+
if (action.must_match) {
|
|
181
|
+
body.must_match = action.must_match;
|
|
182
|
+
}
|
|
183
|
+
const conditions = this.#fillConditions(action.conditions, filler, requestVariables);
|
|
184
|
+
if (conditions) {
|
|
185
|
+
body.conditions = conditions;
|
|
186
|
+
}
|
|
187
|
+
return body;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
#buildDeleteBody(action, filler, requestVariables) {
|
|
191
|
+
const body = {};
|
|
192
|
+
if (action.id_row) {
|
|
193
|
+
body.id_row = filler.fill(action.id_row, requestVariables);
|
|
194
|
+
}
|
|
195
|
+
if (action.must_match) {
|
|
196
|
+
body.must_match = action.must_match;
|
|
197
|
+
}
|
|
198
|
+
const conditions = this.#fillConditions(action.conditions, filler, requestVariables);
|
|
199
|
+
if (conditions) {
|
|
200
|
+
body.conditions = conditions;
|
|
201
|
+
}
|
|
202
|
+
return body;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
#normalizeResult(result, operation) {
|
|
206
|
+
if (!ROW_DOCUMENT_OPERATIONS.includes(operation) || result === undefined || result === null) {
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
if (Array.isArray(result)) {
|
|
210
|
+
return result.map((row) => this.#extractRowData(row));
|
|
211
|
+
}
|
|
212
|
+
return this.#extractRowData(result);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
#extractRowData(row) {
|
|
216
|
+
if (row && row.data !== undefined && row.data !== null && typeof row.data === 'object' && !Array.isArray(row.data)) {
|
|
217
|
+
return row.data;
|
|
218
|
+
}
|
|
219
|
+
return row;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
#extractError(err) {
|
|
223
|
+
if (err?.response?.data?.message) {
|
|
224
|
+
return err.response.data.message;
|
|
225
|
+
}
|
|
226
|
+
if (err?.response?.data?.error) {
|
|
227
|
+
return err.response.data.error;
|
|
228
|
+
}
|
|
229
|
+
if (err?.response?.data) {
|
|
230
|
+
return typeof err.response.data === 'string' ? err.response.data : JSON.stringify(err.response.data);
|
|
231
|
+
}
|
|
232
|
+
if (err?.message) {
|
|
233
|
+
return err.message;
|
|
234
|
+
}
|
|
235
|
+
return String(err);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async #executeCondition(result, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, callback) {
|
|
239
|
+
let trueIntentDirective = null;
|
|
240
|
+
if (trueIntent) {
|
|
241
|
+
trueIntentDirective = DirIntent.intentDirectiveFor(trueIntent, trueIntentAttributes);
|
|
242
|
+
}
|
|
243
|
+
let falseIntentDirective = null;
|
|
244
|
+
if (falseIntent) {
|
|
245
|
+
falseIntentDirective = DirIntent.intentDirectiveFor(falseIntent, falseIntentAttributes);
|
|
246
|
+
}
|
|
247
|
+
if (result === true) {
|
|
248
|
+
if (trueIntentDirective) {
|
|
249
|
+
this.logger.native("[DataTables] executing true condition");
|
|
250
|
+
this.intentDir.execute(trueIntentDirective, () => {
|
|
251
|
+
if (callback) {
|
|
252
|
+
callback();
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
winston.debug("DirDataTables No trueIntentDirective specified");
|
|
258
|
+
if (callback) {
|
|
259
|
+
callback();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
if (falseIntentDirective) {
|
|
265
|
+
this.logger.native("[DataTables] executing false condition");
|
|
266
|
+
this.intentDir.execute(falseIntentDirective, () => {
|
|
267
|
+
if (callback) {
|
|
268
|
+
callback();
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
winston.debug("DirDataTables No falseIntentDirective specified");
|
|
274
|
+
if (callback) {
|
|
275
|
+
callback();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
async #assignAttributes(action, result, error) {
|
|
282
|
+
if (this.context.tdcache) {
|
|
283
|
+
if (action.assignResultTo && result !== undefined && result !== null) {
|
|
284
|
+
await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignResultTo, result);
|
|
285
|
+
}
|
|
286
|
+
if (action.assignErrorTo && error) {
|
|
287
|
+
await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, action.assignErrorTo, error);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
module.exports = { DirDataTables };
|