wingbot 3.46.0-alpha.1 → 3.46.0-alpha.10
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 +2 -2
- package/src/analytics/consts.js +12 -4
- package/src/analytics/onInteractionHandler.js +144 -57
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wingbot",
|
|
3
|
-
"version": "3.46.0-alpha.
|
|
3
|
+
"version": "3.46.0-alpha.10",
|
|
4
4
|
"description": "Enterprise Messaging Bot Conversation Engine",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"doc": "npm run doc:gql && node ./bin/makeApiDoc.js && cpy ./CHANGELOG.md ./doc && gitbook install ./doc && gitbook build ./doc && rimraf -rf ./docs && rimraf --rf ./doc/CHANGELOG.md && move-cli ./doc/_book ./docs",
|
|
10
10
|
"test": "npm run test:lint && npm run test:coverage && npm run test:coverage:threshold",
|
|
11
11
|
"test:coverage": "nyc --reporter=html mocha ./test && nyc report",
|
|
12
|
-
"test:coverage:threshold": "nyc check-coverage --lines 90 --functions
|
|
12
|
+
"test:coverage:threshold": "nyc check-coverage --lines 90 --functions 89 --branches 80",
|
|
13
13
|
"test:backend": "mocha ./test",
|
|
14
14
|
"test:lint": "eslint --ext .js src test *.js plugins"
|
|
15
15
|
},
|
package/src/analytics/consts.js
CHANGED
|
@@ -42,6 +42,10 @@ const TrackingType = { // max length 12
|
|
|
42
42
|
* @enum {string} TrackingCategory
|
|
43
43
|
*/
|
|
44
44
|
const TrackingCategory = { // max length 3
|
|
45
|
+
// PAGE_VIEW: 'page_view'
|
|
46
|
+
PAGE_VIEW_FIRST: 'pf',
|
|
47
|
+
PAGE_VIEW_SUBSEQUENT: 'pp',
|
|
48
|
+
|
|
45
49
|
// CONVERSATION_EVENT: 'conversation'
|
|
46
50
|
STICKER: 'sti',
|
|
47
51
|
IMAGE: 'img',
|
|
@@ -58,18 +62,22 @@ const TrackingCategory = { // max length 3
|
|
|
58
62
|
|
|
59
63
|
// TRAINING: 'train'
|
|
60
64
|
INTENT_DETECTION: 'int',
|
|
61
|
-
HANDOVER_OCCURRED: 'hum',
|
|
62
65
|
DISAMBIGUATION_SELECTED: 'dis',
|
|
63
66
|
DISAMBIGUATION_OFFERED: 'dio',
|
|
64
67
|
|
|
65
68
|
// REPORT: 'report'
|
|
66
|
-
REPORT_FEEDBACK: 'fdb'
|
|
69
|
+
REPORT_FEEDBACK: 'fdb',
|
|
70
|
+
HANDOVER_OCCURRED: 'hum'
|
|
67
71
|
};
|
|
68
72
|
|
|
69
73
|
/**
|
|
70
74
|
* @type {Object<TrackingCategory,string>}
|
|
71
75
|
*/
|
|
72
76
|
const CATEGORY_LABELS = {
|
|
77
|
+
// PAGE_VIEW: 'page_view'
|
|
78
|
+
[TrackingCategory.PAGE_VIEW_FIRST]: 'Bot: Interaction',
|
|
79
|
+
[TrackingCategory.PAGE_VIEW_SUBSEQUENT]: 'Bot: Sub-interaction',
|
|
80
|
+
|
|
73
81
|
// CONVERSATION_EVENT: 'conversation'
|
|
74
82
|
[TrackingCategory.STICKER]: 'User: Sticker',
|
|
75
83
|
[TrackingCategory.IMAGE]: 'User: Image',
|
|
@@ -86,12 +94,12 @@ const CATEGORY_LABELS = {
|
|
|
86
94
|
|
|
87
95
|
// TRAINING: 'train'
|
|
88
96
|
[TrackingCategory.INTENT_DETECTION]: 'Intent: Detection',
|
|
89
|
-
[TrackingCategory.HANDOVER_OCCURRED]: 'Bot: Handover out',
|
|
90
97
|
[TrackingCategory.DISAMBIGUATION_SELECTED]: 'Disambiguation: selected',
|
|
91
98
|
[TrackingCategory.DISAMBIGUATION_OFFERED]: 'Disambiguation: offered',
|
|
92
99
|
|
|
93
100
|
// REPORT: 'report'
|
|
94
|
-
[TrackingCategory.REPORT_FEEDBACK]: 'User: Feedback'
|
|
101
|
+
[TrackingCategory.REPORT_FEEDBACK]: 'User: Feedback',
|
|
102
|
+
[TrackingCategory.HANDOVER_OCCURRED]: 'Bot: Handover out'
|
|
95
103
|
};
|
|
96
104
|
|
|
97
105
|
module.exports = {
|
|
@@ -31,6 +31,56 @@ const {
|
|
|
31
31
|
* @prop {string} [action]
|
|
32
32
|
* @prop {string} [label]
|
|
33
33
|
* @prop {number} [value]
|
|
34
|
+
* @prop {string} [lang]
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {object} ConversationEventExtension
|
|
39
|
+
* @prop {string} [lastAction]
|
|
40
|
+
* @prop {string} [skill]
|
|
41
|
+
* @prop {string} [text]
|
|
42
|
+
* @prop {string} [expected]
|
|
43
|
+
* @prop {boolean} expectedTaken
|
|
44
|
+
* @prop {boolean} isContextUpdate
|
|
45
|
+
* @prop {boolean} isAttachment
|
|
46
|
+
* @prop {boolean} isNotification
|
|
47
|
+
* @prop {boolean} isQuickReply
|
|
48
|
+
* @prop {boolean} isPassThread
|
|
49
|
+
* @prop {boolean} isPostback
|
|
50
|
+
* @prop {boolean} isText
|
|
51
|
+
* @prop {boolean} didHandover
|
|
52
|
+
* @prop {boolean} withUser
|
|
53
|
+
* @prop {string} [userId]
|
|
54
|
+
* @prop {number} [feedback]
|
|
55
|
+
* @prop {string} [winnerAction]
|
|
56
|
+
* @prop {string} [winnerIntent]
|
|
57
|
+
* @prop {string[]|string} [winnerEntities]
|
|
58
|
+
* @prop {number} [winnerScore]
|
|
59
|
+
* @prop {boolean} [winnerTaken]
|
|
60
|
+
* @prop {string} [intent]
|
|
61
|
+
* @prop {number} [intentScore]
|
|
62
|
+
* @prop {string[]|string} [entities]
|
|
63
|
+
* @prop {string[]|string} allActions
|
|
64
|
+
* @prop {boolean} nonInteractive
|
|
65
|
+
*
|
|
66
|
+
* @typedef {Event & ConversationEventExtension} ConversationEvent
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @typedef {object} PageViewEventExtension
|
|
71
|
+
* @prop {string} [lastAction]
|
|
72
|
+
* @prop {string} [prevAction]
|
|
73
|
+
* @prop {string} [skill]
|
|
74
|
+
* @prop {string[]|string} allActions
|
|
75
|
+
* @prop {boolean} nonInteractive
|
|
76
|
+
* @prop {boolean} isGoto
|
|
77
|
+
* @prop {boolean} withUser
|
|
78
|
+
*
|
|
79
|
+
* @typedef {Event & PageViewEventExtension} PageViewEvent
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @typedef {ConversationEvent | Event | PageViewEvent} TrackingEvent
|
|
34
84
|
*/
|
|
35
85
|
|
|
36
86
|
/**
|
|
@@ -40,6 +90,11 @@ const {
|
|
|
40
90
|
* @prop {string} [action]
|
|
41
91
|
* @prop {string} [snapshot]
|
|
42
92
|
* @prop {string} [botId]
|
|
93
|
+
* @prop {boolean} [didHandover]
|
|
94
|
+
* @prop {number|null} [feedback]
|
|
95
|
+
* @prop {string} [timeZone]
|
|
96
|
+
* @prop {number} [sessionStart]
|
|
97
|
+
* @prop {number} [sessionDuration]
|
|
43
98
|
*/
|
|
44
99
|
|
|
45
100
|
/**
|
|
@@ -50,7 +105,6 @@ const {
|
|
|
50
105
|
* @param {SessionMetadata} [metadata]
|
|
51
106
|
* @param {number} [ts]
|
|
52
107
|
* @param {boolean} [nonInteractive]
|
|
53
|
-
* @param {string} [timeZone]
|
|
54
108
|
* @returns {Promise}
|
|
55
109
|
*/
|
|
56
110
|
|
|
@@ -59,12 +113,12 @@ const {
|
|
|
59
113
|
* @param {string} pageId
|
|
60
114
|
* @param {string} senderId
|
|
61
115
|
* @param {string} sessionId
|
|
62
|
-
* @param {
|
|
116
|
+
* @param {TrackingEvent[]} events
|
|
63
117
|
* @param {GAUser} [user]
|
|
64
118
|
* @param {number} [ts]
|
|
65
119
|
* @param {boolean} [nonInteractive]
|
|
66
120
|
* @param {boolean} [sessionStarted]
|
|
67
|
-
* @param {
|
|
121
|
+
* @param {SessionMetadata} [metadata]
|
|
68
122
|
* @returns {Promise}
|
|
69
123
|
*/
|
|
70
124
|
|
|
@@ -82,6 +136,7 @@ const {
|
|
|
82
136
|
* @prop {boolean} [supportsArrays]
|
|
83
137
|
* @prop {boolean} [useDescriptiveCategories]
|
|
84
138
|
* @prop {boolean} [useExtendedScalars]
|
|
139
|
+
* @prop {boolean} [parallelSessionInsert]
|
|
85
140
|
*/
|
|
86
141
|
|
|
87
142
|
/**
|
|
@@ -98,7 +153,7 @@ const {
|
|
|
98
153
|
|
|
99
154
|
/**
|
|
100
155
|
* @typedef {object} TrackingEvents
|
|
101
|
-
* @prop {
|
|
156
|
+
* @prop {TrackingEvent[]} events
|
|
102
157
|
*/
|
|
103
158
|
|
|
104
159
|
/**
|
|
@@ -160,13 +215,14 @@ function onInteractionHandler (
|
|
|
160
215
|
supportsArrays = false,
|
|
161
216
|
useExtendedScalars = false,
|
|
162
217
|
hasExtendedEvents = false,
|
|
163
|
-
useDescriptiveCategories = true
|
|
218
|
+
useDescriptiveCategories = true,
|
|
219
|
+
parallelSessionInsert = false
|
|
164
220
|
} = analyticsStorage;
|
|
165
221
|
|
|
166
222
|
const asArray = (data = []) => (supportsArrays ? data : data.join(','));
|
|
167
223
|
const asCategory = (cat) => (useDescriptiveCategories && CATEGORY_LABELS[cat]) || cat;
|
|
168
224
|
const noneAction = useExtendedScalars ? null : '(none)';
|
|
169
|
-
const noneValue = useExtendedScalars ?
|
|
225
|
+
const noneValue = useExtendedScalars ? null : 0;
|
|
170
226
|
|
|
171
227
|
/**
|
|
172
228
|
* @param {InteractionEvent} params
|
|
@@ -201,26 +257,59 @@ function onInteractionHandler (
|
|
|
201
257
|
lang
|
|
202
258
|
} = req.state;
|
|
203
259
|
|
|
260
|
+
const trackEvents = [];
|
|
261
|
+
|
|
204
262
|
const [action = noneAction, ...otherActions] = actions;
|
|
205
263
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
264
|
+
const feedbackEvent = events.find((e) => e.type === TrackingType.REPORT
|
|
265
|
+
&& e.category === TrackingCategory.REPORT_FEEDBACK);
|
|
266
|
+
const feedback = feedbackEvent
|
|
267
|
+
? feedbackEvent.value
|
|
268
|
+
: noneValue;
|
|
269
|
+
let didHandover = flag === ResponseFlag.HANDOVER;
|
|
270
|
+
const hasHandoverEvent = events
|
|
271
|
+
.some((e) => e.category === TrackingCategory.HANDOVER_OCCURRED);
|
|
272
|
+
|
|
273
|
+
if (didHandover && !hasHandoverEvent) {
|
|
274
|
+
trackEvents.push({
|
|
275
|
+
type: TrackingType.REPORT,
|
|
276
|
+
category: asCategory(TrackingCategory.HANDOVER_OCCURRED),
|
|
277
|
+
action: null,
|
|
278
|
+
label: null,
|
|
279
|
+
value: noneValue
|
|
280
|
+
});
|
|
281
|
+
} else if (hasHandoverEvent) {
|
|
282
|
+
didHandover = true;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const metadata = {
|
|
286
|
+
sessionCount,
|
|
287
|
+
lang,
|
|
288
|
+
action,
|
|
289
|
+
snapshot,
|
|
290
|
+
botId,
|
|
291
|
+
didHandover,
|
|
292
|
+
feedback,
|
|
293
|
+
timeZone,
|
|
294
|
+
sessionStart,
|
|
295
|
+
sessionDuration: sessionTs - sessionStart
|
|
296
|
+
};
|
|
214
297
|
|
|
215
|
-
|
|
298
|
+
let sessionPromise;
|
|
299
|
+
if (createSession) {
|
|
300
|
+
sessionPromise = analyticsStorage.createUserSession(
|
|
216
301
|
pageId,
|
|
217
302
|
senderId,
|
|
218
303
|
sessionId,
|
|
219
304
|
metadata,
|
|
220
305
|
timestamp,
|
|
221
|
-
nonInteractive
|
|
222
|
-
timeZone
|
|
306
|
+
nonInteractive
|
|
223
307
|
);
|
|
308
|
+
|
|
309
|
+
if (!parallelSessionInsert) {
|
|
310
|
+
await sessionPromise;
|
|
311
|
+
sessionPromise = null;
|
|
312
|
+
}
|
|
224
313
|
}
|
|
225
314
|
|
|
226
315
|
const [{
|
|
@@ -233,6 +322,7 @@ function onInteractionHandler (
|
|
|
233
322
|
: anonymize(
|
|
234
323
|
replaceDiacritics(req.text()).replace(/\s+/g, ' ').toLowerCase().trim()
|
|
235
324
|
);
|
|
325
|
+
const useSkill = (skill && webalize(skill)) || noneAction;
|
|
236
326
|
|
|
237
327
|
let winnerAction = '';
|
|
238
328
|
let winnerScore = 0;
|
|
@@ -253,14 +343,6 @@ function onInteractionHandler (
|
|
|
253
343
|
}
|
|
254
344
|
|
|
255
345
|
const expected = req.expected() ? req.expected().action : '';
|
|
256
|
-
|
|
257
|
-
const feedbackEvent = events.find((e) => e.type === TrackingType.REPORT
|
|
258
|
-
&& e.category === TrackingCategory.REPORT_FEEDBACK);
|
|
259
|
-
const feedback = feedbackEvent
|
|
260
|
-
? feedbackEvent.value
|
|
261
|
-
: noneValue;
|
|
262
|
-
const didHandover = flag === ResponseFlag.HANDOVER;
|
|
263
|
-
|
|
264
346
|
const user = userExtractor(req.state);
|
|
265
347
|
|
|
266
348
|
const isContextUpdate = req.isSetContext();
|
|
@@ -274,12 +356,12 @@ function onInteractionHandler (
|
|
|
274
356
|
const allActions = asArray(actions);
|
|
275
357
|
const requestAction = req.action();
|
|
276
358
|
|
|
277
|
-
const trackEvents = [];
|
|
278
|
-
|
|
279
359
|
const langsExtension = hasExtendedEvents
|
|
280
360
|
? { lang }
|
|
281
361
|
: { cd1: lang };
|
|
282
362
|
|
|
363
|
+
const withUser = user !== null && !!user.id;
|
|
364
|
+
|
|
283
365
|
const actionMeta = {
|
|
284
366
|
requestAction: req.action() || noneAction,
|
|
285
367
|
expected,
|
|
@@ -292,13 +374,9 @@ function onInteractionHandler (
|
|
|
292
374
|
isText,
|
|
293
375
|
isPostback,
|
|
294
376
|
didHandover,
|
|
295
|
-
withUser
|
|
296
|
-
sessionStart,
|
|
297
|
-
sessionDuration: sessionTs - sessionStart,
|
|
377
|
+
withUser,
|
|
298
378
|
feedback,
|
|
299
|
-
skill:
|
|
300
|
-
snapshot,
|
|
301
|
-
botId,
|
|
379
|
+
skill: useSkill,
|
|
302
380
|
winnerAction,
|
|
303
381
|
winnerIntent,
|
|
304
382
|
winnerEntities: asArray(winnerEntities.map((e) => e.entity)),
|
|
@@ -311,16 +389,24 @@ function onInteractionHandler (
|
|
|
311
389
|
allActions
|
|
312
390
|
};
|
|
313
391
|
|
|
392
|
+
const notHandled = actions.some((a) => a.match(/\*$/)) && !req.isQuickReply();
|
|
393
|
+
const value = notHandled ? 1 : 0;
|
|
394
|
+
|
|
314
395
|
trackEvents.push({
|
|
315
396
|
type: TrackingType.PAGE_VIEW,
|
|
397
|
+
category: asCategory(TrackingCategory.PAGE_VIEW_FIRST),
|
|
316
398
|
action,
|
|
399
|
+
label: (isText || isQuickReply ? text : null),
|
|
400
|
+
value,
|
|
317
401
|
allActions,
|
|
318
402
|
nonInteractive,
|
|
319
403
|
lastAction,
|
|
404
|
+
// @ts-ignore
|
|
320
405
|
prevAction: lastAction,
|
|
321
|
-
skill,
|
|
322
|
-
|
|
323
|
-
|
|
406
|
+
skill: useSkill,
|
|
407
|
+
isGoto: false,
|
|
408
|
+
withUser,
|
|
409
|
+
...langsExtension,
|
|
324
410
|
...(hasExtendedEvents ? {} : actionMeta)
|
|
325
411
|
});
|
|
326
412
|
|
|
@@ -330,12 +416,14 @@ function onInteractionHandler (
|
|
|
330
416
|
...otherActions.map((a) => {
|
|
331
417
|
const r = {
|
|
332
418
|
type: TrackingType.PAGE_VIEW,
|
|
419
|
+
category: asCategory(TrackingCategory.PAGE_VIEW_SUBSEQUENT),
|
|
333
420
|
action: a,
|
|
421
|
+
value: 0,
|
|
334
422
|
allActions,
|
|
335
423
|
nonInteractive: false,
|
|
336
424
|
lastAction,
|
|
337
425
|
prevAction,
|
|
338
|
-
skill,
|
|
426
|
+
skill: useSkill,
|
|
339
427
|
isGoto: true,
|
|
340
428
|
...langsExtension
|
|
341
429
|
};
|
|
@@ -347,14 +435,14 @@ function onInteractionHandler (
|
|
|
347
435
|
|
|
348
436
|
trackEvents.push(
|
|
349
437
|
...events.map(({
|
|
350
|
-
type, category, action: eventAction, label, value
|
|
438
|
+
type, category, action: eventAction, label, value: eVal
|
|
351
439
|
}) => ({
|
|
352
440
|
lastAction,
|
|
353
441
|
type,
|
|
354
|
-
category,
|
|
442
|
+
category: asCategory(category),
|
|
355
443
|
action: eventAction,
|
|
356
444
|
label,
|
|
357
|
-
value,
|
|
445
|
+
value: eVal,
|
|
358
446
|
...langsExtension
|
|
359
447
|
}))
|
|
360
448
|
);
|
|
@@ -375,11 +463,8 @@ function onInteractionHandler (
|
|
|
375
463
|
});
|
|
376
464
|
}
|
|
377
465
|
|
|
378
|
-
const notHandled = actions.some((a) => a.match(/\*$/)) && !req.isQuickReply();
|
|
379
|
-
|
|
380
466
|
let actionCategory;
|
|
381
467
|
let label = noneAction;
|
|
382
|
-
const value = notHandled ? 1 : 0;
|
|
383
468
|
|
|
384
469
|
if (isPassThread) {
|
|
385
470
|
actionCategory = TrackingCategory.HANDOVER_TO_BOT;
|
|
@@ -408,7 +493,7 @@ function onInteractionHandler (
|
|
|
408
493
|
actionCategory = TrackingCategory.REFERRAL;
|
|
409
494
|
} else if (isPostback) {
|
|
410
495
|
actionCategory = TrackingCategory.POSTBACK_BUTTON;
|
|
411
|
-
label = req.
|
|
496
|
+
label = req.event.postback.title || (useExtendedScalars ? null : '(unknown)');
|
|
412
497
|
} else {
|
|
413
498
|
actionCategory = TrackingCategory.OTHER;
|
|
414
499
|
}
|
|
@@ -416,7 +501,6 @@ function onInteractionHandler (
|
|
|
416
501
|
trackEvents.push({
|
|
417
502
|
...(analyticsStorage.hasExtendedEvents ? actionMeta : {}),
|
|
418
503
|
type: TrackingType.CONVERSATION_EVENT,
|
|
419
|
-
// @ts-ignore
|
|
420
504
|
lastAction,
|
|
421
505
|
category: asCategory(actionCategory),
|
|
422
506
|
action,
|
|
@@ -426,18 +510,21 @@ function onInteractionHandler (
|
|
|
426
510
|
});
|
|
427
511
|
}
|
|
428
512
|
|
|
429
|
-
await
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
513
|
+
await Promise.all([
|
|
514
|
+
analyticsStorage.storeEvents(
|
|
515
|
+
pageId,
|
|
516
|
+
senderId,
|
|
517
|
+
sessionId,
|
|
518
|
+
// @ts-ignore
|
|
519
|
+
trackEvents,
|
|
520
|
+
user,
|
|
521
|
+
timestamp,
|
|
522
|
+
nonInteractive,
|
|
523
|
+
createSession,
|
|
524
|
+
metadata
|
|
525
|
+
),
|
|
526
|
+
sessionPromise
|
|
527
|
+
]);
|
|
441
528
|
} catch (e) {
|
|
442
529
|
if (throwException) {
|
|
443
530
|
throw e;
|