@onereach/step-voice 5.0.9-fixsubflow.1 → 5.0.9-fixsubflow.3
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.js +7 -7
- package/dst/Global Command.d.ts +1 -1
- package/dst/Global Command.js +19 -32
- package/dst/Initiate Call.js +15 -8
- package/dst/Say Message.js +3 -4
- package/dst/Send DTMF.d.ts +1 -1
- package/dst/Send DTMF.js +21 -21
- package/dst/step.d.ts +26 -22
- package/dst/step.js +178 -101
- package/dst/voice.d.ts +3 -2
- package/dst/voice.js +22 -11
- package/package.json +2 -2
package/dst/Cancel.js
CHANGED
|
@@ -4,12 +4,12 @@ const tslib_1 = require("tslib");
|
|
|
4
4
|
const voice_1 = tslib_1.__importDefault(require("./voice"));
|
|
5
5
|
class VoiceCancel extends voice_1.default {
|
|
6
6
|
async runStep() {
|
|
7
|
-
const conv = await this.getConversation()
|
|
8
|
-
if (conv.lcl.length <= 1) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
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
|
+
// }
|
|
13
13
|
const call = await this.fetchData();
|
|
14
14
|
this.triggers.once(`in/voice/${call.id}/event`, async (event) => {
|
|
15
15
|
switch (event.params.type) {
|
|
@@ -19,7 +19,7 @@ class VoiceCancel extends voice_1.default {
|
|
|
19
19
|
case 'error':
|
|
20
20
|
return this.throwError(event.params.error);
|
|
21
21
|
case 'cancel': {
|
|
22
|
-
await this.popConvStep()
|
|
22
|
+
// await this.popConvStep() // pop current command (cancel)
|
|
23
23
|
await this.cancel(); // cancel previous command
|
|
24
24
|
return this.exitStep('next');
|
|
25
25
|
}
|
package/dst/Global Command.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export default class GlobalCommand extends VoiceStep<Partial<INPUT>, OUTPUT, EVE
|
|
|
31
31
|
get useQueue(): boolean;
|
|
32
32
|
runStep(): Promise<void>;
|
|
33
33
|
initGrammar(): Promise<void>;
|
|
34
|
-
|
|
34
|
+
_worker(): Promise<void>;
|
|
35
35
|
hangup(call: IVoiceCall): Promise<unknown>;
|
|
36
36
|
exitThread(event: ITypedEvent<EVENT>, type: string, stepExit: string): Promise<void>;
|
|
37
37
|
onAwake(): Promise<void>;
|
package/dst/Global Command.js
CHANGED
|
@@ -7,28 +7,12 @@ const nanoid_1 = require("nanoid");
|
|
|
7
7
|
const voice_1 = tslib_1.__importDefault(require("./voice"));
|
|
8
8
|
class GlobalCommand extends voice_1.default {
|
|
9
9
|
get isGlobal() {
|
|
10
|
-
return
|
|
10
|
+
return true;
|
|
11
11
|
}
|
|
12
12
|
get useQueue() {
|
|
13
|
-
return this.
|
|
13
|
+
return this.isWorker;
|
|
14
14
|
}
|
|
15
15
|
async runStep() {
|
|
16
|
-
const globThread = this.process.newThread(this.globalThreadId, thread => {
|
|
17
|
-
thread.state = {
|
|
18
|
-
name: 'globThread',
|
|
19
|
-
step: this.step.id,
|
|
20
|
-
thread: this.dataThreadId
|
|
21
|
-
};
|
|
22
|
-
});
|
|
23
|
-
if (globThread.isNewThread) {
|
|
24
|
-
globThread.activate();
|
|
25
|
-
await globThread.run();
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
globThread.state.step = this.step.id;
|
|
29
|
-
}
|
|
30
|
-
// refresh cache after global thread was started
|
|
31
|
-
this._clearCache();
|
|
32
16
|
await this.initGrammar();
|
|
33
17
|
this.exitStep('no commands');
|
|
34
18
|
}
|
|
@@ -62,23 +46,26 @@ class GlobalCommand extends voice_1.default {
|
|
|
62
46
|
}
|
|
63
47
|
]);
|
|
64
48
|
}
|
|
65
|
-
async
|
|
49
|
+
async _worker() {
|
|
66
50
|
const call = await this.fetchData();
|
|
67
51
|
if (call.vv >= 1 && lodash_1.default.isFunction(this.triggers.hook)) {
|
|
68
|
-
this.triggers.hook({ name: '
|
|
52
|
+
this.triggers.hook({ name: 'waitEnd', thread: 'main', sync: true }, async () => {
|
|
69
53
|
this.thread.background = call._conv.glb.length > 1;
|
|
70
|
-
|
|
54
|
+
if (this.thread.background)
|
|
55
|
+
this.end();
|
|
71
56
|
});
|
|
72
57
|
this.triggers.hook({ name: 'end', thread: 'main' }, async () => {
|
|
73
58
|
this.log.debug('gc terminate', { bg: this.thread.background });
|
|
74
|
-
if (await this.popConvStep()) {
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
this.
|
|
59
|
+
// if (await this.popConvStep()) {
|
|
60
|
+
// await this.sendEventToStep({ toWorker: this.isWorker, action: 'onAwake' })
|
|
61
|
+
// }
|
|
62
|
+
await this.sendCommands(call, [{ name: 'grammar', params: {} }]);
|
|
63
|
+
if (!this.thread.ending)
|
|
64
|
+
this.end();
|
|
78
65
|
});
|
|
79
66
|
// TODO remove this hack that prevents this.triggers.once execution below
|
|
80
67
|
// currently it skips logic to override triggers (is there better way to do it?)
|
|
81
|
-
if (this.event.name.startsWith('@
|
|
68
|
+
if (this.event.name.startsWith('@'))
|
|
82
69
|
return;
|
|
83
70
|
}
|
|
84
71
|
this.triggers.once(`in/voice/${call.id}/event`, async (event) => {
|
|
@@ -86,7 +73,7 @@ class GlobalCommand extends voice_1.default {
|
|
|
86
73
|
switch (event.params.type) {
|
|
87
74
|
case 'hangup': {
|
|
88
75
|
await this.hangup(call);
|
|
89
|
-
await this.popConvStep()
|
|
76
|
+
// await this.popConvStep()
|
|
90
77
|
await this.notifyConvEnd();
|
|
91
78
|
return this.end();
|
|
92
79
|
}
|
|
@@ -137,10 +124,10 @@ class GlobalCommand extends voice_1.default {
|
|
|
137
124
|
return {};
|
|
138
125
|
}
|
|
139
126
|
case 'error': {
|
|
140
|
-
const localHandler = await this.sendEventToStep({
|
|
141
|
-
if (!localHandler) {
|
|
142
|
-
|
|
143
|
-
}
|
|
127
|
+
// const localHandler = await this.sendEventToStep({ toWorker: false, event: { ...this.event, processed: undefined, action: 'lcl' } })
|
|
128
|
+
// if (!localHandler) {
|
|
129
|
+
// this.throwError(event.params.error)
|
|
130
|
+
// }
|
|
144
131
|
this.event.processed = true;
|
|
145
132
|
break;
|
|
146
133
|
}
|
|
@@ -223,7 +210,7 @@ class GlobalCommand extends voice_1.default {
|
|
|
223
210
|
async onAwake() {
|
|
224
211
|
await super.onAwake();
|
|
225
212
|
await this.initGrammar();
|
|
226
|
-
await this.
|
|
213
|
+
await this.worker();
|
|
227
214
|
this.triggers.refreshAll();
|
|
228
215
|
}
|
|
229
216
|
exitToThread() {
|
package/dst/Initiate Call.js
CHANGED
|
@@ -31,9 +31,9 @@ class InitiateCall extends voice_1.default {
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
-
const convData = { id: callId, type: 'voicer', vv: 0 };
|
|
34
|
+
const convData = { id: callId, type: 'voicer', vv: 0 }; // vv - voicer version
|
|
35
35
|
await this.startConversation(convData);
|
|
36
|
-
await this.pushConvStep()
|
|
36
|
+
// await this.pushConvStep()
|
|
37
37
|
this.gotoState('waitForCall');
|
|
38
38
|
}
|
|
39
39
|
async onAwake() {
|
|
@@ -66,7 +66,7 @@ class InitiateCall extends voice_1.default {
|
|
|
66
66
|
return this.exitFlow();
|
|
67
67
|
}
|
|
68
68
|
case 'call': {
|
|
69
|
-
const
|
|
69
|
+
const newCall = {
|
|
70
70
|
headers: event.params.headers,
|
|
71
71
|
...event.params.channel,
|
|
72
72
|
asr: asr.getSettings(),
|
|
@@ -74,15 +74,17 @@ class InitiateCall extends voice_1.default {
|
|
|
74
74
|
botNumber: event.params.channel.to ?? 'unknown',
|
|
75
75
|
endUserNumber
|
|
76
76
|
};
|
|
77
|
-
delete
|
|
78
|
-
delete
|
|
79
|
-
|
|
80
|
-
await this.
|
|
77
|
+
delete newCall.from;
|
|
78
|
+
delete newCall.to;
|
|
79
|
+
newCall._conv = call._conv;
|
|
80
|
+
await this.startConversation(newCall);
|
|
81
|
+
// await this.popConvStep()
|
|
82
|
+
await this.transcript(newCall, {
|
|
81
83
|
action: 'Call Start',
|
|
82
84
|
reportingSettingsKey: 'transcript',
|
|
83
85
|
actionFromBot: true
|
|
84
86
|
});
|
|
85
|
-
await this.sendCommands(
|
|
87
|
+
await this.sendCommands(newCall, [
|
|
86
88
|
...isAMD
|
|
87
89
|
? [{
|
|
88
90
|
name: 'start-avmd',
|
|
@@ -102,6 +104,11 @@ class InitiateCall extends voice_1.default {
|
|
|
102
104
|
]);
|
|
103
105
|
return this.exitStep('success');
|
|
104
106
|
}
|
|
107
|
+
case 'hangup': {
|
|
108
|
+
await this.handleHangup(call);
|
|
109
|
+
this.end();
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
105
112
|
case 'error': {
|
|
106
113
|
const error = lodash_1.default.get(event, 'params.error.originateStatus');
|
|
107
114
|
const errorCall = {
|
package/dst/Say Message.js
CHANGED
|
@@ -18,10 +18,9 @@ class SayMessage extends voice_1.default {
|
|
|
18
18
|
return this.exitStep('next');
|
|
19
19
|
case 'error':
|
|
20
20
|
return this.throwError(event.params.error);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
// }
|
|
21
|
+
case 'cancel': {
|
|
22
|
+
return this.data.handleCancel === true && this.exitStep('cancel');
|
|
23
|
+
}
|
|
25
24
|
default:
|
|
26
25
|
return this.exitFlow();
|
|
27
26
|
}
|
package/dst/Send DTMF.d.ts
CHANGED
package/dst/Send DTMF.js
CHANGED
|
@@ -7,23 +7,23 @@ const schema = joi_1.default.object().keys({
|
|
|
7
7
|
dtmf: joi_1.default
|
|
8
8
|
.string()
|
|
9
9
|
.required()
|
|
10
|
-
.replace(/\s+/,
|
|
11
|
-
.pattern(/^[0-9A-DwW*#]+$/,
|
|
10
|
+
.replace(/\s+/, '')
|
|
11
|
+
.pattern(/^[0-9A-DwW*#]+$/, 'symbols')
|
|
12
12
|
.messages({
|
|
13
|
-
|
|
13
|
+
'string.pattern.symbols': '{{#label}} should only contain symbols like: 0-9, *, #, A-D, W, w'
|
|
14
14
|
}),
|
|
15
15
|
tonesDuration: joi_1.default.number().required().min(200).max(5000).messages({
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
'number.min': '{{#label}} should be between 200 and 5000 milliseconds',
|
|
17
|
+
'number.max': '{{#label}} should be between 200 and 5000 milliseconds'
|
|
18
18
|
}),
|
|
19
19
|
beforeDelay: joi_1.default.number().required().min(0).max(5000).messages({
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
'number.min': '{{#label}} should be between 0 and 5000 milliseconds',
|
|
21
|
+
'number.max': '{{#label}} should be between 0 and 5000 milliseconds'
|
|
22
22
|
}),
|
|
23
23
|
afterDelay: joi_1.default.number().required().min(0).max(5000).messages({
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
})
|
|
24
|
+
'number.min': '{{#label}} should be between 0 and 5000 milliseconds',
|
|
25
|
+
'number.max': '{{#label}} should be between 0 and 5000 milliseconds'
|
|
26
|
+
})
|
|
27
27
|
});
|
|
28
28
|
class SendDTMF extends voice_1.default {
|
|
29
29
|
async runStep() {
|
|
@@ -33,18 +33,18 @@ class SendDTMF extends voice_1.default {
|
|
|
33
33
|
dtmf,
|
|
34
34
|
tonesDuration,
|
|
35
35
|
beforeDelay,
|
|
36
|
-
afterDelay
|
|
36
|
+
afterDelay
|
|
37
37
|
});
|
|
38
38
|
if (validationError != null)
|
|
39
39
|
throw new Error(validationError.message);
|
|
40
40
|
const command = {
|
|
41
|
-
name:
|
|
41
|
+
name: 'send-dtmf',
|
|
42
42
|
params: {
|
|
43
43
|
dtmf,
|
|
44
44
|
tonesDuration: +tonesDuration,
|
|
45
45
|
beforeDelay: +beforeDelay,
|
|
46
|
-
afterDelay: +afterDelay
|
|
47
|
-
}
|
|
46
|
+
afterDelay: +afterDelay
|
|
47
|
+
}
|
|
48
48
|
};
|
|
49
49
|
this.triggers.once(`in/voice/${call.id}/event`, async (event) => {
|
|
50
50
|
// if (channel.callback.id)
|
|
@@ -53,11 +53,11 @@ class SendDTMF extends voice_1.default {
|
|
|
53
53
|
// "callback"
|
|
54
54
|
// );
|
|
55
55
|
switch (event.params.type) {
|
|
56
|
-
case
|
|
56
|
+
case 'hangup':
|
|
57
57
|
return this.end();
|
|
58
|
-
case
|
|
59
|
-
return this.exitStep(
|
|
60
|
-
case
|
|
58
|
+
case 'dtmf-sent':
|
|
59
|
+
return this.exitStep('next');
|
|
60
|
+
case 'error':
|
|
61
61
|
return this.throwError(event.params.error);
|
|
62
62
|
default:
|
|
63
63
|
return this.exitFlow();
|
|
@@ -65,11 +65,11 @@ class SendDTMF extends voice_1.default {
|
|
|
65
65
|
});
|
|
66
66
|
this.triggers.otherwise(async () => {
|
|
67
67
|
await this.transcript(call, {
|
|
68
|
-
reportingSettingsKey:
|
|
69
|
-
action:
|
|
68
|
+
reportingSettingsKey: 'transcript',
|
|
69
|
+
action: 'Send DTMF',
|
|
70
70
|
actionFromBot: true,
|
|
71
71
|
keyPress: dtmf,
|
|
72
|
-
message: dtmf
|
|
72
|
+
message: dtmf
|
|
73
73
|
});
|
|
74
74
|
await this.sendCommands(call, [command]);
|
|
75
75
|
return this.exitFlow();
|
package/dst/step.d.ts
CHANGED
|
@@ -1,36 +1,49 @@
|
|
|
1
1
|
import Step from '@onereach/flow-sdk/dst/step';
|
|
2
|
-
import { IThreadId,
|
|
3
|
-
import { IConversationStep } from '@onereach/step-conversation/dst/types';
|
|
2
|
+
import { IThreadId, IMergeField } from '@onereach/flow-sdk/dst/types';
|
|
4
3
|
export interface ConvStepDataIn {
|
|
5
4
|
conversation?: string | IMergeField;
|
|
6
5
|
conversationThread?: IThreadId;
|
|
7
6
|
}
|
|
8
|
-
interface IConversation {
|
|
9
|
-
glb: IConversationStep[];
|
|
7
|
+
export interface IConversation {
|
|
10
8
|
lcl: IConversationStep[];
|
|
11
|
-
|
|
9
|
+
glb: IConversationStep[];
|
|
12
10
|
}
|
|
13
|
-
interface IConversationData {
|
|
11
|
+
export interface IConversationData {
|
|
14
12
|
_conv: IConversation;
|
|
15
13
|
}
|
|
16
|
-
export
|
|
14
|
+
export declare const enum ConvThreadType {
|
|
15
|
+
lcl = "lcl",
|
|
16
|
+
glb = "glb",
|
|
17
|
+
wrk = "wrk"
|
|
18
|
+
}
|
|
19
|
+
interface IConversationStep {
|
|
20
|
+
key: string;
|
|
21
|
+
trd: string;
|
|
22
|
+
typ?: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
label?: string;
|
|
25
|
+
step?: string;
|
|
26
|
+
}
|
|
27
|
+
export default abstract class ConvStep<TData extends IConversationData, TIn = unknown, TOut = unknown, TParams = any> extends Step<TIn & ConvStepDataIn, TOut, TParams> {
|
|
17
28
|
private convDataCache?;
|
|
18
|
-
|
|
29
|
+
abstract _worker(data: IConversationData): Promise<void>;
|
|
30
|
+
get cache(): TData | undefined;
|
|
19
31
|
get conversation(): string | IMergeField;
|
|
20
32
|
get conversationId(): string;
|
|
21
|
-
get
|
|
33
|
+
get workerThreadId(): string;
|
|
22
34
|
/** id of the thread where conversation data is stored */
|
|
23
35
|
get dataThreadId(): IThreadId;
|
|
24
36
|
get isGlobal(): boolean;
|
|
37
|
+
get threadType(): ConvThreadType;
|
|
38
|
+
get isWorker(): boolean;
|
|
25
39
|
get useQueue(): boolean;
|
|
26
|
-
fetchData(): Promise<TData
|
|
40
|
+
fetchData(): Promise<TData>;
|
|
27
41
|
getConversation(): Promise<IConversation>;
|
|
28
42
|
updateData(): Promise<void>;
|
|
29
43
|
hasConversation(): Promise<boolean>;
|
|
44
|
+
protected worker(): Promise<void>;
|
|
30
45
|
runBefore(): Promise<void>;
|
|
31
|
-
runHandle(): Promise<unknown>;
|
|
32
46
|
runAfter(): Promise<void>;
|
|
33
|
-
hasActiveGlobal(): Promise<boolean>;
|
|
34
47
|
waitForConversation(): Promise<void>;
|
|
35
48
|
protected onSkipEvent(): Promise<void>;
|
|
36
49
|
cancel(): Promise<void>;
|
|
@@ -47,21 +60,12 @@ export default class ConvStep<TData = unknown, TIn = unknown, TOut = unknown, TP
|
|
|
47
60
|
onConvEnd(): Promise<void>;
|
|
48
61
|
pause(): Promise<void>;
|
|
49
62
|
resume(): Promise<void>;
|
|
50
|
-
protected sendEventToStep({ toGlobal, toStep, action, event }: {
|
|
51
|
-
action?: string;
|
|
52
|
-
event?: IEvent;
|
|
53
|
-
toStep?: IConversationStep;
|
|
54
|
-
toGlobal?: boolean;
|
|
55
|
-
}): Promise<IStepResult | undefined>;
|
|
56
|
-
activeStep(isGlobal?: boolean): Promise<IConversationStep | undefined>;
|
|
57
63
|
/** @returns true if current conv is active */
|
|
58
|
-
protected pushConvStep(): Promise<boolean>;
|
|
59
64
|
/** @returns true if current conv was active */
|
|
60
|
-
protected popConvStep(popStep?: IConversationStep): Promise<boolean>;
|
|
61
65
|
startConversation(data: TData, { thread }?: {
|
|
62
66
|
thread?: IThreadId;
|
|
63
67
|
}): Promise<void>;
|
|
64
|
-
protected _fetchCache(): Promise<(TData
|
|
68
|
+
protected _fetchCache(): Promise<(TData) | undefined>;
|
|
65
69
|
protected _clearCache(): void;
|
|
66
70
|
protected _refreshCache(): Promise<void>;
|
|
67
71
|
}
|
package/dst/step.js
CHANGED
|
@@ -25,7 +25,7 @@ class ConvStep extends step_1.default {
|
|
|
25
25
|
return convOrName;
|
|
26
26
|
throw new Error(`invalid conversation ${JSON.stringify(conv)}`);
|
|
27
27
|
}
|
|
28
|
-
get
|
|
28
|
+
get workerThreadId() {
|
|
29
29
|
return `G:${this.conversationId}`;
|
|
30
30
|
}
|
|
31
31
|
/** id of the thread where conversation data is stored */
|
|
@@ -36,6 +36,14 @@ class ConvStep extends step_1.default {
|
|
|
36
36
|
get isGlobal() {
|
|
37
37
|
return false;
|
|
38
38
|
}
|
|
39
|
+
get threadType() {
|
|
40
|
+
return this.thread.id === this.workerThreadId
|
|
41
|
+
? (this.isGlobal ? "glb" /* ConvThreadType.glb */ : "wrk" /* ConvThreadType.wrk */)
|
|
42
|
+
: "lcl" /* ConvThreadType.lcl */;
|
|
43
|
+
}
|
|
44
|
+
get isWorker() {
|
|
45
|
+
return this.threadType !== "lcl" /* ConvThreadType.lcl */;
|
|
46
|
+
}
|
|
39
47
|
get useQueue() {
|
|
40
48
|
return true;
|
|
41
49
|
}
|
|
@@ -58,13 +66,18 @@ class ConvStep extends step_1.default {
|
|
|
58
66
|
async hasConversation() {
|
|
59
67
|
return (await this._fetchCache())?._conv != null;
|
|
60
68
|
}
|
|
69
|
+
async worker() {
|
|
70
|
+
this.triggers.local('_conv');
|
|
71
|
+
if (this.cache == null)
|
|
72
|
+
return;
|
|
73
|
+
await this._worker(this.cache);
|
|
74
|
+
}
|
|
61
75
|
async runBefore() {
|
|
62
76
|
await super.runBefore();
|
|
63
77
|
if (this.thread.ending)
|
|
64
78
|
return;
|
|
65
79
|
// ensure cache is reset between step runs, just in case
|
|
66
80
|
this._clearCache();
|
|
67
|
-
this.triggers.local('_conv');
|
|
68
81
|
if (!await this.hasConversation())
|
|
69
82
|
return;
|
|
70
83
|
this.log.debug('conv.runBefore', { state: this.state, conv: this.convDataCache?._conv });
|
|
@@ -76,36 +89,69 @@ class ConvStep extends step_1.default {
|
|
|
76
89
|
this.state.name = this.event.action;
|
|
77
90
|
return;
|
|
78
91
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
async runAfter() {
|
|
91
|
-
if (this.thread.ending)
|
|
92
|
+
console.log('BEFORE', {
|
|
93
|
+
event: this.event,
|
|
94
|
+
state: this.state,
|
|
95
|
+
name: this.constructor.name,
|
|
96
|
+
thread: this.thread.id,
|
|
97
|
+
...this.cache?._conv
|
|
98
|
+
});
|
|
99
|
+
// if (this.useQueue && !await this.pushConvStep()) {
|
|
100
|
+
// return await this.waitForConversation()
|
|
101
|
+
// }
|
|
102
|
+
if (this.cache == null)
|
|
92
103
|
return;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (this.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
// const glb = this.cache._conv.glb
|
|
105
|
+
// if (!this.isGlobal && glb.length > 0 && glb[glb.length - 1].typ !== ConvThreadType.wrk) return
|
|
106
|
+
if (!this.isGlobal)
|
|
107
|
+
return;
|
|
108
|
+
if (this.thread.id !== this.workerThreadId) {
|
|
109
|
+
const worker = this.process.newThread(this.workerThreadId, thread => {
|
|
110
|
+
thread.state = {
|
|
111
|
+
name: 'worker',
|
|
112
|
+
step: this.step.id,
|
|
113
|
+
thread: this.dataThreadId
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
if (worker.isNewThread === true || worker.state.step !== this.step.id) {
|
|
117
|
+
worker.state.step = this.step.id;
|
|
118
|
+
worker.activate();
|
|
119
|
+
await worker.run();
|
|
120
|
+
await this._refreshCache();
|
|
99
121
|
}
|
|
100
122
|
}
|
|
101
|
-
if (this.isGlobal && !this.event.processed) {
|
|
102
|
-
await this.sendEventToStep({ toGlobal: false, event: { ...this.event, processed: undefined, action: 'local' } });
|
|
103
|
-
}
|
|
104
|
-
await super.runAfter();
|
|
105
123
|
}
|
|
106
|
-
async
|
|
107
|
-
|
|
108
|
-
|
|
124
|
+
// public async runHandle (): Promise<unknown> {
|
|
125
|
+
// if (this.thread.ending || this.state.name === 'onConvEnd') {
|
|
126
|
+
// return await super.runHandle()
|
|
127
|
+
// }
|
|
128
|
+
// // const sid = this.cache?._conv.sid
|
|
129
|
+
// // if (sid != null && sid !== this.session.sessionId) {
|
|
130
|
+
// // this.triggers.refreshAll()
|
|
131
|
+
// // }
|
|
132
|
+
// return await super.runHandle()
|
|
133
|
+
// }
|
|
134
|
+
async runAfter() {
|
|
135
|
+
console.log('AFTER', {
|
|
136
|
+
name: this.constructor.name,
|
|
137
|
+
thread: this.thread.id,
|
|
138
|
+
...this.cache?._conv
|
|
139
|
+
});
|
|
140
|
+
// if (this.thread.ending || this.state.name === 'onConvEnd') {
|
|
141
|
+
// return await super.runAfter()
|
|
142
|
+
// }
|
|
143
|
+
// if (!await this.hasConversation()) return await super.runAfter()
|
|
144
|
+
// if (this.thread.hasControlAction()) {
|
|
145
|
+
// // await this.popConvStep()
|
|
146
|
+
// if (await this.popConvStep()) {
|
|
147
|
+
// // TODO: this seems not to be necessary now or not?
|
|
148
|
+
// await this.sendEventToStep({ toGlobal: this.isGlobal, action: 'onAwake' })
|
|
149
|
+
// }
|
|
150
|
+
// }
|
|
151
|
+
// if (this.isGlobal && !this.event.processed) {
|
|
152
|
+
// await this.sendEventToStep({ toGlobal: false, event: { ...this.event, processed: undefined, action: 'lcl' } })
|
|
153
|
+
// }
|
|
154
|
+
await super.runAfter();
|
|
109
155
|
}
|
|
110
156
|
// public async setLocalTriggers (): Promise<void> {
|
|
111
157
|
// if (!this.isGlobal && await this.hasActiveGlobal()) {
|
|
@@ -132,15 +178,15 @@ class ConvStep extends step_1.default {
|
|
|
132
178
|
delete this.state.prevSkipName;
|
|
133
179
|
}
|
|
134
180
|
async cancel() {
|
|
135
|
-
if (this.
|
|
181
|
+
if (this.isWorker) {
|
|
136
182
|
this.log.debug('conv.cannot cancel global');
|
|
137
|
-
return
|
|
183
|
+
// return
|
|
138
184
|
}
|
|
139
|
-
const activeStep = await this.activeStep()
|
|
140
|
-
await this.sendEventToStep({ event: { name: '_conv', action: 'onCancel', params: { byStep: this.step.label } }, toStep: activeStep })
|
|
185
|
+
// const activeStep = await this.activeStep(this.isWorker)
|
|
186
|
+
// await this.sendEventToStep({ event: { name: '_conv', action: 'onCancel', params: { byStep: this.step.label } }, toStep: activeStep })
|
|
141
187
|
}
|
|
142
188
|
async onCancel() {
|
|
143
|
-
await this.popConvStep()
|
|
189
|
+
// await this.popConvStep()
|
|
144
190
|
if (this.getExitStepId('cancel')) {
|
|
145
191
|
this.log.debug('conv.cancel exit');
|
|
146
192
|
this.exitStep('cancel');
|
|
@@ -156,7 +202,7 @@ class ConvStep extends step_1.default {
|
|
|
156
202
|
this.state.name = this.state.resumeState;
|
|
157
203
|
this.state.resumeState = undefined;
|
|
158
204
|
const conv = await this.getConversation();
|
|
159
|
-
if (this.
|
|
205
|
+
if (this.isWorker && conv.glb.length === 1) {
|
|
160
206
|
this.log.debug('make global thread foreground');
|
|
161
207
|
this.thread.background = false;
|
|
162
208
|
}
|
|
@@ -172,20 +218,21 @@ class ConvStep extends step_1.default {
|
|
|
172
218
|
async notifyConvEnd({ onlyLocal } = {}) {
|
|
173
219
|
const conv = await this.getConversation();
|
|
174
220
|
const lcl = conv.lcl.splice(0);
|
|
175
|
-
const
|
|
176
|
-
if (lcl.length > 0 ||
|
|
221
|
+
const wrk = onlyLocal ? [] : conv.glb.splice(0);
|
|
222
|
+
if (lcl.length > 0 || wrk.length > 0) {
|
|
177
223
|
await this.updateData();
|
|
178
|
-
for (const step of lcl) {
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
for (const step of
|
|
182
|
-
|
|
183
|
-
}
|
|
224
|
+
// for (const step of lcl) {
|
|
225
|
+
// await this.sendEventToStep({ toStep: step, action: 'onConvEnd' })
|
|
226
|
+
// }
|
|
227
|
+
// for (const step of wrk) {
|
|
228
|
+
// await this.sendEventToStep({ toStep: step, action: 'onConvEnd' })
|
|
229
|
+
// }
|
|
184
230
|
}
|
|
185
231
|
}
|
|
186
232
|
async waitConvEnd() {
|
|
187
|
-
const
|
|
188
|
-
|
|
233
|
+
const workerThread = this.process.getThread(this.workerThreadId);
|
|
234
|
+
const workerData = await workerThread?.currentStep.resolveDataIn();
|
|
235
|
+
if (!this.isGlobal && this.thread.id !== 'main' && this.thread.id === workerData?.conversationThread) {
|
|
189
236
|
this.log.debug('conv.wait for end', this.conversation);
|
|
190
237
|
this.gotoState({ ...this.state, name: 'waitGlobEnd', direct: true });
|
|
191
238
|
}
|
|
@@ -195,7 +242,7 @@ class ConvStep extends step_1.default {
|
|
|
195
242
|
}
|
|
196
243
|
}
|
|
197
244
|
async waitGlobEnd() {
|
|
198
|
-
const gcThreadId = this.
|
|
245
|
+
const gcThreadId = this.workerThreadId;
|
|
199
246
|
// wait for glob thread end (if exists)
|
|
200
247
|
this.triggers.hook({ name: 'end', thread: gcThreadId }, async () => await this.onConvEnd());
|
|
201
248
|
if (!this.process.getThread(gcThreadId))
|
|
@@ -218,7 +265,7 @@ class ConvStep extends step_1.default {
|
|
|
218
265
|
}
|
|
219
266
|
async resume() {
|
|
220
267
|
// const conv = await this._getConversation()
|
|
221
|
-
// if (conv.stk.length
|
|
268
|
+
// if (conv.stk.length> 0) {
|
|
222
269
|
// conv.lcl.unshift(...(conv.stk.pop() ?? [])) // restore que from stk
|
|
223
270
|
// await this.updateData()
|
|
224
271
|
// await this.sendEventToStep({ toGlobal: false, action: 'onResume' })
|
|
@@ -226,66 +273,96 @@ class ConvStep extends step_1.default {
|
|
|
226
273
|
// this.log.debug('conv.nothing to resume')
|
|
227
274
|
// }
|
|
228
275
|
}
|
|
229
|
-
async sendEventToStep({
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
276
|
+
// protected async sendEventToStep ({
|
|
277
|
+
// toGlobal = false,
|
|
278
|
+
// toStep,
|
|
279
|
+
// action,
|
|
280
|
+
// event = { name: '_conv', action }
|
|
281
|
+
// }: {
|
|
282
|
+
// action?: string
|
|
283
|
+
// event?: IEvent
|
|
284
|
+
// toStep?: IConversationStep
|
|
285
|
+
// toGlobal?: boolean
|
|
286
|
+
// }): Promise<IStepResult | undefined> {
|
|
287
|
+
// toStep ||= await this.activeStep(toGlobal)
|
|
288
|
+
// if (toStep != null) {
|
|
289
|
+
// const target = { type: 'session' as any, name: toStep.key, id: toStep.trd }
|
|
290
|
+
// return await this.thread.eventManager.emit(
|
|
291
|
+
// event,
|
|
292
|
+
// { invocationType: 'async', target }
|
|
293
|
+
// )
|
|
294
|
+
// }
|
|
295
|
+
// return undefined
|
|
296
|
+
// }
|
|
297
|
+
// async activeStep (toGlobal: boolean): Promise<IConversationStep | undefined> {
|
|
298
|
+
// const conv = await this.getConversation()
|
|
299
|
+
// const que = toGlobal ? conv.glb : conv.lcl
|
|
300
|
+
// if (que == null) return
|
|
301
|
+
// const lastItem = que[que.length - 1]
|
|
302
|
+
// if (toGlobal && lastItem?.typ === ConvThreadType.wrk) return undefined
|
|
303
|
+
// return que[que.length - 1]
|
|
304
|
+
// }
|
|
241
305
|
/** @returns true if current conv is active */
|
|
242
|
-
async pushConvStep() {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
306
|
+
// protected async pushConvStep (): Promise<boolean> {
|
|
307
|
+
// const conv = await this.getConversation()
|
|
308
|
+
// const sessionKey = this.session.key
|
|
309
|
+
// if (sessionKey == null) throw new Error('session is required')
|
|
310
|
+
// const que = this.isWorker ? conv.glb : conv.lcl
|
|
311
|
+
// const lastItem = que[que.length - 1]
|
|
312
|
+
// const lastItemType = lastItem?.typ
|
|
313
|
+
// if (lastItemType === ConvThreadType.wrk) {
|
|
314
|
+
// console.log('POP', lastItem)
|
|
315
|
+
// que.pop() // remove last item, since it's temporary
|
|
316
|
+
// // TODO triggers.refreshAll!
|
|
317
|
+
// }
|
|
318
|
+
// const queIndex = que.findIndex(stp => stp.key === sessionKey && this.thread.id === stp.trd)
|
|
319
|
+
// if (queIndex < 0) {
|
|
320
|
+
// if (que.length > 0) {
|
|
321
|
+
// await this.sendEventToStep({ toGlobal: this.isGlobal, event: { name: '_conv', action: 'onPause', params: { byStep: this.step.label } } })
|
|
322
|
+
// }
|
|
323
|
+
// const type = this.threadType === ConvThreadType.wrk ? this.threadType : undefined
|
|
324
|
+
// que.push({ key: sessionKey, trd: this.thread.id, typ: type, name: this.constructor.name, label: this.label, step: this.id })
|
|
325
|
+
// console.log('PUSH', que[que.length - 1])
|
|
326
|
+
// await this.updateData()
|
|
327
|
+
// return true
|
|
328
|
+
// }
|
|
329
|
+
// // refresh data on step change
|
|
330
|
+
// que[queIndex].name = this.constructor.name
|
|
331
|
+
// que[queIndex].label = this.label
|
|
332
|
+
// que[queIndex].step = this.id
|
|
333
|
+
// return queIndex === que.length - 1
|
|
334
|
+
// }
|
|
257
335
|
/** @returns true if current conv was active */
|
|
258
|
-
async popConvStep(popStep) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}
|
|
336
|
+
// protected async popConvStep (popStep?: IConversationStep): Promise<boolean> {
|
|
337
|
+
// const conv = await this.getConversation()
|
|
338
|
+
// const sessionKey = this.session.key
|
|
339
|
+
// if (sessionKey == null) throw new Error('session is required')
|
|
340
|
+
// popStep ||= { key: sessionKey, trd: this.thread.id }
|
|
341
|
+
// const que = this.isWorker ? conv.glb : conv.lcl
|
|
342
|
+
// const queIndex = que.findIndex(stp => stp.key === popStep?.key && stp.trd === popStep.trd)
|
|
343
|
+
// if (queIndex >= 0) {
|
|
344
|
+
// // console.log('SPLICE1', this.thread.id, this.step.label, que)
|
|
345
|
+
// que.splice(queIndex, 1)
|
|
346
|
+
// // conv.sid = this.session.sessionId
|
|
347
|
+
// await this.updateData()
|
|
348
|
+
// return queIndex === que.length
|
|
349
|
+
// }
|
|
350
|
+
// // let updated = false
|
|
351
|
+
// // conv.stk.forEach((steps, stepsIdx) => {
|
|
352
|
+
// // const stpIdx = steps.findIndex(stp => stp.key === sessionKey && this.thread.id === stp.thread)
|
|
353
|
+
// // if (stpIdx>= 0) {
|
|
354
|
+
// // if (steps.length> 1) steps.splice(stpIdx, 1)
|
|
355
|
+
// // else conv.stk.splice(stepsIdx, 1)
|
|
356
|
+
// // updated = true
|
|
357
|
+
// // }
|
|
358
|
+
// // })
|
|
359
|
+
// // if (updated) await this.updateData()
|
|
360
|
+
// return false
|
|
361
|
+
// }
|
|
285
362
|
async startConversation(data, { thread: _thread } = {}) {
|
|
286
363
|
this.convDataCache = {
|
|
287
364
|
...data,
|
|
288
|
-
_conv: {
|
|
365
|
+
_conv: data._conv ?? {
|
|
289
366
|
glb: [],
|
|
290
367
|
lcl: []
|
|
291
368
|
}
|
package/dst/voice.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ICallback, IVoiceReporterTranscriptEventArgs, IPromtpSection } from '@onereach/flow-sdk/dst/types';
|
|
2
|
-
import ConvStep from './step';
|
|
2
|
+
import ConvStep, { IConversationData } from './step';
|
|
3
3
|
import BasicError from '@onereach/flow-sdk/dst/errors/base';
|
|
4
4
|
export type TODO = any;
|
|
5
5
|
export interface SensitiveData {
|
|
@@ -7,7 +7,7 @@ export interface SensitiveData {
|
|
|
7
7
|
muteUser: boolean;
|
|
8
8
|
muteBot: boolean;
|
|
9
9
|
}
|
|
10
|
-
export interface IVoiceCall {
|
|
10
|
+
export interface IVoiceCall extends IConversationData {
|
|
11
11
|
vv: number;
|
|
12
12
|
id: string;
|
|
13
13
|
ended: boolean;
|
|
@@ -44,6 +44,7 @@ export interface CallStartEvent extends VoiceEvent {
|
|
|
44
44
|
export default class VoiceStep<TIn = unknown, TOut = unknown, TParams extends VoiceEvent = VoiceEvent> extends ConvStep<IVoiceCall, TIn & {
|
|
45
45
|
handleCancel?: boolean;
|
|
46
46
|
}, TOut, TParams> {
|
|
47
|
+
_worker(call: IVoiceCall): Promise<void>;
|
|
47
48
|
runBefore(): Promise<void>;
|
|
48
49
|
sendCommands({ id, type, callback }: IVoiceCall, commands: TODO[]): Promise<void>;
|
|
49
50
|
handleHeartbeat(call: IVoiceCall): Promise<void>;
|
package/dst/voice.js
CHANGED
|
@@ -13,17 +13,27 @@ 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
|
+
async _worker(call) {
|
|
17
|
+
this.triggers.once(`in/voice/${call.id}/event`, async (event) => {
|
|
18
|
+
console.log('EVENT', {
|
|
19
|
+
name: this.constructor.name,
|
|
20
|
+
thread: this.thread.id,
|
|
21
|
+
event
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
16
25
|
async runBefore() {
|
|
17
26
|
await super.runBefore();
|
|
18
27
|
if (this.cache != null) {
|
|
19
|
-
if (!this.event.processed &&
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
28
|
+
// if (!this.event.processed && this.event.action == null) {
|
|
29
|
+
// const toWorker = this.event.params.global
|
|
30
|
+
// const hasHandler = await this.sendEventToStep({ event: { ...this.event, action: toWorker ? 'wrk' : 'lcl' }, toWorker }) // redirect to global (1)
|
|
31
|
+
// if (hasHandler != null) {
|
|
32
|
+
// this.log.debug('hasWorker', { hasGlobal: hasHandler })
|
|
33
|
+
// this.state.prevSkipName = this.state.name
|
|
34
|
+
// this.state.name = 'onSkipEvent'
|
|
35
|
+
// }
|
|
36
|
+
// }
|
|
27
37
|
await this.handleHeartbeat(this.cache);
|
|
28
38
|
}
|
|
29
39
|
}
|
|
@@ -35,10 +45,11 @@ class VoiceStep extends step_1.default {
|
|
|
35
45
|
name: `out/voice/${type}`,
|
|
36
46
|
params: {
|
|
37
47
|
id,
|
|
38
|
-
cancel: this.
|
|
39
|
-
async: this.
|
|
48
|
+
cancel: this.isWorker ? undefined : true,
|
|
49
|
+
async: this.isWorker ? true : undefined,
|
|
40
50
|
hbs: 99,
|
|
41
|
-
commands
|
|
51
|
+
commands,
|
|
52
|
+
step: { key: this.session.key, trd: this.isGlobal ? this.workerThreadId : this.thread.id } // response should be sent to this session
|
|
42
53
|
},
|
|
43
54
|
reporting: this.session.getSessionRef()
|
|
44
55
|
}, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onereach/step-voice",
|
|
3
|
-
"version": "5.0.9-fixsubflow.
|
|
3
|
+
"version": "5.0.9-fixsubflow.3",
|
|
4
4
|
"author": "Roman Zolotarov <roman.zolotarov@onereach.com>",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Roman Zolotarov",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"uuid": "^9.0.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@onereach/flow-sdk": "^3.2.
|
|
22
|
+
"@onereach/flow-sdk": "^3.2.16",
|
|
23
23
|
"@onereach/step-voice": "./test",
|
|
24
24
|
"@swc/cli": "^0.1.62",
|
|
25
25
|
"@swc/core": "^1.3.57",
|