@onereach/step-voice 4.0.29 → 4.0.30
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/dst/Cancel.d.ts +0 -1
- package/dst/Cancel.js +25 -6
- package/dst/Choice.js +4 -4
- package/dst/Conference Dial.js +1 -1
- package/dst/Global Command.d.ts +1 -2
- package/dst/Global Command.js +27 -40
- package/dst/Hangup.d.ts +1 -0
- package/dst/Hangup.js +6 -3
- package/dst/Initiate Call.d.ts +1 -1
- package/dst/Initiate Call.js +10 -5
- package/dst/Join Conference.js +1 -1
- package/dst/Keypad Input.js +4 -4
- package/dst/Kick From Conference.js +1 -1
- package/dst/Say Message.js +5 -4
- package/dst/Transfer.js +1 -1
- package/dst/Voice Recording.js +1 -1
- package/dst/Wait For Call.d.ts +0 -1
- package/dst/Wait For Call.js +11 -5
- package/dst/step.d.ts +11 -6
- package/dst/step.js +104 -78
- package/dst/voice.d.ts +2 -2
- package/dst/voice.js +7 -4
- package/package.json +6 -6
package/dst/Cancel.d.ts
CHANGED
package/dst/Cancel.js
CHANGED
|
@@ -3,14 +3,33 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const voice_1 = tslib_1.__importDefault(require("./voice"));
|
|
5
5
|
class VoiceCancel extends voice_1.default {
|
|
6
|
-
get useQueue() {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
6
|
async runStep() {
|
|
7
|
+
const conv = await this.getConversation();
|
|
8
|
+
if (conv.lcl.length <= 1) {
|
|
9
|
+
this.log.debug('nothing to cancel');
|
|
10
|
+
this.exitStep('next');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
10
13
|
const channel = await this.fetchData();
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
this.triggers.once(`in/voice/${channel.id}/event`, async (event) => {
|
|
15
|
+
switch (event.params.type) {
|
|
16
|
+
case 'hangup':
|
|
17
|
+
await this.handleHangup(channel);
|
|
18
|
+
return await this.waitConvEnd();
|
|
19
|
+
case 'error':
|
|
20
|
+
return this.throwError(event.params.error);
|
|
21
|
+
case 'cancel': {
|
|
22
|
+
await this.popConvStep(); // pop current command (cancel)
|
|
23
|
+
await this.cancel(); // cancel previous command
|
|
24
|
+
return this.exitStep('next');
|
|
25
|
+
}
|
|
26
|
+
default:
|
|
27
|
+
return this.exitFlow();
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
this.triggers.otherwise(async () => {
|
|
31
|
+
await this.sendCommands(channel, [{ name: 'cancel' }]);
|
|
32
|
+
});
|
|
14
33
|
}
|
|
15
34
|
}
|
|
16
35
|
exports.default = VoiceCancel;
|
package/dst/Choice.js
CHANGED
|
@@ -230,11 +230,11 @@ class Choice extends voice_1.default {
|
|
|
230
230
|
}
|
|
231
231
|
case 'hangup': {
|
|
232
232
|
await this.handleHangup(channel);
|
|
233
|
-
return this.
|
|
234
|
-
}
|
|
235
|
-
case 'cancel': {
|
|
236
|
-
return this.exitStep('cancel');
|
|
233
|
+
return await this.waitConvEnd();
|
|
237
234
|
}
|
|
235
|
+
// case 'cancel': {
|
|
236
|
+
// return this.data.handleCancel === true && this.exitStep('cancel')
|
|
237
|
+
// }
|
|
238
238
|
case 'error':
|
|
239
239
|
return this.throwError(event.params.error);
|
|
240
240
|
default:
|
package/dst/Conference Dial.js
CHANGED
|
@@ -11,7 +11,7 @@ class ConferenceDial extends voice_1.default {
|
|
|
11
11
|
switch (event.params.type) {
|
|
12
12
|
case 'hangup':
|
|
13
13
|
await this.handleHangup(channel);
|
|
14
|
-
return this.
|
|
14
|
+
return await this.waitConvEnd();
|
|
15
15
|
case 'conference-start':
|
|
16
16
|
if (this.data.stayInConference) {
|
|
17
17
|
return this.exitFlow();
|
package/dst/Global Command.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ITypedEvent } from '@onereach/flow-sdk/dst/types';
|
|
|
2
2
|
import VoiceStep, { IVoiceChannel, TODO, VoiceEvent } from './voice';
|
|
3
3
|
interface INPUT {
|
|
4
4
|
asr: TODO;
|
|
5
|
-
processHangUp: 'user' | 'bot' | 'both' | 'none';
|
|
5
|
+
processHangUp: 'user' | 'bot' | 'both' | 'none' | string;
|
|
6
6
|
recordAfterTransfer: boolean;
|
|
7
7
|
recordCall: boolean;
|
|
8
8
|
choices: TODO[];
|
|
@@ -27,7 +27,6 @@ interface EVENT extends VoiceEvent {
|
|
|
27
27
|
}
|
|
28
28
|
export default class GlobalCommand extends VoiceStep<Partial<INPUT>, OUTPUT, EVENT> {
|
|
29
29
|
get isGlobal(): boolean;
|
|
30
|
-
get autoCancel(): boolean | undefined;
|
|
31
30
|
runStep(): Promise<void>;
|
|
32
31
|
initThread(): Promise<void>;
|
|
33
32
|
globThread(): Promise<void>;
|
package/dst/Global Command.js
CHANGED
|
@@ -9,16 +9,10 @@ class GlobalCommand extends voice_1.default {
|
|
|
9
9
|
get isGlobal() {
|
|
10
10
|
return true;
|
|
11
11
|
}
|
|
12
|
-
get autoCancel() {
|
|
13
|
-
return undefined;
|
|
14
|
-
}
|
|
15
12
|
async runStep() {
|
|
16
13
|
this._clearCache();
|
|
17
14
|
await this.process.runThread({
|
|
18
15
|
id: `G:${this.dataThreadId}`,
|
|
19
|
-
local: {
|
|
20
|
-
background: true
|
|
21
|
-
},
|
|
22
16
|
state: {
|
|
23
17
|
name: 'initThread',
|
|
24
18
|
step: this.step.id,
|
|
@@ -30,10 +24,6 @@ class GlobalCommand extends voice_1.default {
|
|
|
30
24
|
}
|
|
31
25
|
async initThread() {
|
|
32
26
|
const channel = await this.fetchData();
|
|
33
|
-
// if (recordCall || _.includes(['bot', 'both'], processHangUp)) {
|
|
34
|
-
// // prevent delete of session by "End" step
|
|
35
|
-
// this.session.set('keepAlive', true);
|
|
36
|
-
// }
|
|
37
27
|
const choices = this.buildChoices({ choices: this.data.choices });
|
|
38
28
|
const grammar = await this.buildGrammar(channel, choices);
|
|
39
29
|
// set grammar into voice conversation
|
|
@@ -65,30 +55,29 @@ class GlobalCommand extends voice_1.default {
|
|
|
65
55
|
}
|
|
66
56
|
async globThread() {
|
|
67
57
|
const channel = await this.fetchData();
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
58
|
+
const findExit = (exitId) => {
|
|
59
|
+
return lodash_1.default.find(this.step.exits, (exit) => exitId === exit.stepId);
|
|
60
|
+
};
|
|
61
|
+
// if (channel.autoHangup) {
|
|
62
|
+
// this.triggers.local('thread/end/main', async () => {
|
|
63
|
+
// delete this.thread.waits['thread/end/main']
|
|
64
|
+
// const channel = await this.fetchData()
|
|
65
|
+
// if (!channel.hangup) {
|
|
66
|
+
// channel.autoHangup = false
|
|
67
|
+
// await this.updateData()
|
|
68
|
+
// this.local.background = undefined
|
|
69
|
+
// await this.sendCommands(channel, [{ name: 'hangup' }])
|
|
70
|
+
// void this.process.main.enqueueAndRun({ name: 'ending' })
|
|
71
|
+
// this.exitFlow()
|
|
72
|
+
// }
|
|
73
|
+
// })
|
|
74
|
+
// }
|
|
86
75
|
this.triggers.once(`in/voice/${channel.id}/event`, async (event) => {
|
|
87
76
|
event.processed = undefined;
|
|
88
77
|
switch (event.params.type) {
|
|
89
78
|
case 'hangup': {
|
|
90
79
|
await this.hangup(channel);
|
|
91
|
-
await this.
|
|
80
|
+
await this.notifyConvEnd();
|
|
92
81
|
return this.end();
|
|
93
82
|
}
|
|
94
83
|
case 'avm-detected':
|
|
@@ -98,7 +87,7 @@ class GlobalCommand extends voice_1.default {
|
|
|
98
87
|
case 'digits': {
|
|
99
88
|
const params = event.params;
|
|
100
89
|
const exitId = params.exitId ?? '';
|
|
101
|
-
if (
|
|
90
|
+
if (findExit(exitId)) {
|
|
102
91
|
await this.transcript(channel, {
|
|
103
92
|
previousTranscriptId: channel.lastTranscriptId,
|
|
104
93
|
keyPress: params.digit,
|
|
@@ -114,7 +103,7 @@ class GlobalCommand extends voice_1.default {
|
|
|
114
103
|
case 'recognition': {
|
|
115
104
|
const params = event.params;
|
|
116
105
|
const exitId = params.exitId ?? '';
|
|
117
|
-
if (
|
|
106
|
+
if (findExit(exitId)) {
|
|
118
107
|
const voiceProcessResult = lodash_1.default.chain(params.phrases)
|
|
119
108
|
.map((p) => p.lexical)
|
|
120
109
|
.join(' | ')
|
|
@@ -140,10 +129,6 @@ class GlobalCommand extends voice_1.default {
|
|
|
140
129
|
}
|
|
141
130
|
async hangup(channel) {
|
|
142
131
|
await this.handleHangup(channel);
|
|
143
|
-
// if (channel.recordCall || _.includes(['bot', 'both'], processHangUp)) {
|
|
144
|
-
// // turn off protection of session deletion by "End" step
|
|
145
|
-
// this.session.unset('keepAlive');
|
|
146
|
-
// }
|
|
147
132
|
const isHangedUpByBot = channel.sessionEndedBy === 'Bot';
|
|
148
133
|
const hangUpType = isHangedUpByBot ? 'bot hang up' : 'user hang up';
|
|
149
134
|
// process call recording in hangup event
|
|
@@ -163,7 +148,7 @@ class GlobalCommand extends voice_1.default {
|
|
|
163
148
|
return await this.exitThread(this.event, hangUpType, 'hang up');
|
|
164
149
|
case 'none':
|
|
165
150
|
default:
|
|
166
|
-
return this.
|
|
151
|
+
return this.end();
|
|
167
152
|
}
|
|
168
153
|
}
|
|
169
154
|
async exitThread(event, type, stepExit) {
|
|
@@ -195,16 +180,18 @@ class GlobalCommand extends voice_1.default {
|
|
|
195
180
|
// params: {}
|
|
196
181
|
// }])
|
|
197
182
|
// channel.global = null;
|
|
198
|
-
await this.updateData()
|
|
183
|
+
// await this.updateData()
|
|
184
|
+
const exitLabel = this.getExitStepLabel(stepExit) ?? stepExit;
|
|
199
185
|
await this.process.runThread({
|
|
200
|
-
id: `${
|
|
186
|
+
id: `${exitLabel}_${(0, nanoid_1.nanoid)(8)}`,
|
|
201
187
|
state: {
|
|
202
188
|
name: 'exitToThread',
|
|
189
|
+
direct: true,
|
|
203
190
|
result: {
|
|
204
191
|
conversation: this.conversation,
|
|
205
192
|
conversationThreadId: this.dataThreadId
|
|
206
193
|
},
|
|
207
|
-
exitStep:
|
|
194
|
+
exitStep: stepExit,
|
|
208
195
|
step: this.currentStepId
|
|
209
196
|
}
|
|
210
197
|
});
|
|
@@ -213,7 +200,7 @@ class GlobalCommand extends voice_1.default {
|
|
|
213
200
|
// this.gotoState(this.state, { name: 'exiting' })
|
|
214
201
|
}
|
|
215
202
|
exitToThread() {
|
|
216
|
-
this.thread.
|
|
203
|
+
this.thread.exitStep(this.state.exitStep, this.state.result);
|
|
217
204
|
}
|
|
218
205
|
async buildGrammar(channel, choices) {
|
|
219
206
|
const { asr } = this.data;
|
package/dst/Hangup.d.ts
CHANGED
package/dst/Hangup.js
CHANGED
|
@@ -12,9 +12,9 @@ class Hangup extends voice_1.default {
|
|
|
12
12
|
return this.exitStep('next');
|
|
13
13
|
case 'error':
|
|
14
14
|
return this.throwError(event.params.error);
|
|
15
|
-
case 'cancel': {
|
|
16
|
-
|
|
17
|
-
}
|
|
15
|
+
// case 'cancel': {
|
|
16
|
+
// return this.data.handleCancel === true && this.exitStep('cancel')
|
|
17
|
+
// }
|
|
18
18
|
default:
|
|
19
19
|
return this.exitFlow();
|
|
20
20
|
}
|
|
@@ -32,5 +32,8 @@ class Hangup extends voice_1.default {
|
|
|
32
32
|
return this.exitFlow();
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
+
async onConvEnd() {
|
|
36
|
+
this.exitStep('next');
|
|
37
|
+
}
|
|
35
38
|
}
|
|
36
39
|
exports.default = Hangup;
|
package/dst/Initiate Call.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import VoiceStep, { CallStartEvent, TODO } from './voice';
|
|
|
2
2
|
interface INPUT {
|
|
3
3
|
channelId?: string;
|
|
4
4
|
sessionTimeout?: number | string;
|
|
5
|
+
autoHangup?: boolean;
|
|
5
6
|
asr: TODO;
|
|
6
7
|
tts: TODO;
|
|
7
8
|
from: string;
|
|
@@ -20,7 +21,6 @@ interface INPUT {
|
|
|
20
21
|
}
|
|
21
22
|
export default class InitiateCall extends VoiceStep<INPUT, TODO, CallStartEvent> {
|
|
22
23
|
get conversation(): string | import("@onereach/flow-sdk/dst/types").IMergeField;
|
|
23
|
-
get autoCancel(): undefined;
|
|
24
24
|
runStep(): Promise<void>;
|
|
25
25
|
waitForCall(): Promise<void>;
|
|
26
26
|
}
|
package/dst/Initiate Call.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable
|
|
2
|
+
/* eslint-disable
|
|
3
|
+
@typescript-eslint/strict-boolean-expressions,
|
|
4
|
+
@typescript-eslint/explicit-function-return-type,
|
|
5
|
+
@typescript-eslint/no-misused-promises
|
|
6
|
+
*/
|
|
3
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
8
|
const tslib_1 = require("tslib");
|
|
5
9
|
const voice_1 = tslib_1.__importDefault(require("./voice"));
|
|
@@ -13,9 +17,6 @@ class InitiateCall extends voice_1.default {
|
|
|
13
17
|
throw new Error('missing conversation');
|
|
14
18
|
return this.step.dataOut;
|
|
15
19
|
}
|
|
16
|
-
get autoCancel() {
|
|
17
|
-
return undefined;
|
|
18
|
-
}
|
|
19
20
|
async runStep() {
|
|
20
21
|
const { channelId = uuid.v4() } = this.data;
|
|
21
22
|
if (!this.session.key) {
|
|
@@ -35,7 +36,7 @@ class InitiateCall extends voice_1.default {
|
|
|
35
36
|
this.gotoState('waitForCall');
|
|
36
37
|
}
|
|
37
38
|
async waitForCall() {
|
|
38
|
-
const { asr, tts, from: botNumber, endUserNumber, sipHost, sipUser, sipPassword, timeout, headers, enableSpoofCallerId, spoofCallerId, isAMD } = this.data;
|
|
39
|
+
const { autoHangup, asr, tts, from: botNumber, endUserNumber, sipHost, sipUser, sipPassword, timeout, headers, enableSpoofCallerId, spoofCallerId, isAMD } = this.data;
|
|
39
40
|
const { id: channelId } = await this.fetchData();
|
|
40
41
|
this.triggers.once(`in/voice/${channelId}/event`, async (event) => {
|
|
41
42
|
switch (event.params.type) {
|
|
@@ -56,6 +57,7 @@ class InitiateCall extends voice_1.default {
|
|
|
56
57
|
const channel = {
|
|
57
58
|
headers: event.params.headers,
|
|
58
59
|
...event.params.channel,
|
|
60
|
+
autoHangup,
|
|
59
61
|
asr: asr.getSettings(),
|
|
60
62
|
tts: tts.getVoice(),
|
|
61
63
|
botNumber: event.params.channel.to ?? 'unknown',
|
|
@@ -89,6 +91,9 @@ class InitiateCall extends voice_1.default {
|
|
|
89
91
|
}]
|
|
90
92
|
: []
|
|
91
93
|
]);
|
|
94
|
+
if (this.data.autoHangup) {
|
|
95
|
+
this.once('ending', this.autoHangup);
|
|
96
|
+
}
|
|
92
97
|
return this.exitStep('success');
|
|
93
98
|
}
|
|
94
99
|
case 'error': {
|
package/dst/Join Conference.js
CHANGED
|
@@ -11,7 +11,7 @@ class JoinConference extends voice_1.default {
|
|
|
11
11
|
switch (event.params.type) {
|
|
12
12
|
case 'hangup':
|
|
13
13
|
await this.handleHangup(channel);
|
|
14
|
-
return this.
|
|
14
|
+
return await this.waitConvEnd();
|
|
15
15
|
case 'conference-start':
|
|
16
16
|
await this.transcript(channel, {
|
|
17
17
|
conferenceId: conferenceName,
|
package/dst/Keypad Input.js
CHANGED
|
@@ -152,11 +152,11 @@ class KeypadInput extends voice_1.default {
|
|
|
152
152
|
}
|
|
153
153
|
case 'hangup': {
|
|
154
154
|
await this.handleHangup(channel);
|
|
155
|
-
return this.
|
|
156
|
-
}
|
|
157
|
-
case 'cancel': {
|
|
158
|
-
return this.exitStep('cancel');
|
|
155
|
+
return await this.waitConvEnd();
|
|
159
156
|
}
|
|
157
|
+
// case 'cancel': {
|
|
158
|
+
// return this.data.handleCancel === true && this.exitStep('cancel')
|
|
159
|
+
// }
|
|
160
160
|
case 'error':
|
|
161
161
|
return this.throwError(event.params.error);
|
|
162
162
|
default:
|
|
@@ -11,7 +11,7 @@ class KickFromConference extends voice_1.default {
|
|
|
11
11
|
switch (event.params.type) {
|
|
12
12
|
case 'hangup':
|
|
13
13
|
await this.handleHangup(channel);
|
|
14
|
-
return this.
|
|
14
|
+
return await this.waitConvEnd();
|
|
15
15
|
case 'conference-end':
|
|
16
16
|
await this.transcript(channel, {
|
|
17
17
|
conferenceId: room,
|
package/dst/Say Message.js
CHANGED
|
@@ -21,14 +21,15 @@ class SayMessage extends voice_1.default {
|
|
|
21
21
|
switch (event.params.type) {
|
|
22
22
|
case 'hangup':
|
|
23
23
|
await this.handleHangup(channel);
|
|
24
|
-
return this.
|
|
24
|
+
return await this.waitConvEnd();
|
|
25
25
|
case 'playback':
|
|
26
26
|
return this.exitStep('next');
|
|
27
27
|
case 'error':
|
|
28
28
|
return this.throwError(event.params.error);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
//
|
|
30
|
+
// case 'cancel': {
|
|
31
|
+
// return this.data.handleCancel === true && this.exitStep('cancel')
|
|
32
|
+
// }
|
|
32
33
|
default:
|
|
33
34
|
return this.exitFlow();
|
|
34
35
|
}
|
package/dst/Transfer.js
CHANGED
package/dst/Voice Recording.js
CHANGED
|
@@ -39,7 +39,7 @@ class Recording extends voice_1.default {
|
|
|
39
39
|
// TODO do we need zombie?
|
|
40
40
|
this.state.zombie = true;
|
|
41
41
|
await this.handleHangup(channel);
|
|
42
|
-
return this.
|
|
42
|
+
return await this.waitConvEnd();
|
|
43
43
|
case 'record':
|
|
44
44
|
if (!lodash_1.default.isEmpty(url)) {
|
|
45
45
|
await this.transcript(channel, {
|
package/dst/Wait For Call.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import VoiceStep, { CallStartEvent, TODO } from './voice';
|
|
|
2
2
|
import { ITypedEvent } from '@onereach/flow-sdk/dst/types';
|
|
3
3
|
export default class WaitForCall extends VoiceStep<TODO, TODO, TODO> {
|
|
4
4
|
get conversation(): string | import("@onereach/flow-sdk/dst/types").IMergeField;
|
|
5
|
-
get autoCancel(): boolean;
|
|
6
5
|
runStep(): Promise<void>;
|
|
7
6
|
onCall(event: ITypedEvent<CallStartEvent>): Promise<unknown>;
|
|
8
7
|
}
|
package/dst/Wait For Call.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable
|
|
2
|
+
/* eslint-disable
|
|
3
|
+
@typescript-eslint/strict-boolean-expressions,
|
|
4
|
+
@typescript-eslint/explicit-function-return-type,
|
|
5
|
+
@typescript-eslint/no-misused-promises
|
|
6
|
+
*/
|
|
3
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
8
|
const tslib_1 = require("tslib");
|
|
5
9
|
const voice_1 = tslib_1.__importDefault(require("./voice"));
|
|
@@ -11,14 +15,16 @@ class WaitForCall extends voice_1.default {
|
|
|
11
15
|
throw new Error('missing conversation');
|
|
12
16
|
return this.step.dataOut;
|
|
13
17
|
}
|
|
14
|
-
get autoCancel() {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
18
|
async runStep() {
|
|
18
19
|
const selectedNumbers = this.data.selectedNumbers;
|
|
19
20
|
lodash_1.default.forEach(selectedNumbers, number => {
|
|
20
|
-
this.triggers.on(`in/voice/${number.value}/call`,
|
|
21
|
+
this.triggers.on(`in/voice/${number.value}/call`, this.onCall);
|
|
21
22
|
});
|
|
23
|
+
if (this.data.autoHangup) {
|
|
24
|
+
this.triggers.otherwise(() => {
|
|
25
|
+
this.once('ending', this.autoHangup);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
22
28
|
}
|
|
23
29
|
async onCall(event) {
|
|
24
30
|
const { autoHangup, asr, tts, endOfInputTimeout } = this.data;
|
package/dst/step.d.ts
CHANGED
|
@@ -10,10 +10,10 @@ export default class ConvStep<TData = unknown, TIn = unknown, TOut = unknown, TP
|
|
|
10
10
|
get conversation(): IMergeFieldKey | IMergeField;
|
|
11
11
|
/** id of the thread where conversation data is stored */
|
|
12
12
|
get dataThreadId(): IThreadId;
|
|
13
|
-
get autoCancel(): boolean | undefined;
|
|
14
13
|
get isGlobal(): boolean;
|
|
15
14
|
get useQueue(): boolean;
|
|
16
15
|
fetchData(): Promise<TData & IConversationData>;
|
|
16
|
+
getConversation(): Promise<IConversation>;
|
|
17
17
|
updateData(): Promise<void>;
|
|
18
18
|
hasConversation(): Promise<boolean>;
|
|
19
19
|
runBefore(): Promise<void>;
|
|
@@ -24,7 +24,14 @@ export default class ConvStep<TData = unknown, TIn = unknown, TOut = unknown, TP
|
|
|
24
24
|
onSkipEvent(): Promise<void>;
|
|
25
25
|
cancel(): Promise<void>;
|
|
26
26
|
onCancel(): Promise<void>;
|
|
27
|
-
|
|
27
|
+
onSleep(): Promise<void>;
|
|
28
|
+
onAwake(): Promise<void>;
|
|
29
|
+
onPause(): Promise<void>;
|
|
30
|
+
onResume(): Promise<void>;
|
|
31
|
+
notifyConvEnd(): Promise<void>;
|
|
32
|
+
waitConvEnd(): Promise<void>;
|
|
33
|
+
waitGlobEnd(): Promise<void>;
|
|
34
|
+
onConvEnd(): Promise<void>;
|
|
28
35
|
pause(): Promise<void>;
|
|
29
36
|
resume(): Promise<void>;
|
|
30
37
|
sendEventToStep({ toGlobal, toStep, action, event }: {
|
|
@@ -37,13 +44,11 @@ export default class ConvStep<TData = unknown, TIn = unknown, TOut = unknown, TP
|
|
|
37
44
|
/** @returns true if current conv is active */
|
|
38
45
|
pushConvStep(): Promise<boolean>;
|
|
39
46
|
/** @returns true if current conv was active */
|
|
40
|
-
popConvStep(): Promise<boolean>;
|
|
41
|
-
startConversation(data: TData, {
|
|
42
|
-
autoCancel?: boolean;
|
|
47
|
+
popConvStep(popStep?: IConversationStep): Promise<boolean>;
|
|
48
|
+
startConversation(data: TData, { events }: {
|
|
43
49
|
events: Record<string, {}>;
|
|
44
50
|
thread?: IThreadId;
|
|
45
51
|
}): Promise<void>;
|
|
46
52
|
_fetchData(): Promise<(TData & IConversationData) | undefined>;
|
|
47
|
-
_getConversation(): Promise<IConversation>;
|
|
48
53
|
_clearCache(): void;
|
|
49
54
|
}
|
package/dst/step.js
CHANGED
|
@@ -15,9 +15,6 @@ class ConvStep extends step_1.default {
|
|
|
15
15
|
const dataThreadId = this.state.thread ?? this.data.conversationThread;
|
|
16
16
|
return dataThreadId || this.thread.id;
|
|
17
17
|
}
|
|
18
|
-
get autoCancel() {
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
18
|
get isGlobal() {
|
|
22
19
|
return false;
|
|
23
20
|
}
|
|
@@ -30,6 +27,9 @@ class ConvStep extends step_1.default {
|
|
|
30
27
|
throw new Error(`missing conversation data in state ${this.state.name}`);
|
|
31
28
|
return data;
|
|
32
29
|
}
|
|
30
|
+
async getConversation() {
|
|
31
|
+
return (await this.fetchData())._conv;
|
|
32
|
+
}
|
|
33
33
|
async updateData() {
|
|
34
34
|
if (this.convDataCache == null)
|
|
35
35
|
throw new Error(`missing conversation cache in state ${this.state.name}`);
|
|
@@ -42,6 +42,8 @@ class ConvStep extends step_1.default {
|
|
|
42
42
|
}
|
|
43
43
|
async runBefore() {
|
|
44
44
|
await super.runBefore();
|
|
45
|
+
if (this.state.ending)
|
|
46
|
+
return;
|
|
45
47
|
// ensure cache is reset between step runs, just in case
|
|
46
48
|
this._clearCache();
|
|
47
49
|
this.triggers.local('_conv');
|
|
@@ -50,14 +52,15 @@ class ConvStep extends step_1.default {
|
|
|
50
52
|
this.log.debug('conv.runBefore', { state: this.state, conv: this.convDataCache?._conv });
|
|
51
53
|
if (this.state.direct)
|
|
52
54
|
return;
|
|
53
|
-
if (this.event.action === '
|
|
54
|
-
this.
|
|
55
|
+
if (!this.event.processed && this.event.action && typeof this[this.event.action] === 'function') {
|
|
56
|
+
this.event.processed = true;
|
|
57
|
+
this.state.name = this.event.action;
|
|
55
58
|
return;
|
|
56
59
|
}
|
|
57
60
|
if (this.useQueue && !await this.pushConvStep()) {
|
|
58
61
|
return await this.waitForConversation();
|
|
59
62
|
}
|
|
60
|
-
if (this.event.action == null && this.event.processed
|
|
63
|
+
if (this.event.action == null && !this.event.processed && this.convDataCache?._conv?.trg?.[this.event.name] != null) {
|
|
61
64
|
if (this.isGlobal)
|
|
62
65
|
return;
|
|
63
66
|
const hasGlobal = await this.sendEventToStep({ event: { ...this.event, action: 'global' }, toGlobal: true }); // redirect to global (1)
|
|
@@ -77,9 +80,10 @@ class ConvStep extends step_1.default {
|
|
|
77
80
|
if (!await this.hasConversation())
|
|
78
81
|
return await super.runAfter();
|
|
79
82
|
if (this.thread.hasControlAction()) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
+
await this.popConvStep();
|
|
84
|
+
// if (await this.popConvStep()) {
|
|
85
|
+
// await this.sendEventToStep({ toGlobal: this.isGlobal, action: 'onAwake' })
|
|
86
|
+
// }
|
|
83
87
|
}
|
|
84
88
|
if (this.isGlobal && !event_1.default.isProcessed(this.event)) {
|
|
85
89
|
await this.sendEventToStep({ toGlobal: false, event: { ...this.event, processed: undefined, action: 'local' } });
|
|
@@ -87,7 +91,7 @@ class ConvStep extends step_1.default {
|
|
|
87
91
|
await super.runAfter();
|
|
88
92
|
}
|
|
89
93
|
async hasActiveGlobal() {
|
|
90
|
-
const globalLength = (await this.
|
|
94
|
+
const globalLength = (await this.getConversation())?.glb?.length ?? 0;
|
|
91
95
|
return globalLength > 0;
|
|
92
96
|
}
|
|
93
97
|
async setLocalTriggers() {
|
|
@@ -119,59 +123,88 @@ class ConvStep extends step_1.default {
|
|
|
119
123
|
this.log.debug('conv.cannot cancel global');
|
|
120
124
|
return;
|
|
121
125
|
}
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
if (activeStep != null) {
|
|
125
|
-
this.log.debug('conv.cancel', activeStep);
|
|
126
|
-
conv.lcl.splice(0);
|
|
127
|
-
await this.updateData();
|
|
128
|
-
await this.sendEventToStep({ toGlobal: false, action: 'cancel', toStep: activeStep });
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
this.log.debug('conv.nothing to cancel');
|
|
132
|
-
}
|
|
126
|
+
const activeStep = await this.activeStep();
|
|
127
|
+
await this.sendEventToStep({ event: { name: '_conv', action: 'onCancel', params: { byStep: this.step.label } }, toStep: activeStep });
|
|
133
128
|
}
|
|
134
129
|
async onCancel() {
|
|
130
|
+
await this.popConvStep();
|
|
135
131
|
if (this.getExitStepId('cancel')) {
|
|
136
132
|
this.log.debug('conv.cancel exit');
|
|
137
133
|
this.exitStep('cancel');
|
|
138
134
|
}
|
|
139
135
|
else {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
136
|
+
return await this.waitConvEnd();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
async onSleep() {
|
|
140
|
+
// sleep
|
|
141
|
+
}
|
|
142
|
+
async onAwake() {
|
|
143
|
+
// wakeup
|
|
144
|
+
}
|
|
145
|
+
async onPause() {
|
|
146
|
+
// return await this.waitConvEnd()
|
|
147
|
+
}
|
|
148
|
+
async onResume() {
|
|
149
|
+
// resume
|
|
150
|
+
}
|
|
151
|
+
async notifyConvEnd() {
|
|
152
|
+
await this.popConvStep();
|
|
153
|
+
const conv = await this.getConversation();
|
|
154
|
+
const lcl = conv.lcl.splice(0);
|
|
155
|
+
const glb = conv.glb.splice(0);
|
|
156
|
+
if (lcl.length > 0 || glb.length > 0) {
|
|
157
|
+
await this.updateData();
|
|
158
|
+
for (const step of lcl) {
|
|
159
|
+
await this.sendEventToStep({ toStep: step, action: 'onConvEnd' });
|
|
144
160
|
}
|
|
145
|
-
|
|
146
|
-
this.
|
|
147
|
-
this.end();
|
|
161
|
+
for (const step of glb) {
|
|
162
|
+
await this.sendEventToStep({ toStep: step, action: 'onConvEnd' });
|
|
148
163
|
}
|
|
149
164
|
}
|
|
150
165
|
}
|
|
151
|
-
async
|
|
152
|
-
this.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const activeStep = await this.activeStep(false);
|
|
157
|
-
if (activeStep != null) {
|
|
158
|
-
this.log.debug('conv.pause', activeStep);
|
|
159
|
-
conv.stk.push(conv.lcl.splice(0)); // save que to stk
|
|
160
|
-
await this.sendEventToStep({ toGlobal: false, action: 'pause', toStep: activeStep });
|
|
166
|
+
async waitConvEnd() {
|
|
167
|
+
const conversationThread = this.state.thread ?? this.thread.id;
|
|
168
|
+
if (!this.isGlobal && conversationThread === this.thread.id && this.thread.id !== 'main') {
|
|
169
|
+
this.log.debug('conv.wait for end', this.conversation);
|
|
170
|
+
this.gotoState({ ...this.state, name: 'waitGlobEnd', direct: true });
|
|
161
171
|
}
|
|
162
172
|
else {
|
|
163
|
-
this.log.debug('conv.
|
|
173
|
+
this.log.debug('conv.end', this.conversation);
|
|
174
|
+
await this.onConvEnd();
|
|
164
175
|
}
|
|
165
176
|
}
|
|
177
|
+
async waitGlobEnd() {
|
|
178
|
+
const gcThreadId = `G:${this.thread.id}`;
|
|
179
|
+
// wait for glob thread end (if exists)
|
|
180
|
+
this.triggers.local(`thread/end/${gcThreadId}`, async () => await this.onConvEnd());
|
|
181
|
+
if (!this.process.getThread(gcThreadId))
|
|
182
|
+
await this.onConvEnd();
|
|
183
|
+
}
|
|
184
|
+
async onConvEnd() {
|
|
185
|
+
this.end();
|
|
186
|
+
}
|
|
187
|
+
async pause() {
|
|
188
|
+
// const conv = await this._getConversation()
|
|
189
|
+
// const activeStep = await this.activeStep(false)
|
|
190
|
+
// if (activeStep != null) {
|
|
191
|
+
// this.log.debug('conv.pause', activeStep)
|
|
192
|
+
// conv.stk.push(conv.lcl.splice(0)) // save que to stk
|
|
193
|
+
// await this.updateData()
|
|
194
|
+
// await this.sendEventToStep({ action: 'onPause', toStep: activeStep })
|
|
195
|
+
// } else {
|
|
196
|
+
// this.log.debug('conv.nothing to pause')
|
|
197
|
+
// }
|
|
198
|
+
}
|
|
166
199
|
async resume() {
|
|
167
|
-
const conv = await this._getConversation()
|
|
168
|
-
if (conv.stk.length > 0) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
|
|
174
|
-
}
|
|
200
|
+
// const conv = await this._getConversation()
|
|
201
|
+
// if (conv.stk.length > 0) {
|
|
202
|
+
// conv.lcl.unshift(...(conv.stk.pop() ?? [])) // restore que from stk
|
|
203
|
+
// await this.updateData()
|
|
204
|
+
// await this.sendEventToStep({ toGlobal: false, action: 'onResume' })
|
|
205
|
+
// } else {
|
|
206
|
+
// this.log.debug('conv.nothing to resume')
|
|
207
|
+
// }
|
|
175
208
|
}
|
|
176
209
|
async sendEventToStep({ toGlobal, toStep, action, event = { name: '_conv', action } }) {
|
|
177
210
|
toStep || (toStep = await this.activeStep(toGlobal));
|
|
@@ -182,63 +215,59 @@ class ConvStep extends step_1.default {
|
|
|
182
215
|
return undefined;
|
|
183
216
|
}
|
|
184
217
|
async activeStep(isGlobal = this.isGlobal) {
|
|
185
|
-
const conv = await this.
|
|
186
|
-
return isGlobal ? conv.glb[conv.glb.length - 1] : conv.lcl[
|
|
218
|
+
const conv = await this.getConversation();
|
|
219
|
+
return isGlobal ? conv.glb[conv.glb.length - 1] : conv.lcl[conv.lcl.length - 1];
|
|
187
220
|
}
|
|
188
221
|
/** @returns true if current conv is active */
|
|
189
222
|
async pushConvStep() {
|
|
190
|
-
const conv = await this.
|
|
223
|
+
const conv = await this.getConversation();
|
|
191
224
|
const sessionKey = this.session.key;
|
|
192
225
|
if (sessionKey == null)
|
|
193
226
|
throw new Error('session is required');
|
|
194
227
|
const que = this.isGlobal ? conv.glb : conv.lcl;
|
|
195
228
|
const queIndex = que.findIndex(stp => stp.key === sessionKey && this.thread.id === stp.thread);
|
|
196
229
|
if (queIndex < 0) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
que.push({ key: sessionKey, thread: this.thread.id });
|
|
230
|
+
await this.sendEventToStep({ toGlobal: false, event: { name: '_conv', action: 'onPause', params: { byStep: this.step.label } } });
|
|
231
|
+
que.push({ key: sessionKey, thread: this.thread.id, name: this.constructor.name, label: this.label, step: this.id });
|
|
200
232
|
await this.updateData();
|
|
201
|
-
return
|
|
233
|
+
return true;
|
|
202
234
|
}
|
|
203
|
-
return queIndex ===
|
|
235
|
+
return queIndex === que.length - 1;
|
|
204
236
|
}
|
|
205
237
|
/** @returns true if current conv was active */
|
|
206
|
-
async popConvStep() {
|
|
207
|
-
const conv = await this.
|
|
238
|
+
async popConvStep(popStep) {
|
|
239
|
+
const conv = await this.getConversation();
|
|
208
240
|
const sessionKey = this.session.key;
|
|
209
241
|
if (sessionKey == null)
|
|
210
242
|
throw new Error('session is required');
|
|
243
|
+
popStep || (popStep = { key: sessionKey, thread: this.thread.id });
|
|
211
244
|
const que = this.isGlobal ? conv.glb : conv.lcl;
|
|
212
|
-
const queIndex = que.findIndex(stp => stp.key ===
|
|
245
|
+
const queIndex = que.findIndex(stp => stp.key === popStep?.key && stp.thread === popStep.thread);
|
|
213
246
|
if (queIndex >= 0) {
|
|
214
247
|
// console.log('SPLICE1', this.thread.id, this.step.label, que)
|
|
215
248
|
que.splice(queIndex, 1);
|
|
216
249
|
await this.updateData();
|
|
217
|
-
return
|
|
250
|
+
return queIndex === que.length;
|
|
218
251
|
}
|
|
219
|
-
let updated = false
|
|
220
|
-
conv.stk.forEach((steps, stepsIdx) => {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
});
|
|
230
|
-
if (updated)
|
|
231
|
-
await this.updateData();
|
|
252
|
+
// let updated = false
|
|
253
|
+
// conv.stk.forEach((steps, stepsIdx) => {
|
|
254
|
+
// const stpIdx = steps.findIndex(stp => stp.key === sessionKey && this.thread.id === stp.thread)
|
|
255
|
+
// if (stpIdx >= 0) {
|
|
256
|
+
// if (steps.length > 1) steps.splice(stpIdx, 1)
|
|
257
|
+
// else conv.stk.splice(stepsIdx, 1)
|
|
258
|
+
// updated = true
|
|
259
|
+
// }
|
|
260
|
+
// })
|
|
261
|
+
// if (updated) await this.updateData()
|
|
232
262
|
return false;
|
|
233
263
|
}
|
|
234
|
-
async startConversation(data, {
|
|
264
|
+
async startConversation(data, { events }) {
|
|
235
265
|
this.convDataCache = {
|
|
236
266
|
...data,
|
|
237
267
|
_conv: {
|
|
238
|
-
acl: (autoCancel ? 1 : undefined),
|
|
239
268
|
trg: events,
|
|
240
269
|
glb: [],
|
|
241
|
-
stk: [],
|
|
270
|
+
// stk: [],
|
|
242
271
|
lcl: []
|
|
243
272
|
}
|
|
244
273
|
};
|
|
@@ -253,9 +282,6 @@ class ConvStep extends step_1.default {
|
|
|
253
282
|
// console.log('FETCH', this.conversation, this.thread.id, this.step.label, this.convDataCache?._conv.que)
|
|
254
283
|
return this.convDataCache;
|
|
255
284
|
}
|
|
256
|
-
async _getConversation() {
|
|
257
|
-
return (await this.fetchData())._conv;
|
|
258
|
-
}
|
|
259
285
|
_clearCache() {
|
|
260
286
|
this.convDataCache = undefined;
|
|
261
287
|
}
|
package/dst/voice.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import BasicError from '@onereach/flow-sdk/dst/errors/base';
|
|
|
4
4
|
export declare type TODO = any;
|
|
5
5
|
export interface IVoiceChannel {
|
|
6
6
|
id: string;
|
|
7
|
-
autoHangup
|
|
7
|
+
autoHangup?: boolean;
|
|
8
8
|
hangup: boolean;
|
|
9
9
|
endUserNumber: string;
|
|
10
10
|
botNumber: string;
|
|
@@ -34,7 +34,6 @@ export interface CallStartEvent extends VoiceEvent {
|
|
|
34
34
|
export default class VoiceStep<TIn = unknown, TOut = unknown, TParams = VoiceEvent> extends ConvStep<IVoiceChannel, TIn & {
|
|
35
35
|
handleCancel?: boolean;
|
|
36
36
|
}, TOut, TParams> {
|
|
37
|
-
get autoCancel(): boolean | undefined;
|
|
38
37
|
sendCommands({ id, type, callback }: IVoiceChannel, commands: TODO[]): Promise<unknown>;
|
|
39
38
|
extractSectionMessages(sections: IPromtpSection[]): string;
|
|
40
39
|
extractSectionFiles(sections: IPromtpSection[]): Array<{
|
|
@@ -47,6 +46,7 @@ export default class VoiceStep<TIn = unknown, TOut = unknown, TParams = VoiceEve
|
|
|
47
46
|
message: string;
|
|
48
47
|
}): never;
|
|
49
48
|
handleHangup(channel: IVoiceChannel): Promise<void>;
|
|
49
|
+
autoHangup(): Promise<void>;
|
|
50
50
|
buildSections({ sections, textType, ttsSettings, allowKeypadBargeIn }: TODO): TODO;
|
|
51
51
|
buildReprompts({ prompts, allowKeypadBargeIn }: TODO): TODO;
|
|
52
52
|
buildChoices({ choices }: TODO): TODO;
|
package/dst/voice.js
CHANGED
|
@@ -13,9 +13,6 @@ class VoiceStepError extends base_1.default {
|
|
|
13
13
|
exports.VoiceStepError = VoiceStepError;
|
|
14
14
|
class VoiceStep extends step_1.default {
|
|
15
15
|
// static Error = VoiceStepError
|
|
16
|
-
get autoCancel() {
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
16
|
async sendCommands({ id, type, callback }, commands) {
|
|
20
17
|
if (lodash_1.default.isEmpty(commands))
|
|
21
18
|
return;
|
|
@@ -24,7 +21,7 @@ class VoiceStep extends step_1.default {
|
|
|
24
21
|
name: `out/voice/${type}`,
|
|
25
22
|
params: {
|
|
26
23
|
id,
|
|
27
|
-
cancel: this.
|
|
24
|
+
cancel: this.isGlobal ? undefined : true,
|
|
28
25
|
commands
|
|
29
26
|
},
|
|
30
27
|
reporting: this.session.getSessionRef()
|
|
@@ -116,6 +113,12 @@ class VoiceStep extends step_1.default {
|
|
|
116
113
|
channel.hangup = true;
|
|
117
114
|
await this.updateData();
|
|
118
115
|
}
|
|
116
|
+
async autoHangup() {
|
|
117
|
+
const channel = await this.fetchData();
|
|
118
|
+
if (!channel.hangup) {
|
|
119
|
+
await this.sendCommands(channel, [{ name: 'hangup', reason: 'AUTO' }]);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
119
122
|
buildSections({ sections, textType, ttsSettings, allowKeypadBargeIn }) {
|
|
120
123
|
return lodash_1.default.map(sections, section => ({
|
|
121
124
|
text: section.voiceTextMsg,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onereach/step-voice",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.30",
|
|
4
4
|
"author": "Roman Zolotarov <roman.zolotarov@onereach.com>",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Roman Zolotarov",
|
|
@@ -18,19 +18,19 @@
|
|
|
18
18
|
"uuid": "^8.3.2"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@onereach/flow-sdk": "^3.1.
|
|
21
|
+
"@onereach/flow-sdk": "^3.1.50",
|
|
22
22
|
"@swc/cli": "^0.1.57",
|
|
23
|
-
"@swc/core": "^1.2.
|
|
23
|
+
"@swc/core": "^1.2.210",
|
|
24
24
|
"@swc/jest": "^0.2.21",
|
|
25
|
-
"@types/jest": "^28.1.
|
|
25
|
+
"@types/jest": "^28.1.4",
|
|
26
26
|
"@types/lodash": "^4.14.182",
|
|
27
27
|
"@types/timestring": "^6.0.2",
|
|
28
28
|
"@types/uuid": "^8.3.4",
|
|
29
|
-
"aws-sdk": "^2.
|
|
29
|
+
"aws-sdk": "^2.1168.0",
|
|
30
30
|
"babel-runtime": "^6.26.0",
|
|
31
31
|
"docdash": "^1.2.0",
|
|
32
32
|
"husky": "^8.0.1",
|
|
33
|
-
"jest": "^28.1.
|
|
33
|
+
"jest": "^28.1.2",
|
|
34
34
|
"pinst": "^3.0.0",
|
|
35
35
|
"ts-standard": "^11.0.0",
|
|
36
36
|
"typescript": "^4.7.4"
|