@onereach/step-voice 6.1.16-changegrammarstructure.0 → 6.1.17-test.0
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/Choice.js +19 -3
- package/dst/Custom Voice Input.js +1 -1
- package/dst/Global Command.js +1 -1
- package/dst/Keypad Input.js +1 -1
- package/dst/Say Message.js +20 -10
- package/dst/voice.d.ts +12 -2
- package/dst/voice.js +46 -6
- package/package.json +1 -1
package/dst/Choice.js
CHANGED
|
@@ -81,7 +81,7 @@ class Choice extends voice_1.default {
|
|
|
81
81
|
const grammar = {
|
|
82
82
|
id: this.currentStepId,
|
|
83
83
|
choices,
|
|
84
|
-
asrSettings
|
|
84
|
+
asr: asrSettings
|
|
85
85
|
};
|
|
86
86
|
const command = {
|
|
87
87
|
name: 'speak',
|
|
@@ -97,6 +97,19 @@ class Choice extends voice_1.default {
|
|
|
97
97
|
// There's a specific need to do so. There might be ${variable} section
|
|
98
98
|
this.triggers.local(`in/voice/${call.id}`, async (event) => {
|
|
99
99
|
const reportingSettingsKey = this.rptsStarted ? 'transcriptRepromptResponse' : 'transcriptResponse';
|
|
100
|
+
const interruptionMetadata = event.params.interruptionMetadata ?? null;
|
|
101
|
+
if (interruptionMetadata) {
|
|
102
|
+
await this.transcript(call, {
|
|
103
|
+
sections: speechSections,
|
|
104
|
+
reprompt: {
|
|
105
|
+
maxAttempts: repromptsList.length,
|
|
106
|
+
attempt: 0
|
|
107
|
+
},
|
|
108
|
+
reportingSettingsKey: 'transcriptPrompt',
|
|
109
|
+
action: 'Call Prompt',
|
|
110
|
+
actionFromBot: true
|
|
111
|
+
}, interruptionMetadata);
|
|
112
|
+
}
|
|
100
113
|
switch (event.params.type) {
|
|
101
114
|
case 'digit':
|
|
102
115
|
case 'digits': {
|
|
@@ -105,9 +118,11 @@ class Choice extends voice_1.default {
|
|
|
105
118
|
const exitId = params.exitId;
|
|
106
119
|
// On bargeIn, we should stop playback
|
|
107
120
|
if (exitExists(exitId)) {
|
|
121
|
+
const exitStepLabel = this.getExitStepLabel(exitId) ?? '';
|
|
122
|
+
const message = lodash_1.default.replace(exitStepLabel, /^(\d+\. )?(~ )?/, '');
|
|
108
123
|
await this.transcript(call, {
|
|
109
124
|
keyPress: digit,
|
|
110
|
-
message:
|
|
125
|
+
message: message,
|
|
111
126
|
reportingSettingsKey,
|
|
112
127
|
action: 'Call DTMF',
|
|
113
128
|
actionFromBot: false
|
|
@@ -245,7 +260,7 @@ class Choice extends voice_1.default {
|
|
|
245
260
|
}
|
|
246
261
|
});
|
|
247
262
|
this.triggers.otherwise(async () => {
|
|
248
|
-
await this.transcript(call, {
|
|
263
|
+
const eventId = await this.transcript(call, {
|
|
249
264
|
sections: speechSections,
|
|
250
265
|
reprompt: {
|
|
251
266
|
maxAttempts: repromptsList.length,
|
|
@@ -255,6 +270,7 @@ class Choice extends voice_1.default {
|
|
|
255
270
|
action: 'Call Prompt',
|
|
256
271
|
actionFromBot: true
|
|
257
272
|
});
|
|
273
|
+
command.params.reporterTranscriptEventId = eventId;
|
|
258
274
|
command.params.sections = speechSections;
|
|
259
275
|
command.params.timeout = this.rptsTimeout({ noReplyDelay, repromptsList, initial: true });
|
|
260
276
|
await this.pauseRecording(call, command, sensitiveData);
|
package/dst/Global Command.js
CHANGED
package/dst/Keypad Input.js
CHANGED
package/dst/Say Message.js
CHANGED
|
@@ -8,7 +8,26 @@ class SayMessage extends voice_1.default {
|
|
|
8
8
|
async runStep() {
|
|
9
9
|
const { audio, textType, tts, sensitiveData } = this.data;
|
|
10
10
|
const call = await this.fetchData();
|
|
11
|
+
const speechSections = lodash_1.default.map(audio, (section) => ({
|
|
12
|
+
text: section.voiceTextMsg,
|
|
13
|
+
url: section.audioUrl,
|
|
14
|
+
bargeInVoice: false,
|
|
15
|
+
bargeInKeypad: false,
|
|
16
|
+
textType,
|
|
17
|
+
provider: ttsSettings.provider,
|
|
18
|
+
...ttsSettings
|
|
19
|
+
}));
|
|
20
|
+
const ttsSettings = tts.getSettings(call.tts);
|
|
11
21
|
this.triggers.local(`in/voice/${call.id}`, async (event) => {
|
|
22
|
+
const interruptionMetadata = event.params.interruptionMetadata ?? null;
|
|
23
|
+
if (interruptionMetadata) {
|
|
24
|
+
await this.transcript(call, {
|
|
25
|
+
action: 'Call Prompt',
|
|
26
|
+
sections: speechSections,
|
|
27
|
+
reportingSettingsKey: 'transcript',
|
|
28
|
+
actionFromBot: true
|
|
29
|
+
}, interruptionMetadata);
|
|
30
|
+
}
|
|
12
31
|
switch (event.params.type) {
|
|
13
32
|
case 'hangup':
|
|
14
33
|
await this.handleHangup(call);
|
|
@@ -26,19 +45,10 @@ class SayMessage extends voice_1.default {
|
|
|
26
45
|
}
|
|
27
46
|
});
|
|
28
47
|
this.triggers.otherwise(async () => {
|
|
29
|
-
const ttsSettings = tts.getSettings(call.tts);
|
|
30
48
|
const command = {
|
|
31
49
|
name: 'speak',
|
|
32
50
|
params: {
|
|
33
|
-
sections:
|
|
34
|
-
text: section.voiceTextMsg,
|
|
35
|
-
url: section.audioUrl,
|
|
36
|
-
bargeInVoice: false,
|
|
37
|
-
bargeInKeypad: false,
|
|
38
|
-
textType,
|
|
39
|
-
provider: ttsSettings.provider,
|
|
40
|
-
...ttsSettings
|
|
41
|
-
}))
|
|
51
|
+
sections: speechSections
|
|
42
52
|
}
|
|
43
53
|
};
|
|
44
54
|
await this.transcript(call, {
|
package/dst/voice.d.ts
CHANGED
|
@@ -42,10 +42,19 @@ export type VoicerError = Error & {
|
|
|
42
42
|
date?: never;
|
|
43
43
|
originateStatus?: never;
|
|
44
44
|
};
|
|
45
|
+
export interface VoiceInterruptionMetadata {
|
|
46
|
+
interruptionReason: 'keypad' | 'voice';
|
|
47
|
+
interruptionTime: number;
|
|
48
|
+
playedTime: number;
|
|
49
|
+
sectionIndex: number;
|
|
50
|
+
sectionDuration: number;
|
|
51
|
+
reporterTranscriptEventId: string;
|
|
52
|
+
}
|
|
45
53
|
export interface VoiceEvent {
|
|
46
54
|
type: EventType;
|
|
47
55
|
global?: boolean;
|
|
48
56
|
error?: VoicerError;
|
|
57
|
+
interruptionMetadata: VoiceInterruptionMetadata;
|
|
49
58
|
}
|
|
50
59
|
export interface CallStartEvent extends VoiceEvent {
|
|
51
60
|
channel: IVoiceCall;
|
|
@@ -61,14 +70,15 @@ export default class VoiceStep<TIn = unknown, TOut = unknown, TParams extends Vo
|
|
|
61
70
|
sendCommands({ id, type, callback }: IVoiceCall, commands: TODO[]): Promise<void>;
|
|
62
71
|
handleHeartbeat(call: IVoiceCall): Promise<void>;
|
|
63
72
|
handleCancel(): void;
|
|
64
|
-
extractSectionMessages(sections: IPromtpSection[]): string;
|
|
73
|
+
extractSectionMessages(sections: IPromtpSection[], interruptionMetadata?: VoiceInterruptionMetadata): string;
|
|
74
|
+
extractPlayedSectionMessage(text: string, sectionDuration: number, playedTime: number): string;
|
|
65
75
|
extractSectionFiles(sections: IPromtpSection[]): Array<{
|
|
66
76
|
fileUrl: string;
|
|
67
77
|
fileType: string;
|
|
68
78
|
}>;
|
|
69
79
|
pauseRecording(call: IVoiceCall, command: any, sensitiveData?: SensitiveData): Promise<void>;
|
|
70
80
|
resumeRecording(call: IVoiceCall, sensitiveData?: SensitiveData): Promise<void>;
|
|
71
|
-
transcript(call: IVoiceCall, data?: Partial<IVoiceReporterTranscriptEventArgs
|
|
81
|
+
transcript(call: IVoiceCall, data?: Partial<IVoiceReporterTranscriptEventArgs>, interruptionMetadata?: VoiceInterruptionMetadata): Promise<string>;
|
|
72
82
|
throwError(error?: VoicerError): never;
|
|
73
83
|
handleHangup(call: IVoiceCall): Promise<void>;
|
|
74
84
|
buildSections({ sections, textType, ttsSettings, allowKeypadBargeIn }: TODO): TODO;
|
package/dst/voice.js
CHANGED
|
@@ -103,16 +103,33 @@ class VoiceStep extends step_1.default {
|
|
|
103
103
|
else
|
|
104
104
|
this.end();
|
|
105
105
|
}
|
|
106
|
-
extractSectionMessages(sections) {
|
|
106
|
+
extractSectionMessages(sections, interruptionMetadata) {
|
|
107
107
|
return lodash_1.default.chain(sections)
|
|
108
108
|
.filter(s => Boolean(s.text))
|
|
109
|
-
.map(s => {
|
|
109
|
+
.map((s, index) => {
|
|
110
110
|
// Should escape html, max length 4000 symbols
|
|
111
|
-
|
|
111
|
+
let text = s.text?.slice(0, 4000).replace(/(<[^>]+>|<\/[^>]+>)/gi, ' ') ?? '';
|
|
112
|
+
// Extracts the portion of the section text that corresponds to the played time.
|
|
113
|
+
if (interruptionMetadata) {
|
|
114
|
+
const { playedTime, sectionDuration, sectionIndex } = interruptionMetadata;
|
|
115
|
+
if (sectionIndex === index) {
|
|
116
|
+
text = this.extractPlayedSectionMessage(text, sectionDuration, playedTime);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return text;
|
|
112
120
|
})
|
|
113
121
|
.join(' ')
|
|
114
122
|
.value();
|
|
115
123
|
}
|
|
124
|
+
extractPlayedSectionMessage(text, sectionDuration, playedTime) {
|
|
125
|
+
const words = text.split(' ');
|
|
126
|
+
const totalWords = words.length;
|
|
127
|
+
const sectionDurationSec = sectionDuration / 1000;
|
|
128
|
+
const playedTimeSec = playedTime / 1000;
|
|
129
|
+
const wordsPerSecond = totalWords / sectionDurationSec;
|
|
130
|
+
const wordsPlayed = Math.floor(wordsPerSecond * playedTimeSec);
|
|
131
|
+
return words.slice(0, wordsPlayed).join(' ');
|
|
132
|
+
}
|
|
116
133
|
extractSectionFiles(sections) {
|
|
117
134
|
return lodash_1.default.chain(sections)
|
|
118
135
|
.filter(s => Boolean(s.url))
|
|
@@ -151,7 +168,7 @@ class VoiceStep extends step_1.default {
|
|
|
151
168
|
}
|
|
152
169
|
}]);
|
|
153
170
|
}
|
|
154
|
-
async transcript(call, data = {}) {
|
|
171
|
+
async transcript(call, data = {}, interruptionMetadata) {
|
|
155
172
|
const { previousTranscriptId = call.lastTranscriptId, action, keyPress, message, voiceProcessResult, reportingSettingsKey, sections, reprompt, recording, conferenceId, actionFromBot = false } = data;
|
|
156
173
|
const eventId = (0, uuid_1.v4)();
|
|
157
174
|
const fromIdentifier = actionFromBot ? call.botNumber : call.endUserNumber;
|
|
@@ -175,7 +192,7 @@ class VoiceStep extends step_1.default {
|
|
|
175
192
|
eventId
|
|
176
193
|
};
|
|
177
194
|
if (sections != null) {
|
|
178
|
-
const allMessages = this.extractSectionMessages(sections);
|
|
195
|
+
const allMessages = this.extractSectionMessages(sections, interruptionMetadata);
|
|
179
196
|
const allFiles = this.extractSectionFiles(sections);
|
|
180
197
|
if (!lodash_1.default.isEmpty(allMessages))
|
|
181
198
|
reportingObject.message = allMessages;
|
|
@@ -195,7 +212,30 @@ class VoiceStep extends step_1.default {
|
|
|
195
212
|
reportingObject.keyPress = keyPress;
|
|
196
213
|
else if (voiceProcessResult)
|
|
197
214
|
reportingObject.voiceProcessResult = voiceProcessResult;
|
|
198
|
-
|
|
215
|
+
/**
|
|
216
|
+
* If we have the previous transcript event ID,
|
|
217
|
+
* which was returned from the interrupted message,
|
|
218
|
+
* try to update the reporting message.
|
|
219
|
+
*/
|
|
220
|
+
if (interruptionMetadata?.reporterTranscriptEventId) {
|
|
221
|
+
if (this.process.cache.hitl) {
|
|
222
|
+
const updateReportingObject = {
|
|
223
|
+
EventId: eventId,
|
|
224
|
+
Timestamp: new Date().toISOString(),
|
|
225
|
+
Event: 'Augment',
|
|
226
|
+
EventValue: {
|
|
227
|
+
eventId: interruptionMetadata.reporterTranscriptEventId,
|
|
228
|
+
eventValue: {
|
|
229
|
+
Message: reportingObject.message,
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
await this.process.cache.hitl.queueEvents([updateReportingObject]);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
await this.reporter.reportTranscriptEvent(reportingObject);
|
|
238
|
+
}
|
|
199
239
|
call.lastTranscriptId = eventId;
|
|
200
240
|
await this.updateData();
|
|
201
241
|
return eventId;
|