@onereach/step-generate-call-telemetry 0.0.2-rc.6 → 0.0.2-rc.8
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/dist/index.d.mts +78 -50
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -22,28 +22,59 @@ declare class BaseStep<T extends BaseConfig> extends Step<T> {
|
|
|
22
22
|
}>;
|
|
23
23
|
}
|
|
24
24
|
//#endregion
|
|
25
|
-
//#region src/threads/main/types.d.ts
|
|
26
|
-
interface GenerateCallTelemetryConfig extends CONFIG {
|
|
27
|
-
dataIn: DataIn;
|
|
28
|
-
}
|
|
29
|
-
//#endregion
|
|
30
25
|
//#region src/threads/events-aggregator/constants.d.ts
|
|
31
26
|
declare const eventsAggregatorClassId = "evt_aggr";
|
|
32
27
|
declare const eventsAggregatorEvents: {
|
|
33
28
|
readonly refreshTurnContext: "aggr_ctx_rsh";
|
|
34
29
|
};
|
|
35
30
|
//#endregion
|
|
36
|
-
//#region src/threads/events-aggregator/services/
|
|
37
|
-
type
|
|
38
|
-
type
|
|
39
|
-
turnId:
|
|
31
|
+
//#region src/threads/events-aggregator/services/turns-manager/types.d.ts
|
|
32
|
+
type TurnsManagerTurnId = string;
|
|
33
|
+
type TurnsManagerContext = {
|
|
34
|
+
turnId: TurnsManagerTurnId;
|
|
40
35
|
turnIndex: number;
|
|
41
36
|
};
|
|
42
|
-
type
|
|
43
|
-
|
|
44
|
-
turnsContextMap: Record<
|
|
37
|
+
type TurnsManagerState = {
|
|
38
|
+
turn: TurnsManagerContext;
|
|
39
|
+
turnsContextMap: Record<TurnsManagerTurnId, TurnsManagerContext>;
|
|
45
40
|
};
|
|
46
41
|
//#endregion
|
|
42
|
+
//#region src/threads/events-aggregator/services/voice/types.d.ts
|
|
43
|
+
type ConversationParameters = {
|
|
44
|
+
conversation: string;
|
|
45
|
+
conversationThread: IThreadId;
|
|
46
|
+
};
|
|
47
|
+
type ConversationData = {
|
|
48
|
+
id: string;
|
|
49
|
+
type: string;
|
|
50
|
+
callback: ICallback;
|
|
51
|
+
_conv: Record<string, unknown>;
|
|
52
|
+
};
|
|
53
|
+
type VoiceServiceState = {
|
|
54
|
+
conversation?: ConversationData;
|
|
55
|
+
};
|
|
56
|
+
type VoiceEventParameters = {
|
|
57
|
+
type?: string;
|
|
58
|
+
[key: string]: unknown;
|
|
59
|
+
timestamp?: number;
|
|
60
|
+
ttsContext?: TurnsManagerContext;
|
|
61
|
+
ttsProvider?: string;
|
|
62
|
+
partialText?: string;
|
|
63
|
+
ttsUsageMeta?: Record<string, unknown>;
|
|
64
|
+
inputId?: string;
|
|
65
|
+
confidenceScore?: number;
|
|
66
|
+
phrase?: {
|
|
67
|
+
text?: string;
|
|
68
|
+
};
|
|
69
|
+
asrProvider?: string;
|
|
70
|
+
asrUsageMeta?: {
|
|
71
|
+
provider?: string;
|
|
72
|
+
modelId?: string;
|
|
73
|
+
languageCode?: string;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
type VoiceEvent = IEvent<VoiceEventParameters, `in/voice/${string}`>;
|
|
77
|
+
//#endregion
|
|
47
78
|
//#region src/threads/events-aggregator/services/turns-aggregator/types.d.ts
|
|
48
79
|
type VoiceTurn = {
|
|
49
80
|
id: string;
|
|
@@ -85,63 +116,60 @@ type TurnsAggregatorState = {
|
|
|
85
116
|
type EventsAggregatorEventName = typeof eventsAggregatorEvents;
|
|
86
117
|
type EventsAggregatorEventRefreshContext = IEvent<unknown, EventsAggregatorEventName['refreshTurnContext']>;
|
|
87
118
|
type EventsAggregatorEvent = EventsAggregatorEventRefreshContext;
|
|
88
|
-
type VoiceEventParameters = {
|
|
89
|
-
type?: string;
|
|
90
|
-
[key: string]: unknown;
|
|
91
|
-
timestamp?: number;
|
|
92
|
-
ttsContext?: ContextManagerContext;
|
|
93
|
-
ttsProvider?: string;
|
|
94
|
-
partialText?: string;
|
|
95
|
-
ttsUsageMeta?: Record<string, unknown>;
|
|
96
|
-
inputId?: string;
|
|
97
|
-
confidenceScore?: number;
|
|
98
|
-
phrase?: {
|
|
99
|
-
text?: string;
|
|
100
|
-
};
|
|
101
|
-
asrProvider?: string;
|
|
102
|
-
asrUsageMeta?: {
|
|
103
|
-
provider?: string;
|
|
104
|
-
modelId?: string;
|
|
105
|
-
languageCode?: string;
|
|
106
|
-
};
|
|
107
|
-
};
|
|
108
|
-
type VoiceEvent = IEvent<VoiceEventParameters, `in/voice/${string}`>;
|
|
109
|
-
type VoiceConversation = {
|
|
110
|
-
id: string;
|
|
111
|
-
type: string;
|
|
112
|
-
callback: ICallback;
|
|
113
|
-
};
|
|
114
119
|
type EventsAggregatorState = {
|
|
115
120
|
class: typeof eventsAggregatorClassId;
|
|
116
121
|
parentThreadId: IThreadId;
|
|
117
|
-
|
|
118
|
-
} & ContextManagerState & TurnsAggregatorState;
|
|
122
|
+
} & VoiceServiceState & TurnsManagerState & TurnsAggregatorState;
|
|
119
123
|
interface EventsAggregatorConfig extends BaseConfig {
|
|
120
124
|
state: EventsAggregatorState;
|
|
121
125
|
events: EventsAggregatorEvent;
|
|
122
126
|
}
|
|
123
127
|
//#endregion
|
|
128
|
+
//#region src/threads/main/constants.d.ts
|
|
129
|
+
declare const mainEvents: {
|
|
130
|
+
readonly telemetryActivated: "main_tel_act";
|
|
131
|
+
};
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/threads/main/types.d.ts
|
|
134
|
+
type MainEventName = typeof mainEvents;
|
|
135
|
+
type MainEventTelemetryActivated = IEvent<{
|
|
136
|
+
turn: TurnsManagerContext;
|
|
137
|
+
}, MainEventName['telemetryActivated']>;
|
|
138
|
+
type MainEvent = MainEventTelemetryActivated;
|
|
139
|
+
type MainDataOut = {
|
|
140
|
+
turn: TurnsManagerContext;
|
|
141
|
+
};
|
|
142
|
+
type MainState = {
|
|
143
|
+
activationStart: number;
|
|
144
|
+
};
|
|
145
|
+
interface GenerateCallTelemetryConfig extends CONFIG {
|
|
146
|
+
dataIn: DataIn;
|
|
147
|
+
state: MainState;
|
|
148
|
+
events: MainEvent;
|
|
149
|
+
dataOut: MainDataOut;
|
|
150
|
+
}
|
|
151
|
+
//#endregion
|
|
124
152
|
//#region src/threads/events-aggregator/events-aggregator.d.ts
|
|
125
153
|
declare class EventsAggregator extends BaseStep<EventsAggregatorConfig> {
|
|
126
154
|
static readonly class = "evt_aggr";
|
|
127
|
-
static start(thread: IThread<GenerateCallTelemetryConfig
|
|
155
|
+
static start(thread: IThread<GenerateCallTelemetryConfig>): Promise<void>;
|
|
128
156
|
static getThreadId(stepId: IStepId): IThreadId;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
runStep(): void;
|
|
157
|
+
runStep(): Promise<void>;
|
|
158
|
+
onVoiceEvent(event: VoiceEvent): void;
|
|
132
159
|
initialize(): Promise<void>;
|
|
160
|
+
onDeadline(): void;
|
|
133
161
|
onRefreshTurnContext(): Promise<void>;
|
|
134
|
-
private
|
|
162
|
+
private resumeParentThread;
|
|
163
|
+
private get voiceService();
|
|
164
|
+
private get turnsManagerService();
|
|
165
|
+
private get turnsAggregatorService();
|
|
135
166
|
}
|
|
136
167
|
//#endregion
|
|
137
168
|
//#region src/threads/main/step.d.ts
|
|
138
169
|
declare class GenerateCallTelemetryStep extends BaseStep<GenerateCallTelemetryConfig> {
|
|
139
170
|
runStep(): Promise<void>;
|
|
140
171
|
initialize(): Promise<void>;
|
|
141
|
-
|
|
142
|
-
context: unknown;
|
|
143
|
-
}, `ack`>): void;
|
|
144
|
-
private get conversationContext();
|
|
172
|
+
onTelemetryActivated(event: MainEventTelemetryActivated): void;
|
|
145
173
|
}
|
|
146
174
|
//#endregion
|
|
147
175
|
//#region src/index.d.ts
|
|
@@ -149,5 +177,5 @@ declare const states: {
|
|
|
149
177
|
evt_aggr: typeof EventsAggregator;
|
|
150
178
|
};
|
|
151
179
|
//#endregion
|
|
152
|
-
export { BaseConfig,
|
|
180
|
+
export { BaseConfig, ConversationData, ConversationParameters, DataIn, EventsAggregatorConfig, EventsAggregatorEvent, EventsAggregatorEventName, EventsAggregatorEventRefreshContext, EventsAggregatorState, GenerateCallTelemetryConfig, MainDataOut, MainEvent, MainEventName, MainEventTelemetryActivated, MainState, TurnsAggregatorState, TurnsManagerContext, TurnsManagerState, TurnsManagerTurnId, VoiceEvent, VoiceEventParameters, VoiceServiceState, VoiceTurn, dataInSchema, states, GenerateCallTelemetryStep as step };
|
|
153
181
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/schemas/data-in.ts","../src/threads/base/types.ts","../src/threads/base/base.ts","../src/threads/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/schemas/data-in.ts","../src/threads/base/types.ts","../src/threads/base/base.ts","../src/threads/events-aggregator/constants.ts","../src/threads/events-aggregator/services/turns-manager/types.ts","../src/threads/events-aggregator/services/voice/types.ts","../src/threads/events-aggregator/services/turns-aggregator/types.ts","../src/threads/events-aggregator/types.ts","../src/threads/main/constants.ts","../src/threads/main/types.ts","../src/threads/events-aggregator/events-aggregator.ts","../src/threads/main/step.ts","../src/index.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";import{install as t}from"source-map-support";import{Memoize as n}from"typescript-memoize";import{ACTION as r}from"@onereach/flow-sdk/types/index.js";import i from"@onereach/flow-sdk/errors/timeout.js";import{z as a}from"zod/v4-mini";import o from"@onereach/flow-sdk/errors/base.js";import s from"@onereach/flow-sdk/step.js";import*as c from"zod/mini";import{BasicThreadService as l}from"@onereach/flow-sdk/services/basic.js";import u from"node:crypto";import{readFile as d}from"node:fs/promises";const f={UNKNOWN:`UNKNOWN`,STEP_LOGIC_ISSUE:`STEP_LOGIC_ISSUE`,AUTH:`AUTH`,TIMEOUT:`TIMEOUT`,VALIDATION:`VALIDATION`,INVALID_REQUEST:`INVALID_REQUEST`,RATE_LIMITED:`RATE_LIMITED`,SERVER_ERROR:`SERVER_ERROR`,UNSUPPORTED:`UNSUPPORTED`};var p=class extends o{};const m=[p,i];function h(e,t={}){let{preserveErrors:n=m,unknownMessage:r=`Unknown error`,unknownCode:o=f.UNKNOWN}=t;if(n?.some(t=>e instanceof t))return e;if(e instanceof a.core.$ZodError)return new p(a.prettifyError(e),e,{code:f.VALIDATION});if(typeof e==`string`)return new p(e,{code:f.UNKNOWN});if(e instanceof Error){if(e.message.includes(`Request timed out`))return new i(`Timeout`,e,{code:f.TIMEOUT});let t=e?.response?.data?.error?.message;return t==null?new p(r,e,{code:o}):new p(t,e,{code:f.SERVER_ERROR})}return new p(r,{code:o,data:e})}function g(e,t){function n(t,n,r,i){let a=e(t,n,r,i);if(typeof a==`function`){let e=i.value,t=a;if(e?.name!=null)try{Object.defineProperty(t,`name`,{value:e.name})}catch{}return i.value=t,i}return a??i}return function(e,r,i){if(typeof e==`object`&&e&&(typeof r==`string`||typeof r==`symbol`)&&typeof i==`object`&&i)return n(t,e,r,i);{let r=e??t;return(e,t,i)=>n(r,e,t,i)}}}const _=g((e,t,n,r)=>{let i=r.value;if(!(!i||typeof i!=`function`))return function(...t){try{let r=i.apply(this,t);return r instanceof Promise?r.catch(t=>v.call(this,e,t,n)):r}catch(t){return v.call(this,e,t,n)}}},{allowHandleError:!1,useErrorFilter:!0});function v(e,t,n){let i=n.toString();this.log.DEBUG?.(`Error in method '${i}'`,t);let a=e.useErrorFilter?h(t):t;if(a instanceof Error)if(e.allowHandleError){this.thread.enqueue({name:r.error,error:a});return}else{this.end(a);return}throw a}const y=g((e,t,n,r)=>{let i=r.value;if(!(!i||typeof i!=`function`))return function(...e){try{let t=i.apply(this,e);return t instanceof Promise?t.catch(e=>{let t=n.toString();throw this.log.DEBUG?.(`Error in method '${t}'`,e),h(e)}):t}catch(e){let t=n.toString();throw this.log.DEBUG?.(`Error in method '${t}'`,e),h(e)}}},{});c.config(c.locales.en());const b=c.string().check(c.trim(),c.refine(e=>![`undefined`,`null`].includes(e),{error:`Unexpected undefined or null merge-field value`})),x=c.object({conversation:b.check(c.minLength(1)),conversationThread:b});function S(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function C(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}var w=class extends s{async resolveDataIn(){let e=await super.resolveDataIn();return x.parse(e)}};C([y,S(`design:type`,Function),S(`design:paramtypes`,[]),S(`design:returntype`,Promise)],w.prototype,`resolveDataIn`,null);const T={refreshTurnContext:`aggr_ctx_rsh`};var E=class extends l{static get statePlaceholder(){return{context:{turnId:``,turnIndex:-1},turnsContextMap:{}}}async initializeTurnContext(){if(this.thread.state.context.turnId!==``){this.thread.log.WARN?.(`Turn context already initialized. Skipping initialization.`);return}this.thread.log.DEBUG?.(`Initializing turn context`),this.updateTurnContext(),await this.refreshStepDataOut()}async refreshTurnContext(){if(this.thread.state.context.turnId===``){this.thread.log.WARN?.(`Turn context was not initialized. Initializing new turn context.`),await this.initializeTurnContext();return}this.thread.log.DEBUG?.(`Refreshing turn context`),this.updateTurnContext(),await this.refreshStepDataOut()}updateTurnContext(){let e=crypto.randomUUID(),t={turnId:e,turnIndex:(this.thread.state.context.turnIndex??-1)+1};this.thread.state.context=t,this.thread.state.turnsContextMap[e]=t}async refreshStepDataOut(){await this.thread.setDataOut({context:this.thread.state.context})}},D=class extends l{static get statePlaceholder(){return{rawEvents:[],turns:[]}}constructor(e){super(e)}addEvent(e){this.thread.state.rawEvents.push(e);let t=this.thread.state.turns.findLast(t=>e.params.type?.startsWith?.(`asr-input/`)&&t.asrInputId===e.params?.inputId||e.params.type?.startsWith?.(`tts-audio/`)&&t.ttsContext?.turnId===e.params?.ttsContext?.turnId||e.params.type===`tts-audio/started`&&t.ttsStartedTimestamp==null);if(t==null){this.thread.state.turns.length===0&&e.params.type!==`asr-input/started`&&console.warn(`Turn started without ASR input started event`,e);let n=e.params?.inputId??e.params?.ttsContext?.turnId??u.randomUUID(),r=e.params.timestamp??Date.now();this.thread.state.turns.some(e=>e.id===n)&&(console.warn(`Turn already exists`,{id:n,event:e}),n=u.randomUUID()),t={id:n,finished:!1,startTimestamp:r,endTimestamp:void 0,asrInputId:void 0,asrStartedTimestamp:void 0,asrEndedTimestamp:void 0,asrProcessedTimestamp:void 0,asrConfidenceScore:void 0,asrRecognitionText:void 0,asrProvider:void 0,asrUsageMeta:void 0,ttsStartedTimestamp:void 0,ttsEndedTimestamp:void 0,ttsEndedReason:void 0,ttsInterruptedAfterText:void 0,ttsProvider:void 0,ttsContext:void 0},this.thread.state.turns.push(t)}switch(e.params.type){case`asr-input/started`:t.asrInputId&&t.asrInputId!==e.params.inputId&&(console.warn(`ASR input started for wrong input`,{expected:t.asrInputId,actual:e.params.inputId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`asr-input-started-for-wrong-input`)),t.asrInputId=e.params.inputId,t.asrStartedTimestamp=e.params.timestamp;break;case`asr-input/ended`:t.asrInputId&&t.asrInputId!==e.params.inputId&&(console.warn(`ASR input ended for wrong input`,{expected:t.asrInputId,actual:e.params.inputId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`asr-input-ended-for-wrong-input`)),t.asrEndedTimestamp=e.params.timestamp;break;case`asr-input/processed`:t.asrInputId!==e.params.inputId&&(console.warn(`ASR input processed for wrong input`,{expected:t.asrInputId,actual:e.params.inputId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`asr-input-processed-for-wrong-input`)),t.asrProcessedTimestamp=e.params.timestamp,t.asrConfidenceScore=e.params.confidenceScore,t.asrRecognitionText=e.params.phrase?.text,t.asrProvider=e.params.asrProvider,t.asrUsageMeta=e.params.asrUsageMeta;break;case`tts-audio/started`:t.ttsContext?.turnId&&t.ttsContext?.turnId!==e.params.ttsContext?.turnId&&(console.warn(`TTS audio started for wrong turn id`,{expected:t.ttsContext?.turnId,actual:e.params.ttsContext?.turnId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`tts-audio-started-for-wrong-message`)),t.ttsProvider=e.params.ttsProvider,t.ttsContext=e.params.ttsContext,t.ttsStartedTimestamp=e.params.timestamp;break;case`tts-audio/interrupted`:t.ttsContext?.turnId&&t.ttsContext?.turnId!==e.params.ttsContext?.turnId&&(console.warn(`TTS audio interrupted for wrong turn id`,{expected:e.params.ttsContext?.turnId,actual:e.params.ttsContext?.turnId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`tts-audio-interrupted-for-wrong-message`)),t.ttsInterruptedAfterText=e.params.partialText,t.ttsEndedReason=`interrupted`,t.ttsEndedTimestamp=e.params.timestamp,t.endTimestamp=e.params.timestamp,t.finished=!0;break;case`tts-audio/ended`:t.ttsContext?.turnId&&t.ttsContext?.turnId!==e.params.ttsContext?.turnId&&(console.warn(`TTS audio interrupted for wrong turn id`,{expected:e.params.ttsContext?.turnId,actual:e.params.ttsContext?.turnId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`tts-audio-ended-for-wrong-message`)),t.ttsEndedReason=`ended`,t.ttsEndedTimestamp=e.params.timestamp,t.endTimestamp=e.params.timestamp,t.finished=!0;break;default:console.warn(`Unknown event type`,e)}}},O,k=class extends w{static class=`evt_aggr`;static async start(e,t){if(!t)throw Error(`Voice conversation data is missing`);let n=this.getThreadId(e.step.id);e.process.getThread(n)??await e.process.runThread({id:n,background:!0,state:{...E.statePlaceholder,...D.statePlaceholder,step:e.step.id,class:this.class,parentThreadId:e.id,voiceConversation:t}})}static getThreadId(e){return`vce_otel_${this.class}_${e}`}async onVoiceEvent(e){switch(this.log.WARN?.(`>>>VOICE event`,e),this.log.DEBUG?.(`onAcknowledge event`,e),e.params.type){case`ack`:await this.process.enqueueAndRun({name:`ack`,params:{context:this.state.context},thread:this.state.parentThreadId});break;case`hangup`:break;default:}}async startTelemetry(){let{id:e,type:t,callback:n}=this.state.voiceConversation,r={target:this.helpers.providersAccountId,name:`out/voice/${t}`,params:{id:e,async:!0,commands:[{name:`start-telemetry`,params:{ack:!0}}],step:{key:this.session.key,trd:this.thread.id}},reporting:{...this.session.getSessionRef()}},i=performance.now();this.log.DEBUG?.(`startTelemetry event`,r);let a=await this.thread.eventManager.emit(r,{target:n,invocationType:`async`,timeout:5e3});if(this.log.DEBUG?.(`startTelemetry result`,{result:a,delay:performance.now()-i}),a==null)throw new p(`Failed to start telemetry`,{code:f.SERVER_ERROR,data:r})}runStep(){this.triggers.local(`in/voice/${this.state.voiceConversation.id}`,this.onVoiceEvent),this.triggers.local(T.refreshTurnContext,this.onRefreshTurnContext),this.triggers.otherwise(this.initialize)}async initialize(){this.log.DEBUG?.(`Initializing EventsAggregator thread`),await this.contextManagerService.initializeTurnContext(),await this.startTelemetry()}async onRefreshTurnContext(){await this.contextManagerService.refreshTurnContext()}get contextManagerService(){return new E(this.thread)}};C([_,S(`design:type`,Function),S(`design:paramtypes`,[Object]),S(`design:returntype`,Promise)],k.prototype,`onVoiceEvent`,null),C([_,S(`design:type`,Function),S(`design:paramtypes`,[]),S(`design:returntype`,void 0)],k.prototype,`runStep`,null),C([_,S(`design:type`,Function),S(`design:paramtypes`,[]),S(`design:returntype`,Promise)],k.prototype,`initialize`,null),C([_,S(`design:type`,Function),S(`design:paramtypes`,[]),S(`design:returntype`,Promise)],k.prototype,`onRefreshTurnContext`,null),C([n(),S(`design:type`,typeof(O=E!==void 0&&E)==`function`?O:Object),S(`design:paramtypes`,[])],k.prototype,`contextManagerService`,null);const A=e(import.meta.url);async function j(e){if(typeof e!=`string`||!/^\d+\.\d+\.\d+$/.test(e))throw Error(`Invalid minimum version format: ${e}`);let t=A.resolve(`@onereach/flow-sdk/package.json`);if(!t)throw Error(`Could not find package.json for @onereach/flow-sdk`);let n=await d(t,`utf8`),{version:r}=JSON.parse(n),{groups:i}=/^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)/.exec(r)||{};if(!i)throw Error(`Invalid Flow SDK version format: ${r}`);let a=Number.parseInt(i.major??`0`,10),o=Number.parseInt(i.minor??`0`,10),s=Number.parseInt(i.patch??`0`,10);if(a==null||o==null||s==null||Number.isNaN(a)||Number.isNaN(o)||Number.isNaN(s))throw Error(`Invalid version format: ${r}`);let[c,l,u]=e.split(`.`).map(e=>Number.parseInt(e,10));if(c==null||l==null||u==null||Number.isNaN(c)||Number.isNaN(l)||Number.isNaN(u))throw Error(`Invalid minimum version format: ${e}`);if(a<c||a===c&&o<l||a===c&&o===l&&s<u)throw Error(`Flow SDK version '${r}' is lower than required minimum version '${e}' for the step`)}var M=class extends l{data;constructor(e,t){super(e),this.data=t}},N=class extends M{async getCallId(){return(await this.getConversationData()).id}async getConversationData(){let{conversation:e}=this.data,t=await this.fetchConversationData({conversation:e,conversationThread:this.dataThreadId});if(!t||t._conv==null)throw Error(`Missing conversation data`);return t}get dataThreadId(){return this.data.conversationThread||this.thread.id}async fetchConversationData({conversation:e,conversationThread:t}){return await this.process.getSafeThread(t).get(e)}};C([n(),S(`design:type`,Function),S(`design:paramtypes`,[Object]),S(`design:returntype`,Promise)],N.prototype,`fetchConversationData`,null);var P,F=class extends w{async runStep(){await j(`8.0.72`),this.triggers.local(`ack`,this.onAcknowledge),this.triggers.otherwise(this.initialize)}async initialize(){let e=await this.conversationContext.getConversationData();await k.start(this.thread,e)}onAcknowledge(e){this.log.DEBUG?.(`onAcknowledge event`,e),this.exitStep(`next`,{context:e.params.context})}get conversationContext(){return new N(this.thread,this.data)}};C([y,S(`design:type`,Function),S(`design:paramtypes`,[]),S(`design:returntype`,Promise)],F.prototype,`runStep`,null),C([n(),S(`design:type`,typeof(P=N!==void 0&&N)==`function`?P:Object),S(`design:paramtypes`,[])],F.prototype,`conversationContext`,null),t();const I={[k.class]:k};export{I as states,F as step};
|
|
1
|
+
import{createRequire as e}from"node:module";import{install as t}from"source-map-support";import{Memoize as n}from"typescript-memoize";import{ACTION as r}from"@onereach/flow-sdk/types/index.js";import i from"@onereach/flow-sdk/errors/timeout.js";import{z as a}from"zod/v4-mini";import o from"@onereach/flow-sdk/errors/base.js";import s from"@onereach/flow-sdk/step.js";import*as c from"zod/mini";import{BasicThreadService as l}from"@onereach/flow-sdk/services/basic.js";import u from"node:crypto";import{performance as d}from"node:perf_hooks";import{readFile as f}from"node:fs/promises";const p={UNKNOWN:`UNKNOWN`,STEP_LOGIC_ISSUE:`STEP_LOGIC_ISSUE`,AUTH:`AUTH`,TIMEOUT:`TIMEOUT`,VALIDATION:`VALIDATION`,INVALID_REQUEST:`INVALID_REQUEST`,RATE_LIMITED:`RATE_LIMITED`,SERVER_ERROR:`SERVER_ERROR`,UNSUPPORTED:`UNSUPPORTED`};var m=class extends o{};const h=[m,i];function g(e,t={}){let{preserveErrors:n=h,unknownMessage:r=`Unknown error`,unknownCode:o=p.UNKNOWN}=t;if(n?.some(t=>e instanceof t))return e;if(e instanceof a.core.$ZodError)return new m(a.prettifyError(e),e,{code:p.VALIDATION});if(typeof e==`string`)return new m(e,{code:p.UNKNOWN});if(e instanceof Error){if(e.message.includes(`Request timed out`))return new i(`Timeout`,e,{code:p.TIMEOUT});let t=e?.response?.data?.error?.message;return t==null?new m(r,e,{code:o}):new m(t,e,{code:p.SERVER_ERROR})}return new m(r,{code:o,data:e})}function _(e,t){function n(t,n,r,i){let a=e(t,n,r,i);if(typeof a==`function`){let e=i.value,t=a;if(e?.name!=null)try{Object.defineProperty(t,`name`,{value:e.name})}catch{}return i.value=t,i}return a??i}return function(e,r,i){if(typeof e==`object`&&e&&(typeof r==`string`||typeof r==`symbol`)&&typeof i==`object`&&i)return n(t,e,r,i);{let r=e??t;return(e,t,i)=>n(r,e,t,i)}}}const v=_((e,t,n,r)=>{let i=r.value;if(!(!i||typeof i!=`function`))return function(...t){try{let r=i.apply(this,t);return r instanceof Promise?r.catch(t=>y.call(this,e,t,n)):r}catch(t){return y.call(this,e,t,n)}}},{allowHandleError:!1,useErrorFilter:!0});function y(e,t,n){let i=n.toString();this.log.DEBUG?.(`Error in method '${i}'`,t);let a=e.useErrorFilter?g(t):t;if(a instanceof Error)if(e.allowHandleError){this.thread.enqueue({name:r.error,error:a});return}else{this.end(a);return}throw a}const b=_((e,t,n,r)=>{let i=r.value;if(!(!i||typeof i!=`function`))return function(...e){try{let t=i.apply(this,e);return t instanceof Promise?t.catch(e=>{let t=n.toString();throw this.log.DEBUG?.(`Error in method '${t}'`,e),g(e)}):t}catch(e){let t=n.toString();throw this.log.DEBUG?.(`Error in method '${t}'`,e),g(e)}}},{});c.config(c.locales.en());const x=c.string().check(c.trim(),c.refine(e=>![`undefined`,`null`].includes(e),{error:`Unexpected undefined or null merge-field value`})),S=c.object({conversation:x.check(c.minLength(1)),conversationThread:x});function C(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function w(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}var T=class extends s{async resolveDataIn(){let e=await super.resolveDataIn();return S.parse(e)}};w([b,C(`design:type`,Function),C(`design:paramtypes`,[]),C(`design:returntype`,Promise)],T.prototype,`resolveDataIn`,null);const E={telemetryActivated:`main_tel_act`},D={refreshTurnContext:`aggr_ctx_rsh`};var O=class extends l{static get statePlaceholder(){return{rawEvents:[],turns:[]}}addEvent(e){this.thread.state.rawEvents.push(e);let t=this.thread.state.turns.findLast(t=>e.params.type?.startsWith?.(`asr-input/`)&&t.asrInputId===e.params?.inputId||e.params.type?.startsWith?.(`tts-audio/`)&&t.ttsContext?.turnId===e.params?.ttsContext?.turnId||e.params.type===`tts-audio/started`&&t.ttsStartedTimestamp==null);if(t==null){this.thread.state.turns.length===0&&e.params.type!==`asr-input/started`&&console.warn(`Turn started without ASR input started event`,e);let n=e.params?.inputId??e.params?.ttsContext?.turnId??u.randomUUID(),r=e.params.timestamp??Date.now();this.thread.state.turns.some(e=>e.id===n)&&(console.warn(`Turn already exists`,{id:n,event:e}),n=u.randomUUID()),t={id:n,finished:!1,startTimestamp:r,endTimestamp:void 0,asrInputId:void 0,asrStartedTimestamp:void 0,asrEndedTimestamp:void 0,asrProcessedTimestamp:void 0,asrConfidenceScore:void 0,asrRecognitionText:void 0,asrProvider:void 0,asrUsageMeta:void 0,ttsStartedTimestamp:void 0,ttsEndedTimestamp:void 0,ttsEndedReason:void 0,ttsInterruptedAfterText:void 0,ttsProvider:void 0,ttsContext:void 0},this.thread.state.turns.push(t)}switch(e.params.type){case`asr-input/started`:t.asrInputId&&t.asrInputId!==e.params.inputId&&(console.warn(`ASR input started for wrong input`,{expected:t.asrInputId,actual:e.params.inputId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`asr-input-started-for-wrong-input`)),t.asrInputId=e.params.inputId,t.asrStartedTimestamp=e.params.timestamp;break;case`asr-input/ended`:t.asrInputId&&t.asrInputId!==e.params.inputId&&(console.warn(`ASR input ended for wrong input`,{expected:t.asrInputId,actual:e.params.inputId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`asr-input-ended-for-wrong-input`)),t.asrEndedTimestamp=e.params.timestamp;break;case`asr-input/processed`:t.asrInputId!==e.params.inputId&&(console.warn(`ASR input processed for wrong input`,{expected:t.asrInputId,actual:e.params.inputId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`asr-input-processed-for-wrong-input`)),t.asrProcessedTimestamp=e.params.timestamp,t.asrConfidenceScore=e.params.confidenceScore,t.asrRecognitionText=e.params.phrase?.text,t.asrProvider=e.params.asrProvider,t.asrUsageMeta=e.params.asrUsageMeta;break;case`tts-audio/started`:t.ttsContext?.turnId&&t.ttsContext?.turnId!==e.params.ttsContext?.turnId&&(console.warn(`TTS audio started for wrong turn id`,{expected:t.ttsContext?.turnId,actual:e.params.ttsContext?.turnId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`tts-audio-started-for-wrong-message`)),t.ttsProvider=e.params.ttsProvider,t.ttsContext=e.params.ttsContext,t.ttsStartedTimestamp=e.params.timestamp;break;case`tts-audio/interrupted`:t.ttsContext?.turnId&&t.ttsContext?.turnId!==e.params.ttsContext?.turnId&&(console.warn(`TTS audio interrupted for wrong turn id`,{expected:e.params.ttsContext?.turnId,actual:e.params.ttsContext?.turnId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`tts-audio-interrupted-for-wrong-message`)),t.ttsInterruptedAfterText=e.params.partialText,t.ttsEndedReason=`interrupted`,t.ttsEndedTimestamp=e.params.timestamp,t.endTimestamp=e.params.timestamp,t.finished=!0;break;case`tts-audio/ended`:t.ttsContext?.turnId&&t.ttsContext?.turnId!==e.params.ttsContext?.turnId&&(console.warn(`TTS audio interrupted for wrong turn id`,{expected:e.params.ttsContext?.turnId,actual:e.params.ttsContext?.turnId,event:e}),t.damaged=!0,t.damagedReasons??=[],t.damagedReasons.push(`tts-audio-ended-for-wrong-message`)),t.ttsEndedReason=`ended`,t.ttsEndedTimestamp=e.params.timestamp,t.endTimestamp=e.params.timestamp,t.finished=!0;break;default:this.log.WARN?.(`Unknown event type`,e)}}},k=class extends l{static get statePlaceholder(){return{turn:{turnId:``,turnIndex:-1},turnsContextMap:{}}}async initializeTurnContext(){if(this.thread.state.turn.turnId!==``){this.thread.log.WARN?.(`Turn context already initialized. Skipping initialization.`);return}this.thread.log.DEBUG?.(`Initializing turn context`),this.updateTurnContext(),await this.refreshStepDataOut()}async refreshTurnContext(){if(this.thread.state.turn.turnId===``){this.thread.log.WARN?.(`Turn context was not initialized. Initializing new turn context.`),await this.initializeTurnContext();return}this.thread.log.DEBUG?.(`Refreshing turn context`),this.updateTurnContext(),await this.refreshStepDataOut()}updateTurnContext(){let e=crypto.randomUUID(),t={turnId:e,turnIndex:(this.thread.state.turn.turnIndex??-1)+1};this.thread.state.turn=t,this.thread.state.turnsContextMap[e]=t}async refreshStepDataOut(){await this.thread.setDataOut({context:this.thread.state.turn})}},A=class extends l{data;constructor(e,t){super(e),this.data=t}},j=class extends A{async getConversationData({force:e}={}){let t=this.thread.state.conversation;if(t&&e!==!0)return t;let{conversation:n}=this.data,r={conversation:n,conversationThread:this.conversationThreadId},i=await this.fetchConversationData(r);if(!i||i._conv==null)throw new m(`Missing conversation data`,{code:p.VALIDATION,data:r});return this.thread.state.conversation=i,i}async enableTelemetry(){if(!this.thread.state.conversation)throw new m(`Conversation data is not available`,{code:p.VALIDATION});let{id:e,type:t,callback:n}=this.thread.state.conversation,r={target:this.thread.helpers.providersAccountId,name:`out/voice/${t}`,params:{id:e,async:!0,hbs:99,commands:[{name:`start-telemetry`,params:{ack:!0}}],step:{key:this.session.key,trd:this.thread.id}},reporting:{...this.session.getSessionRef()}};this.log.DEBUG?.(`startTelemetry event`,r);let i=await this.thread.eventManager.emit(r,{target:n,invocationType:`async`,timeout:5e3});if(this.log.DEBUG?.(`startTelemetry result`,i),i==null)throw new m(`Failed to start telemetry`,{code:p.SERVER_ERROR,data:r})}get expectHeartbeatBefore(){return Date.now()+3e5}onHeartbeatTimeout(){this.log.WARN?.(`Heartbeat was not received before the deadline`),this.thread.end()}get conversationThreadId(){let{conversationThread:e}=this.data;return e||this.thread.state.parentThreadId}async fetchConversationData({conversation:e,conversationThread:t}){return await this.process.getSafeThread(t).get(e)}},M,N,P=class extends T{static class=`evt_aggr`;static async start(e){let t=this.getThreadId(e.step.id);e.process.getThread(t)??await e.process.runThread({id:t,background:!0,state:{...k.statePlaceholder,...O.statePlaceholder,step:e.step.id,class:this.class,parentThreadId:e.id}})}static getThreadId(e){return`vce_otel_${this.class}_${e}`}async runStep(){let{id:e}=await this.voiceService.getConversationData();this.triggers.local(`in/voice/${e}`,this.onVoiceEvent),this.triggers.local(D.refreshTurnContext,this.onRefreshTurnContext),this.triggers.deadline(this.voiceService.expectHeartbeatBefore,this.onDeadline),this.triggers.otherwise(this.initialize)}onVoiceEvent(e){switch(this.log.DEBUG?.(`onVoiceEvent`,e),e.params.type){case`ack`:this.resumeParentThread();break;case`tts-audio/started`:case`tts-audio/finished`:case`tts-audio/interrupted`:case`asr-input/started`:case`asr-input/ended`:case`asr-input/processed`:this.turnsAggregatorService.addEvent(e);break;case`hangup`:{let{turns:e,rawEvents:t}=this.state;this.log.WARN?.(`Hangup event received`,{turns:e,rawEvents:t});break}case`heartbeat`:break;default:this.log.WARN?.(`Unexpected type of event`,e)}}async initialize(){this.log.DEBUG?.(`Initializing EventsAggregator thread`),await this.turnsManagerService.initializeTurnContext(),await this.voiceService.enableTelemetry()}onDeadline(){this.voiceService.onHeartbeatTimeout()}async onRefreshTurnContext(){await this.turnsManagerService.refreshTurnContext()}async resumeParentThread(){let e={name:E.telemetryActivated,params:{turn:this.state.turn},thread:this.state.parentThreadId};await this.process.enqueueAndRun(e)}get voiceService(){return new j(this.thread,this.data)}get turnsManagerService(){return new k(this.thread)}get turnsAggregatorService(){return new O(this.thread)}};w([v,C(`design:type`,Function),C(`design:paramtypes`,[]),C(`design:returntype`,Promise)],P.prototype,`runStep`,null),w([v,C(`design:type`,Function),C(`design:paramtypes`,[Object]),C(`design:returntype`,void 0)],P.prototype,`onVoiceEvent`,null),w([v,C(`design:type`,Function),C(`design:paramtypes`,[]),C(`design:returntype`,Promise)],P.prototype,`initialize`,null),w([v,C(`design:type`,Function),C(`design:paramtypes`,[]),C(`design:returntype`,void 0)],P.prototype,`onDeadline`,null),w([v,C(`design:type`,Function),C(`design:paramtypes`,[]),C(`design:returntype`,Promise)],P.prototype,`onRefreshTurnContext`,null),w([n(),C(`design:type`,typeof(M=k!==void 0&&k)==`function`?M:Object),C(`design:paramtypes`,[])],P.prototype,`turnsManagerService`,null),w([n(),C(`design:type`,typeof(N=O!==void 0&&O)==`function`?N:Object),C(`design:paramtypes`,[])],P.prototype,`turnsAggregatorService`,null);const F=e(import.meta.url);async function I(e){if(typeof e!=`string`||!/^\d+\.\d+\.\d+$/.test(e))throw Error(`Invalid minimum version format: ${e}`);let t=F.resolve(`@onereach/flow-sdk/package.json`);if(!t)throw Error(`Could not find package.json for @onereach/flow-sdk`);let n=await f(t,`utf8`),{version:r}=JSON.parse(n),{groups:i}=/^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)/.exec(r)||{};if(!i)throw Error(`Invalid Flow SDK version format: ${r}`);let a=Number.parseInt(i.major??`0`,10),o=Number.parseInt(i.minor??`0`,10),s=Number.parseInt(i.patch??`0`,10);if(a==null||o==null||s==null||Number.isNaN(a)||Number.isNaN(o)||Number.isNaN(s))throw Error(`Invalid version format: ${r}`);let[c,l,u]=e.split(`.`).map(e=>Number.parseInt(e,10));if(c==null||l==null||u==null||Number.isNaN(c)||Number.isNaN(l)||Number.isNaN(u))throw Error(`Invalid minimum version format: ${e}`);if(a<c||a===c&&o<l||a===c&&o===l&&s<u)throw Error(`Flow SDK version '${r}' is lower than required minimum version '${e}' for the step`)}var L=class extends T{async runStep(){await I(`8.0.72`),this.triggers.local(E.telemetryActivated,this.onTelemetryActivated),this.triggers.otherwise(this.initialize)}async initialize(){this.state.activationStart=d.now(),await P.start(this.thread)}onTelemetryActivated(e){let t=d.now()-this.state.activationStart;this.log.DEBUG?.(`onTelemetryActivated`,{event:e,activationMs:t}),this.exitStep(`next`,{turn:e.params.turn})}};w([b,C(`design:type`,Function),C(`design:paramtypes`,[]),C(`design:returntype`,Promise)],L.prototype,`runStep`,null),t();const R={[P.class]:P};export{R as states,L as step};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["defaultOptions","z","crypto"],"sources":["../src/errors/step-error.ts","../src/errors/error-filter.ts","../src/utils/create-method-decorator.ts","../src/decorators/background-thread-error-filter.ts","../src/decorators/error-filter.ts","../src/schemas/data-in.ts","../src/threads/base/base.ts","../src/threads/base/constants.ts","../src/threads/events-aggregator/constants.ts","../src/threads/events-aggregator/services/context-manager/context-manager.ts","../src/threads/events-aggregator/services/turns-aggregator/turns-aggregator.ts","../src/threads/events-aggregator/events-aggregator.ts","../src/utils/validate-flow-sdk-version.ts","../src/services/thread-service-with-data.ts","../src/threads/main/services/conversation-context/conversation-context.ts","../src/threads/main/step.ts","../src/index.ts"],"sourcesContent":["import BaseError from '@onereach/flow-sdk/errors/base.js';\n\nexport const ErrorCode = {\n UNKNOWN: 'UNKNOWN',\n STEP_LOGIC_ISSUE: 'STEP_LOGIC_ISSUE',\n AUTH: 'AUTH',\n TIMEOUT: 'TIMEOUT',\n VALIDATION: 'VALIDATION',\n INVALID_REQUEST: 'INVALID_REQUEST',\n RATE_LIMITED: 'RATE_LIMITED',\n SERVER_ERROR: 'SERVER_ERROR',\n UNSUPPORTED: 'UNSUPPORTED',\n} as const;\n\nexport class GenerateCallTelemetryStepError extends BaseError<{\n code: keyof typeof ErrorCode;\n data?: unknown;\n}> {}\n\nexport class AbortRequestError extends BaseError {}\n","import TimeoutError from '@onereach/flow-sdk/errors/timeout.js';\nimport { z } from 'zod/v4-mini';\n\nimport { GenerateCallTelemetryStepError, ErrorCode } from './step-error.ts';\n\nconst defaultPreserveErrors = [GenerateCallTelemetryStepError, TimeoutError] as const;\nexport function errorFilter<P extends readonly AnyErrorClass[] = typeof defaultPreserveErrors>(\n error: unknown,\n options: ErrorFilterOptions<P> = {},\n): InstancesOf<P> | GenerateCallTelemetryStepError | TimeoutError {\n const {\n preserveErrors = defaultPreserveErrors,\n unknownMessage = 'Unknown error',\n unknownCode = ErrorCode.UNKNOWN,\n } = options;\n\n // if error is GenerateCallTelemetryStepError or TimeoutError, return it directly\n if (preserveErrors?.some((ErrorClass) => error instanceof ErrorClass)) {\n return error as InstancesOf<P>;\n }\n\n // validation errors\n if (error instanceof z.core.$ZodError) {\n return new GenerateCallTelemetryStepError(z.prettifyError(error), error, {\n code: ErrorCode.VALIDATION,\n });\n }\n\n // if error is a string assume it's an error message\n if (typeof error === 'string') {\n return new GenerateCallTelemetryStepError(error, {\n code: ErrorCode.UNKNOWN,\n });\n }\n\n if (error instanceof Error) {\n // timeout errors\n if (error.message.includes('Request timed out')) {\n return new TimeoutError('Timeout', error, { code: ErrorCode.TIMEOUT });\n }\n\n // TODO: fix interpreting of this kind of errors\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n const responseErrorMessage: string | undefined = (error as unknown as any)?.response?.data?.error?.message;\n if (responseErrorMessage != undefined) {\n return new GenerateCallTelemetryStepError(responseErrorMessage, error, {\n code: ErrorCode.SERVER_ERROR,\n });\n }\n\n return new GenerateCallTelemetryStepError(unknownMessage, error, {\n code: unknownCode,\n });\n }\n\n // catch all for unknown errors\n return new GenerateCallTelemetryStepError(unknownMessage, {\n code: unknownCode,\n data: error,\n });\n}\n\nexport type ErrorFilterOptions<P extends readonly AnyErrorClass[]> = {\n /** Array of error classes that should not be wrapped */\n preserveErrors?: P;\n /** Error message to use when message is unknown */\n unknownMessage?: string;\n /** Error code to use when message is unknown */\n unknownCode?: keyof typeof ErrorCode;\n};\n\n/** Any Error class */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyErrorClass<E extends Error = Error> = new (...arguments_: any[]) => E;\n\n/** Turn a tuple/array of constructors into a union of their instance types. */\nexport type InstancesOf<Ctors extends readonly AnyErrorClass[]> =\n Ctors[number] extends AnyErrorClass<infer I> ? I : never;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Creates a method decorator that can be used with or without options.\n * @param apply - Function that applies the decorator logic with given options.\n * @param defaultOptions - Default options to use if none are provided.\n */\nexport function createMethodDecoratorWithOptionalArguments<A, T extends AnyFunction = AnyFunction>(\n apply: (\n options: A,\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ) => T | TypedPropertyDescriptor<T> | void,\n defaultOptions: A,\n): MethodDecoratorWithOptionalArguments<A, T> {\n function runApply(\n options: A,\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ): TypedPropertyDescriptor<T> | void {\n const maybe = apply(options, target, propertyKey, descriptor);\n\n // If the decorator factory returned a wrapped function, assign it to the descriptor here\n if (typeof maybe === 'function') {\n const originalMethod = descriptor.value;\n const wrappedMethod = maybe as typeof originalMethod;\n\n if (originalMethod?.name != undefined) {\n try {\n Object.defineProperty(wrappedMethod, 'name', { value: originalMethod.name });\n } catch {\n // ignore if name is non-configurable\n }\n }\n\n descriptor.value = wrappedMethod;\n return descriptor;\n }\n\n // If a descriptor was returned or decorator mutated descriptor in-place, use that\n return maybe ?? descriptor;\n }\n\n return function decoratorOrFactory(\n argument0?: object | A,\n argument1?: string | symbol,\n argument2?: TypedPropertyDescriptor<T>,\n ): any {\n if (\n argument0 !== null &&\n typeof argument0 === 'object' &&\n (typeof argument1 === 'string' || typeof argument1 === 'symbol') &&\n argument2 !== null &&\n typeof argument2 === 'object'\n ) {\n // Called as plain decorator: @Decorator\n return runApply(defaultOptions, argument0, argument1, argument2);\n } else {\n // Called as decorator factory: @Decorator(options)\n const options = (argument0 as A) ?? defaultOptions;\n return (target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => {\n return runApply(options, target, propertyKey, descriptor);\n };\n }\n };\n}\n\nexport type AnyFunction = (...arguments_: any[]) => any;\n\nexport type MethodDecoratorWithOptionalArguments<A, T extends AnyFunction = AnyFunction> =\n // Plain method decorator (three arguments)\n ((\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ) => TypedPropertyDescriptor<T> | void) &\n // Decorator factory (optional options argument)\n ((options?: A) => MethodDecorator);\n","import type Step from '@onereach/flow-sdk/step.js';\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\n\nimport { errorFilter } from '../errors/error-filter.ts';\nimport { createMethodDecoratorWithOptionalArguments } from '../utils/create-method-decorator.ts';\n\nconst defaultOptions: BackgroundThreadErrorFilterOptions = { allowHandleError: false, useErrorFilter: true };\n\n/**\n * Since errors in hooks are fatal and can't be processed this decorator allows to wrap hook handler\n * and manage errors by ending a thread with the error (preventing sending error to `error` exit)\n * @param options.allowHandleError - Default `false`. If `false` in case of error will end thread with error as result, if `true` will allow to handle error via 'error' exit\n * @param options.useErrorFilter - Default `true`. If `true` every error wild be processed with `errorFilter` utility function\n */\nexport const BackgroundThreadErrorFilter = createMethodDecoratorWithOptionalArguments(\n (options, _target, propertyKey, descriptor) => {\n const originalMethod = descriptor.value;\n if (!originalMethod || typeof originalMethod !== 'function') return;\n\n return function (this: Step, ...arguments_: Parameters<typeof originalMethod>): ReturnType<typeof originalMethod> {\n try {\n const result: unknown = originalMethod.apply(this, arguments_);\n\n if (result instanceof Promise) {\n return result.catch((error) => errorHandler.call(this, options, error, propertyKey));\n }\n\n return result;\n } catch (error) {\n return errorHandler.call(this, options, error, propertyKey) as ReturnType<typeof originalMethod>;\n }\n } as typeof originalMethod;\n },\n defaultOptions,\n);\n\nfunction errorHandler(\n this: Step,\n options: BackgroundThreadErrorFilterOptions,\n error: unknown,\n propertyKey: string | symbol,\n): void {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n const filteredError = options.useErrorFilter ? errorFilter(error) : error;\n\n if (filteredError instanceof Error) {\n if (options.allowHandleError) {\n // Send it to the 'error' exit and stop here\n this.thread.enqueue({ name: ACTION.error, error: filteredError });\n return;\n } else {\n // End the thread with the error and stop here\n this.end(filteredError);\n return;\n }\n }\n\n // Only throw if it's not an Error instance and you truly want to bubble it\n throw filteredError;\n}\n\nexport type BackgroundThreadErrorFilterOptions = {\n allowHandleError?: boolean;\n useErrorFilter?: boolean;\n};\n","import type Step from '@onereach/flow-sdk/step.js';\n\nimport { errorFilter } from '../errors/error-filter.ts';\nimport { createMethodDecoratorWithOptionalArguments } from '../utils/create-method-decorator.ts';\n\nconst defaultOptions = {};\n\n/**\n * Will wrap method with `errorFilter` for every error.\n */\nexport const ErrorFilter = createMethodDecoratorWithOptionalArguments((_options, _target, propertyKey, descriptor) => {\n const originalMethod = descriptor.value;\n\n if (!originalMethod || typeof originalMethod !== 'function') return;\n\n return function (this: Step, ...arguments_: Parameters<typeof originalMethod>): ReturnType<typeof originalMethod> {\n try {\n const result: unknown = originalMethod.apply(this, arguments_);\n\n if (result instanceof Promise) {\n return result.catch((error: unknown) => {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n throw errorFilter(error);\n }) as ReturnType<typeof originalMethod>;\n }\n\n return result;\n } catch (error) {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n throw errorFilter(error);\n }\n };\n}, defaultOptions);\n","import * as z from 'zod/mini';\n\nz.config(z.locales.en());\n\n// string that prevents 'undefined' and 'null' values\nconst stringNoUndefinedSchema = z.string().check(\n z.trim(),\n z.refine((value) => !['undefined', 'null'].includes(value), {\n error: 'Unexpected undefined or null merge-field value',\n }),\n);\n\nexport const dataInSchema = z.object({\n conversation: stringNoUndefinedSchema.check(z.minLength(1)),\n conversationThread: stringNoUndefinedSchema,\n});\n\nexport type DataIn = z.infer<typeof dataInSchema>;\n\n// /**\n// * Convert empty string to undefined before running schema validation\n// * @param schema schema to validate against\n// * @param defaultValue optional default value\n// */\n// function optionalStringValue<T extends z.core.SomeType>(schema: T) {\n// return z.optional(\n// z.pipe(\n// z.union([z.undefined(), z.literal(''), schema]),\n// z.transform((value) => (value === '' ? undefined : value)),\n// ),\n// );\n// }\n","import Step from '@onereach/flow-sdk/step.js';\n\nimport { ErrorFilter } from '../../decorators/error-filter.ts';\nimport { dataInSchema } from '../../schemas/data-in.ts';\n\nimport type { BaseConfig } from './types.ts';\n\n// TODO: convert it into class decorator\nexport class BaseStep<T extends BaseConfig> extends Step<T> {\n @ErrorFilter\n public async resolveDataIn() {\n const dataIn = await super.resolveDataIn();\n return dataInSchema.parse(dataIn);\n }\n}\n","export const baseClassIdPrefix = 'vce_otel';\n","export const eventsAggregatorClassId = 'evt_aggr';\n\nexport const eventsAggregatorEvents = {\n refreshTurnContext: 'aggr_ctx_rsh',\n} as const;\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\n\nimport { EventsAggregatorConfig } from '../../types.ts';\n\nimport { ContextManagerContext, ContextManagerState } from './types.ts';\n\nexport class ContextManagerService extends BasicThreadService<EventsAggregatorConfig> {\n public static get statePlaceholder(): ContextManagerState {\n return {\n context: {\n turnId: '',\n turnIndex: -1,\n },\n turnsContextMap: {},\n };\n }\n\n public async initializeTurnContext(): Promise<void> {\n if (this.thread.state.context.turnId !== '') {\n this.thread.log.WARN?.(`Turn context already initialized. Skipping initialization.`);\n return;\n }\n\n this.thread.log.DEBUG?.(`Initializing turn context`);\n this.updateTurnContext();\n await this.refreshStepDataOut();\n }\n\n public async refreshTurnContext(): Promise<void> {\n if (this.thread.state.context.turnId === '') {\n this.thread.log.WARN?.(`Turn context was not initialized. Initializing new turn context.`);\n await this.initializeTurnContext();\n return;\n }\n\n this.thread.log.DEBUG?.(`Refreshing turn context`);\n this.updateTurnContext();\n await this.refreshStepDataOut();\n }\n\n private updateTurnContext(): void {\n const turnId = crypto.randomUUID();\n const turnIndex = (this.thread.state.context.turnIndex ?? -1) + 1;\n const context: ContextManagerContext = {\n turnId,\n turnIndex,\n };\n this.thread.state.context = context;\n this.thread.state.turnsContextMap[turnId] = context;\n }\n\n private async refreshStepDataOut(): Promise<void> {\n // refresh step data out to have new context\n await this.thread.setDataOut({\n context: this.thread.state.context,\n });\n }\n}\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport type { IThread } from '@onereach/flow-sdk/types/index.js';\nimport crypto from 'node:crypto';\n\nimport type { EventsAggregatorConfig, VoiceEvent } from '../../types.ts';\n\nimport type { TurnsAggregatorState } from './types.ts';\n\n// const ttsMsgs: Record<string, { message: string; complete: boolean }> = {\n// 'a9a89135-90a0-42ab-b96e-a846a4930828': {\n// message: 'Hello! How can I assist you today?',\n// complete: true,\n// },\n// '8b20aa6d-5ab3-44d5-9e45-6e59ac1a2a08': {\n// message: 'My name is Alice. How can I help you today?',\n// complete: true,\n// },\n// 'c5ffec3b-c1c8-4029-b2e9-0543db2d0176': {\n// message: \"I don't have access to your name. Can you please tell me your name?\",\n// complete: true,\n// },\n// '823ef603-1dc3-4264-a399-ec7e25230b4a': {\n// message:\n// 'I’m sorry, I don’t have the ability to provide weather updates yet. Is there anything else I can help you with?',\n// complete: true,\n// },\n// };\n\nexport class TurnsAggregator extends BasicThreadService<EventsAggregatorConfig> {\n public static get statePlaceholder(): TurnsAggregatorState {\n return {\n rawEvents: [],\n turns: [],\n };\n }\n\n // private readonly turnsMap: Map<string, Turn>;\n // private turns: VoiceTurn[];\n\n constructor(thread: IThread<EventsAggregatorConfig>) {\n super(thread);\n\n // this.turnsMap = new Map();\n // this.turns = [];\n }\n\n addEvent(event: VoiceEvent) {\n this.thread.state.rawEvents.push(event);\n\n let currentTurn = this.thread.state.turns.findLast((turn) => {\n return (\n (event.params.type?.startsWith?.('asr-input/') && turn.asrInputId === event.params?.inputId) ||\n (event.params.type?.startsWith?.('tts-audio/') &&\n turn.ttsContext?.turnId === event.params?.ttsContext?.turnId) ||\n (event.params.type === 'tts-audio/started' && turn.ttsStartedTimestamp == undefined)\n );\n });\n if (currentTurn == undefined) {\n if (this.thread.state.turns.length === 0 && event.params.type !== 'asr-input/started') {\n console.warn('Turn started without ASR input started event', event);\n }\n\n let id: string = event.params?.inputId ?? event.params?.ttsContext?.turnId ?? crypto.randomUUID();\n const startTimestamp = event.params.timestamp ?? Date.now();\n\n if (this.thread.state.turns.some((turn) => turn.id === id)) {\n console.warn('Turn already exists', { id, event });\n id = crypto.randomUUID();\n }\n\n currentTurn = {\n id,\n finished: false,\n startTimestamp,\n\n // events: [],\n // asrEvents: [],\n // ttsEvents: [],\n // stage: 'init',\n\n endTimestamp: undefined,\n\n asrInputId: undefined,\n asrStartedTimestamp: undefined,\n asrEndedTimestamp: undefined,\n asrProcessedTimestamp: undefined,\n asrConfidenceScore: undefined,\n asrRecognitionText: undefined,\n asrProvider: undefined,\n asrUsageMeta: undefined,\n\n ttsStartedTimestamp: undefined,\n ttsEndedTimestamp: undefined,\n ttsEndedReason: undefined,\n ttsInterruptedAfterText: undefined,\n ttsProvider: undefined,\n ttsContext: undefined,\n };\n this.thread.state.turns.push(currentTurn);\n // this.turnsMap.set(id, currentTurn);\n }\n\n // currentTurn.events.push(event);\n\n switch (event.params.type) {\n case 'asr-input/started': {\n if (currentTurn.asrInputId && currentTurn.asrInputId !== event.params.inputId) {\n console.warn('ASR input started for wrong input', {\n expected: currentTurn.asrInputId,\n actual: event.params.inputId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('asr-input-started-for-wrong-input');\n }\n currentTurn.asrInputId = event.params.inputId;\n currentTurn.asrStartedTimestamp = event.params.timestamp;\n // currentTurn.asrEvents.push(event);\n // currentTurn.stage = 'input';\n break;\n }\n case 'asr-input/ended': {\n if (currentTurn.asrInputId && currentTurn.asrInputId !== event.params.inputId) {\n console.warn('ASR input ended for wrong input', {\n expected: currentTurn.asrInputId,\n actual: event.params.inputId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('asr-input-ended-for-wrong-input');\n }\n currentTurn.asrEndedTimestamp = event.params.timestamp;\n // currentTurn.asrEvents.push(event);\n break;\n }\n case 'asr-input/processed': {\n if (currentTurn.asrInputId !== event.params.inputId) {\n console.warn('ASR input processed for wrong input', {\n expected: currentTurn.asrInputId,\n actual: event.params.inputId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('asr-input-processed-for-wrong-input');\n }\n currentTurn.asrProcessedTimestamp = event.params.timestamp;\n currentTurn.asrConfidenceScore = event.params.confidenceScore;\n currentTurn.asrRecognitionText = event.params.phrase?.text;\n currentTurn.asrProvider = event.params.asrProvider;\n currentTurn.asrUsageMeta = event.params.asrUsageMeta;\n // currentTurn.asrEvents.push(event);\n break;\n }\n\n case 'tts-audio/started': {\n if (currentTurn.ttsContext?.turnId && currentTurn.ttsContext?.turnId !== event.params.ttsContext?.turnId) {\n console.warn('TTS audio started for wrong turn id', {\n expected: currentTurn.ttsContext?.turnId,\n actual: event.params.ttsContext?.turnId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('tts-audio-started-for-wrong-message');\n }\n currentTurn.ttsProvider = event.params.ttsProvider;\n currentTurn.ttsContext = event.params.ttsContext;\n currentTurn.ttsStartedTimestamp = event.params.timestamp;\n // currentTurn.ttsEvents.push(event);\n // currentTurn.stage = 'output';\n break;\n }\n case 'tts-audio/interrupted': {\n if (currentTurn.ttsContext?.turnId && currentTurn.ttsContext?.turnId !== event.params.ttsContext?.turnId) {\n console.warn('TTS audio interrupted for wrong turn id', {\n expected: event.params.ttsContext?.turnId,\n actual: event.params.ttsContext?.turnId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('tts-audio-interrupted-for-wrong-message');\n }\n currentTurn.ttsInterruptedAfterText = event.params.partialText;\n currentTurn.ttsEndedReason = 'interrupted';\n currentTurn.ttsEndedTimestamp = event.params.timestamp;\n // currentTurn.ttsMessage = ttsMsgs[currentTurn.ttsContext?.turnId as string]?.message;\n currentTurn.endTimestamp = event.params.timestamp;\n\n currentTurn.finished = true;\n\n // currentTurn.ttsEvents.push(event);\n break;\n }\n case 'tts-audio/ended': {\n if (currentTurn.ttsContext?.turnId && currentTurn.ttsContext?.turnId !== event.params.ttsContext?.turnId) {\n console.warn('TTS audio interrupted for wrong turn id', {\n expected: event.params.ttsContext?.turnId,\n actual: event.params.ttsContext?.turnId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('tts-audio-ended-for-wrong-message');\n }\n currentTurn.ttsEndedReason = 'ended';\n currentTurn.ttsEndedTimestamp = event.params.timestamp;\n // currentTurn.ttsMessage = ttsMsgs[currentTurn.ttsContext?.turnId as string]?.message;\n currentTurn.endTimestamp = event.params.timestamp;\n\n currentTurn.finished = true;\n\n // currentTurn.ttsEvents.push(event);\n // currentTurn.stage = 'complete';\n // currentTurn = undefined;\n break;\n }\n\n default: {\n console.warn('Unknown event type', event);\n }\n }\n }\n}\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport type { IThreadId, IThread, IStepId } from '@onereach/flow-sdk/types/index.js';\nimport { Memoize } from 'typescript-memoize';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { ErrorCode, GenerateCallTelemetryStepError } from '../../errors/step-error.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport type { GenerateCallTelemetryConfig } from '../main/types.ts';\n\nimport { eventsAggregatorClassId, eventsAggregatorEvents } from './constants.ts';\nimport { ContextManagerService } from './services/context-manager/context-manager.ts';\nimport { TurnsAggregator } from './services/turns-aggregator/turns-aggregator.ts';\nimport type { EventsAggregatorConfig, VoiceEvent, VoiceConversation } from './types.ts';\n\nexport class EventsAggregator extends BaseStep<EventsAggregatorConfig> {\n public static readonly class = eventsAggregatorClassId;\n\n public static async start(\n thread: IThread<GenerateCallTelemetryConfig>,\n voiceConversation: VoiceConversation,\n ): Promise<void> {\n // TODO: validate with zod schema\n if (!voiceConversation) throw new Error('Voice conversation data is missing');\n\n const interceptorThreadId = this.getThreadId(thread.step.id);\n const interceptorThread = thread.process.getThread<EventsAggregatorConfig>(interceptorThreadId);\n\n if (interceptorThread != undefined) return; // thread already exists\n\n // create thread\n await thread.process.runThread<EventsAggregatorConfig>({\n id: interceptorThreadId,\n background: true,\n state: {\n ...ContextManagerService.statePlaceholder,\n ...TurnsAggregator.statePlaceholder,\n\n step: thread.step.id,\n class: this.class,\n\n parentThreadId: thread.id,\n voiceConversation,\n },\n });\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n //-------------------------------------\n @BackgroundThreadErrorFilter\n public async onVoiceEvent(event: VoiceEvent): Promise<void> {\n this.log.WARN?.('>>>VOICE event', event);\n this.log.DEBUG?.('onAcknowledge event', event);\n\n switch (event.params.type) {\n case 'ack': {\n // wake up parent thread\n await this.process.enqueueAndRun({\n name: 'ack',\n params: { context: this.state.context },\n thread: this.state.parentThreadId,\n });\n break;\n }\n\n case 'hangup': {\n // TODO: end EventsAggregator thread\n break;\n }\n\n default:\n // TODO: end EventsAggregator thread\n // TODO: do not throw error\n // throw new GenerateCallTelemetryStepError('Unexpected type of event', {\n // code: ErrorCode.UNKNOWN,\n // data: event,\n // });\n }\n }\n\n private async startTelemetry(): Promise<void> {\n const { id, type, callback } = this.state.voiceConversation;\n\n const event = {\n target: this.helpers.providersAccountId,\n name: `out/voice/${type}`,\n params: {\n id,\n async: true,\n // hbs: 99, // heartbeat seconds\n commands: [\n {\n name: 'start-telemetry',\n params: { ack: true }, // expect acknowledge from voicer\n },\n ],\n step: {\n key: this.session.key,\n trd: this.thread.id,\n },\n },\n\n reporting: {\n ...this.session.getSessionRef(),\n },\n };\n\n const start = performance.now();\n this.log.DEBUG?.('startTelemetry event', event);\n\n const result = await this.thread.eventManager.emit(event, {\n target: callback,\n invocationType: 'async',\n timeout: 5000,\n });\n this.log.DEBUG?.('startTelemetry result', { result, delay: performance.now() - start });\n\n if (result == undefined) {\n // TODO: test how parent thread will react on this error\n throw new GenerateCallTelemetryStepError('Failed to start telemetry', {\n code: ErrorCode.SERVER_ERROR,\n data: event,\n });\n }\n }\n // ---------------------------------------\n\n @BackgroundThreadErrorFilter\n public runStep(): void {\n // this.triggers.hook({ name: ACTION.event, thread: '*' }, this.onEventAction);\n this.triggers.local(`in/voice/${this.state.voiceConversation.id}`, this.onVoiceEvent);\n this.triggers.local(eventsAggregatorEvents.refreshTurnContext, this.onRefreshTurnContext);\n this.triggers.otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n public async initialize(): Promise<void> {\n this.log.DEBUG?.('Initializing EventsAggregator thread');\n await this.contextManagerService.initializeTurnContext();\n await this.startTelemetry();\n }\n\n // @BackgroundThreadErrorFilter\n // public onVoiceEvent(event: InterceptedEvent): void {\n // this.log.WARN?.('>>>VOICE event', event);\n // }\n\n // @BackgroundThreadErrorFilter\n // public onEventAction(eventAction: IActionEvent<AnyConfig, ACTION.event>): void {\n // const event = eventAction?.params?.action?.event as InterceptedEvent | undefined;\n\n // if (!event || !this.shouldInterceptEvent(event)) return;\n\n // this.log.DEBUG?.('Aggregating event...', event);\n // this.turnsAggregatorService.addEvent(event);\n // }\n\n @BackgroundThreadErrorFilter\n public async onRefreshTurnContext(): Promise<void> {\n await this.contextManagerService.refreshTurnContext();\n }\n\n // private shouldInterceptEvent(event: VoiceEvent): boolean {\n // if (!event || !event.name?.startsWith?.('in/voice/')) return false;\n // return Boolean(event.params?.type?.startsWith?.('tts-audio/') || event.params?.type?.startsWith?.('asr-input/'));\n // }\n\n @Memoize()\n private get contextManagerService(): ContextManagerService {\n return new ContextManagerService(this.thread);\n }\n\n // @Memoize()\n // private get turnsAggregatorService(): TurnsAggregator {\n // return new TurnsAggregator(this.thread);\n // }\n}\n","import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\nexport async function validateFlowSdkVersion(minVersion: string): Promise<void> {\n if (typeof minVersion !== 'string' || !/^\\d+\\.\\d+\\.\\d+$/.test(minVersion)) {\n throw new Error(`Invalid minimum version format: ${minVersion}`);\n }\n\n const packageJsonPath = require.resolve('@onereach/flow-sdk/package.json');\n if (!packageJsonPath) {\n throw new Error(`Could not find package.json for @onereach/flow-sdk`);\n }\n // Read the package.json file to get the version\n const packageJsonContent = await readFile(packageJsonPath, 'utf8');\n\n const { version } = JSON.parse(packageJsonContent) as { version: string };\n const { groups } = /^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)/.exec(version) || {};\n\n if (!groups) throw new Error(`Invalid Flow SDK version format: ${version}`);\n\n const major = Number.parseInt(groups.major ?? '0', 10);\n const minor = Number.parseInt(groups.minor ?? '0', 10);\n const patch = Number.parseInt(groups.patch ?? '0', 10);\n\n if (\n major == undefined ||\n minor == undefined ||\n patch == undefined ||\n Number.isNaN(major) ||\n Number.isNaN(minor) ||\n Number.isNaN(patch)\n ) {\n throw new Error(`Invalid version format: ${version}`);\n }\n\n const [minMajor, minMinor, minPatch] = minVersion.split('.').map((x) => Number.parseInt(x, 10));\n\n if (\n minMajor == undefined ||\n minMinor == undefined ||\n minPatch == undefined ||\n Number.isNaN(minMajor) ||\n Number.isNaN(minMinor) ||\n Number.isNaN(minPatch)\n ) {\n throw new Error(`Invalid minimum version format: ${minVersion}`);\n }\n\n if (\n major < minMajor ||\n (major === minMajor && minor < minMinor) ||\n (major === minMajor && minor === minMinor && patch < minPatch)\n ) {\n throw new Error(\n `Flow SDK version '${version}' is lower than required minimum version '${minVersion}' for the step`,\n );\n }\n}\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport type { CONFIG, IN, IThread } from '@onereach/flow-sdk/types/index.js';\n\nexport class ThreadServiceWithData<\n TConfig extends CONFIG,\n TData extends IN<CONFIG> = IN<TConfig>,\n> extends BasicThreadService<TConfig> {\n protected readonly data: TData;\n\n constructor(thread: IThread<TConfig>, data: TData) {\n super(thread);\n this.data = data;\n }\n}\n","import type { IThreadId } from '@onereach/flow-sdk/types/index.js';\nimport { Memoize } from 'typescript-memoize';\n\nimport { ThreadServiceWithData } from '../../../../services/thread-service-with-data.ts';\nimport type { GenerateCallTelemetryConfig } from '../../types.ts';\n\nimport type { ConversationData } from './types.ts';\n\nexport class ConversationContext extends ThreadServiceWithData<GenerateCallTelemetryConfig> {\n public async getCallId(): Promise<string> {\n const data = await this.getConversationData();\n return data.id;\n }\n\n public async getConversationData(): Promise<ConversationData> {\n const { conversation } = this.data;\n\n const data = await this.fetchConversationData({\n conversation,\n conversationThread: this.dataThreadId,\n });\n if (!data || data._conv == undefined) throw new Error('Missing conversation data');\n return data;\n }\n\n /** id of the thread where conversation data is stored */\n public get dataThreadId(): IThreadId {\n const dataThreadId = this.data.conversationThread;\n return dataThreadId || this.thread.id;\n }\n\n @Memoize()\n private async fetchConversationData({\n conversation,\n conversationThread,\n }: {\n conversation: string;\n conversationThread: string;\n }): Promise<ConversationData | undefined> {\n const conversationDataThread = this.process.getSafeThread(conversationThread);\n // TODO: remove type cast (promise type)\n return await conversationDataThread.get<Promise<ConversationData>>(conversation);\n }\n}\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport type { IEvent } from '@onereach/flow-sdk/types/index.js';\nimport { Memoize } from 'typescript-memoize';\n\nimport { ErrorFilter } from '../../decorators/error-filter.ts';\nimport { validateFlowSdkVersion } from '../../utils/validate-flow-sdk-version.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { EventsAggregator } from '../events-aggregator/events-aggregator.ts';\n\nimport { ConversationContext } from './services/conversation-context/conversation-context.ts';\nimport { GenerateCallTelemetryConfig } from './types.ts';\n\nconst MINIMAL_FLOW_SDK_VERSION = '8.0.72';\n\nexport class GenerateCallTelemetryStep extends BaseStep<GenerateCallTelemetryConfig> {\n @ErrorFilter\n public async runStep(): Promise<void> {\n await validateFlowSdkVersion(MINIMAL_FLOW_SDK_VERSION);\n\n // TODO: wrap in a service\n this.triggers.local('ack', this.onAcknowledge);\n this.triggers.otherwise(this.initialize);\n }\n\n public async initialize(): Promise<void> {\n const conversationData = await this.conversationContext.getConversationData();\n await EventsAggregator.start(this.thread, conversationData);\n }\n\n public onAcknowledge(event: IEvent<{ context: unknown }, `ack`>): void {\n this.log.DEBUG?.('onAcknowledge event', event);\n\n this.exitStep('next', { context: event.params.context });\n }\n\n @Memoize()\n private get conversationContext(): ConversationContext {\n return new ConversationContext(this.thread, this.data);\n }\n}\n","import { install } from 'source-map-support';\n\nimport { EventsAggregator } from './threads/events-aggregator/events-aggregator.ts';\n\n// enable source map support for better error stack traces\ninstall();\n\nexport const states = {\n [EventsAggregator.class]: EventsAggregator,\n};\nexport { GenerateCallTelemetryStep as step } from './threads/main/step.ts';\n\nexport type * from './types.ts';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["defaultOptions","z","crypto"],"sources":["../src/errors/step-error.ts","../src/errors/error-filter.ts","../src/utils/create-method-decorator.ts","../src/decorators/background-thread-error-filter.ts","../src/decorators/error-filter.ts","../src/schemas/data-in.ts","../src/threads/base/base.ts","../src/threads/base/constants.ts","../src/threads/main/constants.ts","../src/threads/events-aggregator/constants.ts","../src/threads/events-aggregator/services/turns-aggregator/turns-aggregator.ts","../src/threads/events-aggregator/services/turns-manager/turns-manager.ts","../src/services/thread-service-with-data.ts","../src/threads/events-aggregator/services/voice/voice.ts","../src/threads/events-aggregator/events-aggregator.ts","../src/utils/validate-flow-sdk-version.ts","../src/threads/main/step.ts","../src/index.ts"],"sourcesContent":["import BaseError from '@onereach/flow-sdk/errors/base.js';\n\nexport const ErrorCode = {\n UNKNOWN: 'UNKNOWN',\n STEP_LOGIC_ISSUE: 'STEP_LOGIC_ISSUE',\n AUTH: 'AUTH',\n TIMEOUT: 'TIMEOUT',\n VALIDATION: 'VALIDATION',\n INVALID_REQUEST: 'INVALID_REQUEST',\n RATE_LIMITED: 'RATE_LIMITED',\n SERVER_ERROR: 'SERVER_ERROR',\n UNSUPPORTED: 'UNSUPPORTED',\n} as const;\n\nexport class GenerateCallTelemetryStepError extends BaseError<{\n code: keyof typeof ErrorCode;\n data?: unknown;\n}> {}\n\nexport class AbortRequestError extends BaseError {}\n","import TimeoutError from '@onereach/flow-sdk/errors/timeout.js';\nimport { z } from 'zod/v4-mini';\n\nimport { GenerateCallTelemetryStepError, ErrorCode } from './step-error.ts';\n\nconst defaultPreserveErrors = [GenerateCallTelemetryStepError, TimeoutError] as const;\nexport function errorFilter<P extends readonly AnyErrorClass[] = typeof defaultPreserveErrors>(\n error: unknown,\n options: ErrorFilterOptions<P> = {},\n): InstancesOf<P> | GenerateCallTelemetryStepError | TimeoutError {\n const {\n preserveErrors = defaultPreserveErrors,\n unknownMessage = 'Unknown error',\n unknownCode = ErrorCode.UNKNOWN,\n } = options;\n\n // if error is GenerateCallTelemetryStepError or TimeoutError, return it directly\n if (preserveErrors?.some((ErrorClass) => error instanceof ErrorClass)) {\n return error as InstancesOf<P>;\n }\n\n // validation errors\n if (error instanceof z.core.$ZodError) {\n return new GenerateCallTelemetryStepError(z.prettifyError(error), error, {\n code: ErrorCode.VALIDATION,\n });\n }\n\n // if error is a string assume it's an error message\n if (typeof error === 'string') {\n return new GenerateCallTelemetryStepError(error, {\n code: ErrorCode.UNKNOWN,\n });\n }\n\n if (error instanceof Error) {\n // timeout errors\n if (error.message.includes('Request timed out')) {\n return new TimeoutError('Timeout', error, { code: ErrorCode.TIMEOUT });\n }\n\n // TODO: fix interpreting of this kind of errors\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n const responseErrorMessage: string | undefined = (error as unknown as any)?.response?.data?.error?.message;\n if (responseErrorMessage != undefined) {\n return new GenerateCallTelemetryStepError(responseErrorMessage, error, {\n code: ErrorCode.SERVER_ERROR,\n });\n }\n\n return new GenerateCallTelemetryStepError(unknownMessage, error, {\n code: unknownCode,\n });\n }\n\n // catch all for unknown errors\n return new GenerateCallTelemetryStepError(unknownMessage, {\n code: unknownCode,\n data: error,\n });\n}\n\nexport type ErrorFilterOptions<P extends readonly AnyErrorClass[]> = {\n /** Array of error classes that should not be wrapped */\n preserveErrors?: P;\n /** Error message to use when message is unknown */\n unknownMessage?: string;\n /** Error code to use when message is unknown */\n unknownCode?: keyof typeof ErrorCode;\n};\n\n/** Any Error class */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyErrorClass<E extends Error = Error> = new (...arguments_: any[]) => E;\n\n/** Turn a tuple/array of constructors into a union of their instance types. */\nexport type InstancesOf<Ctors extends readonly AnyErrorClass[]> =\n Ctors[number] extends AnyErrorClass<infer I> ? I : never;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Creates a method decorator that can be used with or without options.\n * @param apply - Function that applies the decorator logic with given options.\n * @param defaultOptions - Default options to use if none are provided.\n */\nexport function createMethodDecoratorWithOptionalArguments<A, T extends AnyFunction = AnyFunction>(\n apply: (\n options: A,\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ) => T | TypedPropertyDescriptor<T> | void,\n defaultOptions: A,\n): MethodDecoratorWithOptionalArguments<A, T> {\n function runApply(\n options: A,\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ): TypedPropertyDescriptor<T> | void {\n const maybe = apply(options, target, propertyKey, descriptor);\n\n // If the decorator factory returned a wrapped function, assign it to the descriptor here\n if (typeof maybe === 'function') {\n const originalMethod = descriptor.value;\n const wrappedMethod = maybe as typeof originalMethod;\n\n if (originalMethod?.name != undefined) {\n try {\n Object.defineProperty(wrappedMethod, 'name', { value: originalMethod.name });\n } catch {\n // ignore if name is non-configurable\n }\n }\n\n descriptor.value = wrappedMethod;\n return descriptor;\n }\n\n // If a descriptor was returned or decorator mutated descriptor in-place, use that\n return maybe ?? descriptor;\n }\n\n return function decoratorOrFactory(\n argument0?: object | A,\n argument1?: string | symbol,\n argument2?: TypedPropertyDescriptor<T>,\n ): any {\n if (\n argument0 !== null &&\n typeof argument0 === 'object' &&\n (typeof argument1 === 'string' || typeof argument1 === 'symbol') &&\n argument2 !== null &&\n typeof argument2 === 'object'\n ) {\n // Called as plain decorator: @Decorator\n return runApply(defaultOptions, argument0, argument1, argument2);\n } else {\n // Called as decorator factory: @Decorator(options)\n const options = (argument0 as A) ?? defaultOptions;\n return (target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => {\n return runApply(options, target, propertyKey, descriptor);\n };\n }\n };\n}\n\nexport type AnyFunction = (...arguments_: any[]) => any;\n\nexport type MethodDecoratorWithOptionalArguments<A, T extends AnyFunction = AnyFunction> =\n // Plain method decorator (three arguments)\n ((\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ) => TypedPropertyDescriptor<T> | void) &\n // Decorator factory (optional options argument)\n ((options?: A) => MethodDecorator);\n","import type Step from '@onereach/flow-sdk/step.js';\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\n\nimport { errorFilter } from '../errors/error-filter.ts';\nimport { createMethodDecoratorWithOptionalArguments } from '../utils/create-method-decorator.ts';\n\nconst defaultOptions: BackgroundThreadErrorFilterOptions = { allowHandleError: false, useErrorFilter: true };\n\n/**\n * Since errors in hooks are fatal and can't be processed this decorator allows to wrap hook handler\n * and manage errors by ending a thread with the error (preventing sending error to `error` exit)\n * @param options.allowHandleError - Default `false`. If `false` in case of error will end thread with error as result, if `true` will allow to handle error via 'error' exit\n * @param options.useErrorFilter - Default `true`. If `true` every error wild be processed with `errorFilter` utility function\n */\nexport const BackgroundThreadErrorFilter = createMethodDecoratorWithOptionalArguments(\n (options, _target, propertyKey, descriptor) => {\n const originalMethod = descriptor.value;\n if (!originalMethod || typeof originalMethod !== 'function') return;\n\n return function (this: Step, ...arguments_: Parameters<typeof originalMethod>): ReturnType<typeof originalMethod> {\n try {\n const result: unknown = originalMethod.apply(this, arguments_);\n\n if (result instanceof Promise) {\n return result.catch((error) => errorHandler.call(this, options, error, propertyKey));\n }\n\n return result;\n } catch (error) {\n return errorHandler.call(this, options, error, propertyKey) as ReturnType<typeof originalMethod>;\n }\n } as typeof originalMethod;\n },\n defaultOptions,\n);\n\nfunction errorHandler(\n this: Step,\n options: BackgroundThreadErrorFilterOptions,\n error: unknown,\n propertyKey: string | symbol,\n): void {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n const filteredError = options.useErrorFilter ? errorFilter(error) : error;\n\n if (filteredError instanceof Error) {\n if (options.allowHandleError) {\n // Send it to the 'error' exit and stop here\n this.thread.enqueue({ name: ACTION.error, error: filteredError });\n return;\n } else {\n // End the thread with the error and stop here\n this.end(filteredError);\n return;\n }\n }\n\n // Only throw if it's not an Error instance and you truly want to bubble it\n throw filteredError;\n}\n\nexport type BackgroundThreadErrorFilterOptions = {\n allowHandleError?: boolean;\n useErrorFilter?: boolean;\n};\n","import type Step from '@onereach/flow-sdk/step.js';\n\nimport { errorFilter } from '../errors/error-filter.ts';\nimport { createMethodDecoratorWithOptionalArguments } from '../utils/create-method-decorator.ts';\n\nconst defaultOptions = {};\n\n/**\n * Will wrap method with `errorFilter` for every error.\n */\nexport const ErrorFilter = createMethodDecoratorWithOptionalArguments((_options, _target, propertyKey, descriptor) => {\n const originalMethod = descriptor.value;\n\n if (!originalMethod || typeof originalMethod !== 'function') return;\n\n return function (this: Step, ...arguments_: Parameters<typeof originalMethod>): ReturnType<typeof originalMethod> {\n try {\n const result: unknown = originalMethod.apply(this, arguments_);\n\n if (result instanceof Promise) {\n return result.catch((error: unknown) => {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n throw errorFilter(error);\n }) as ReturnType<typeof originalMethod>;\n }\n\n return result;\n } catch (error) {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n throw errorFilter(error);\n }\n };\n}, defaultOptions);\n","import * as z from 'zod/mini';\n\nz.config(z.locales.en());\n\n// string that prevents 'undefined' and 'null' values\nconst stringNoUndefinedSchema = z.string().check(\n z.trim(),\n z.refine((value) => !['undefined', 'null'].includes(value), {\n error: 'Unexpected undefined or null merge-field value',\n }),\n);\n\nexport const dataInSchema = z.object({\n conversation: stringNoUndefinedSchema.check(z.minLength(1)),\n conversationThread: stringNoUndefinedSchema,\n});\n\nexport type DataIn = z.infer<typeof dataInSchema>;\n\n// /**\n// * Convert empty string to undefined before running schema validation\n// * @param schema schema to validate against\n// * @param defaultValue optional default value\n// */\n// function optionalStringValue<T extends z.core.SomeType>(schema: T) {\n// return z.optional(\n// z.pipe(\n// z.union([z.undefined(), z.literal(''), schema]),\n// z.transform((value) => (value === '' ? undefined : value)),\n// ),\n// );\n// }\n","import Step from '@onereach/flow-sdk/step.js';\n\nimport { ErrorFilter } from '../../decorators/error-filter.ts';\nimport { dataInSchema } from '../../schemas/data-in.ts';\n\nimport type { BaseConfig } from './types.ts';\n\n// TODO: convert it into class decorator\nexport class BaseStep<T extends BaseConfig> extends Step<T> {\n @ErrorFilter\n public async resolveDataIn() {\n const dataIn = await super.resolveDataIn();\n return dataInSchema.parse(dataIn);\n }\n}\n","export const baseClassIdPrefix = 'vce_otel';\n","export const MINIMAL_FLOW_SDK_VERSION = '8.0.72';\n\nexport const mainEvents = {\n telemetryActivated: 'main_tel_act',\n} as const;\n","export const eventsAggregatorClassId = 'evt_aggr';\n\nexport const eventsAggregatorEvents = {\n refreshTurnContext: 'aggr_ctx_rsh',\n} as const;\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport crypto from 'node:crypto';\n\nimport type { EventsAggregatorConfig, VoiceEvent } from '../../types.ts';\n\nimport type { TurnsAggregatorState } from './types.ts';\n\n// const ttsMsgs: Record<string, { message: string; complete: boolean }> = {\n// 'a9a89135-90a0-42ab-b96e-a846a4930828': {\n// message: 'Hello! How can I assist you today?',\n// complete: true,\n// },\n// '8b20aa6d-5ab3-44d5-9e45-6e59ac1a2a08': {\n// message: 'My name is Alice. How can I help you today?',\n// complete: true,\n// },\n// 'c5ffec3b-c1c8-4029-b2e9-0543db2d0176': {\n// message: \"I don't have access to your name. Can you please tell me your name?\",\n// complete: true,\n// },\n// '823ef603-1dc3-4264-a399-ec7e25230b4a': {\n// message:\n// 'I’m sorry, I don’t have the ability to provide weather updates yet. Is there anything else I can help you with?',\n// complete: true,\n// },\n// };\n\nexport class TurnsAggregatorService extends BasicThreadService<EventsAggregatorConfig> {\n public static get statePlaceholder(): TurnsAggregatorState {\n return {\n rawEvents: [],\n turns: [],\n };\n }\n\n public addEvent(event: VoiceEvent): void {\n this.thread.state.rawEvents.push(event);\n\n let currentTurn = this.thread.state.turns.findLast((turn) => {\n return (\n (event.params.type?.startsWith?.('asr-input/') && turn.asrInputId === event.params?.inputId) ||\n (event.params.type?.startsWith?.('tts-audio/') &&\n turn.ttsContext?.turnId === event.params?.ttsContext?.turnId) ||\n (event.params.type === 'tts-audio/started' && turn.ttsStartedTimestamp == undefined)\n );\n });\n if (currentTurn == undefined) {\n if (this.thread.state.turns.length === 0 && event.params.type !== 'asr-input/started') {\n console.warn('Turn started without ASR input started event', event);\n }\n\n let id: string = event.params?.inputId ?? event.params?.ttsContext?.turnId ?? crypto.randomUUID();\n const startTimestamp = event.params.timestamp ?? Date.now();\n\n if (this.thread.state.turns.some((turn) => turn.id === id)) {\n console.warn('Turn already exists', { id, event });\n id = crypto.randomUUID();\n }\n\n currentTurn = {\n id,\n finished: false,\n startTimestamp,\n\n // events: [],\n // asrEvents: [],\n // ttsEvents: [],\n // stage: 'init',\n\n endTimestamp: undefined,\n\n asrInputId: undefined,\n asrStartedTimestamp: undefined,\n asrEndedTimestamp: undefined,\n asrProcessedTimestamp: undefined,\n asrConfidenceScore: undefined,\n asrRecognitionText: undefined,\n asrProvider: undefined,\n asrUsageMeta: undefined,\n\n ttsStartedTimestamp: undefined,\n ttsEndedTimestamp: undefined,\n ttsEndedReason: undefined,\n ttsInterruptedAfterText: undefined,\n ttsProvider: undefined,\n ttsContext: undefined,\n };\n this.thread.state.turns.push(currentTurn);\n // this.turnsMap.set(id, currentTurn);\n }\n\n // currentTurn.events.push(event);\n\n switch (event.params.type) {\n case 'asr-input/started': {\n if (currentTurn.asrInputId && currentTurn.asrInputId !== event.params.inputId) {\n console.warn('ASR input started for wrong input', {\n expected: currentTurn.asrInputId,\n actual: event.params.inputId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('asr-input-started-for-wrong-input');\n }\n currentTurn.asrInputId = event.params.inputId;\n currentTurn.asrStartedTimestamp = event.params.timestamp;\n // currentTurn.asrEvents.push(event);\n // currentTurn.stage = 'input';\n break;\n }\n case 'asr-input/ended': {\n if (currentTurn.asrInputId && currentTurn.asrInputId !== event.params.inputId) {\n console.warn('ASR input ended for wrong input', {\n expected: currentTurn.asrInputId,\n actual: event.params.inputId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('asr-input-ended-for-wrong-input');\n }\n currentTurn.asrEndedTimestamp = event.params.timestamp;\n // currentTurn.asrEvents.push(event);\n break;\n }\n case 'asr-input/processed': {\n if (currentTurn.asrInputId !== event.params.inputId) {\n console.warn('ASR input processed for wrong input', {\n expected: currentTurn.asrInputId,\n actual: event.params.inputId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('asr-input-processed-for-wrong-input');\n }\n currentTurn.asrProcessedTimestamp = event.params.timestamp;\n currentTurn.asrConfidenceScore = event.params.confidenceScore;\n currentTurn.asrRecognitionText = event.params.phrase?.text;\n currentTurn.asrProvider = event.params.asrProvider;\n currentTurn.asrUsageMeta = event.params.asrUsageMeta;\n // currentTurn.asrEvents.push(event);\n break;\n }\n\n case 'tts-audio/started': {\n if (currentTurn.ttsContext?.turnId && currentTurn.ttsContext?.turnId !== event.params.ttsContext?.turnId) {\n console.warn('TTS audio started for wrong turn id', {\n expected: currentTurn.ttsContext?.turnId,\n actual: event.params.ttsContext?.turnId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('tts-audio-started-for-wrong-message');\n }\n currentTurn.ttsProvider = event.params.ttsProvider;\n currentTurn.ttsContext = event.params.ttsContext;\n currentTurn.ttsStartedTimestamp = event.params.timestamp;\n // currentTurn.ttsEvents.push(event);\n // currentTurn.stage = 'output';\n break;\n }\n case 'tts-audio/interrupted': {\n if (currentTurn.ttsContext?.turnId && currentTurn.ttsContext?.turnId !== event.params.ttsContext?.turnId) {\n console.warn('TTS audio interrupted for wrong turn id', {\n expected: event.params.ttsContext?.turnId,\n actual: event.params.ttsContext?.turnId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('tts-audio-interrupted-for-wrong-message');\n }\n currentTurn.ttsInterruptedAfterText = event.params.partialText;\n currentTurn.ttsEndedReason = 'interrupted';\n currentTurn.ttsEndedTimestamp = event.params.timestamp;\n // currentTurn.ttsMessage = ttsMsgs[currentTurn.ttsContext?.turnId as string]?.message;\n currentTurn.endTimestamp = event.params.timestamp;\n\n currentTurn.finished = true;\n\n // currentTurn.ttsEvents.push(event);\n break;\n }\n case 'tts-audio/ended': {\n if (currentTurn.ttsContext?.turnId && currentTurn.ttsContext?.turnId !== event.params.ttsContext?.turnId) {\n console.warn('TTS audio interrupted for wrong turn id', {\n expected: event.params.ttsContext?.turnId,\n actual: event.params.ttsContext?.turnId,\n event,\n });\n currentTurn.damaged = true;\n currentTurn.damagedReasons ??= [];\n currentTurn.damagedReasons.push('tts-audio-ended-for-wrong-message');\n }\n currentTurn.ttsEndedReason = 'ended';\n currentTurn.ttsEndedTimestamp = event.params.timestamp;\n // currentTurn.ttsMessage = ttsMsgs[currentTurn.ttsContext?.turnId as string]?.message;\n currentTurn.endTimestamp = event.params.timestamp;\n\n currentTurn.finished = true;\n\n // currentTurn.ttsEvents.push(event);\n // currentTurn.stage = 'complete';\n // currentTurn = undefined;\n break;\n }\n\n default: {\n this.log.WARN?.('Unknown event type', event);\n }\n }\n }\n}\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\n\nimport { EventsAggregatorConfig } from '../../types.ts';\n\nimport { TurnsManagerContext, TurnsManagerState } from './types.ts';\n\nexport class TurnsManagerService extends BasicThreadService<EventsAggregatorConfig> {\n public static get statePlaceholder(): TurnsManagerState {\n return {\n turn: {\n turnId: '',\n turnIndex: -1,\n },\n turnsContextMap: {},\n };\n }\n\n public async initializeTurnContext(): Promise<void> {\n if (this.thread.state.turn.turnId !== '') {\n this.thread.log.WARN?.(`Turn context already initialized. Skipping initialization.`);\n return;\n }\n\n this.thread.log.DEBUG?.(`Initializing turn context`);\n this.updateTurnContext();\n await this.refreshStepDataOut();\n }\n\n public async refreshTurnContext(): Promise<void> {\n if (this.thread.state.turn.turnId === '') {\n this.thread.log.WARN?.(`Turn context was not initialized. Initializing new turn context.`);\n await this.initializeTurnContext();\n return;\n }\n\n this.thread.log.DEBUG?.(`Refreshing turn context`);\n this.updateTurnContext();\n await this.refreshStepDataOut();\n }\n\n private updateTurnContext(): void {\n const turnId = crypto.randomUUID();\n const turnIndex = (this.thread.state.turn.turnIndex ?? -1) + 1;\n const context: TurnsManagerContext = {\n turnId,\n turnIndex,\n };\n this.thread.state.turn = context;\n this.thread.state.turnsContextMap[turnId] = context;\n }\n\n private async refreshStepDataOut(): Promise<void> {\n // refresh step data out to have new context\n await this.thread.setDataOut({\n context: this.thread.state.turn,\n });\n }\n}\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport type { CONFIG, IN, IThread } from '@onereach/flow-sdk/types/index.js';\n\nexport class ThreadServiceWithData<\n TConfig extends CONFIG,\n TData extends IN<CONFIG> = IN<TConfig>,\n> extends BasicThreadService<TConfig> {\n protected readonly data: TData;\n\n constructor(thread: IThread<TConfig>, data: TData) {\n super(thread);\n this.data = data;\n }\n}\n","import type { IThreadId } from '@onereach/flow-sdk/types/index.js';\n\nimport { ErrorCode, GenerateCallTelemetryStepError } from '../../../../errors/step-error.ts';\nimport { ThreadServiceWithData } from '../../../../services/thread-service-with-data.ts';\nimport type { EventsAggregatorConfig } from '../../types.ts';\n\nimport type { ConversationData, ConversationParameters } from './types.ts';\n\nexport class VoiceService extends ThreadServiceWithData<EventsAggregatorConfig> {\n /** Fetch conversation data from the conversation data thread */\n public async getConversationData({ force }: { force?: boolean } = {}): Promise<ConversationData> {\n const voiceConversation = this.thread.state.conversation;\n if (voiceConversation && force !== true) return voiceConversation;\n\n const { conversation } = this.data;\n\n const conversationParameters: ConversationParameters = {\n conversation,\n conversationThread: this.conversationThreadId,\n };\n const data = await this.fetchConversationData(conversationParameters);\n if (!data || data._conv == undefined) {\n throw new GenerateCallTelemetryStepError('Missing conversation data', {\n code: ErrorCode.VALIDATION,\n data: conversationParameters,\n });\n }\n\n this.thread.state.conversation = data;\n\n return data;\n }\n\n /** Enable telemetry for the phone call */\n public async enableTelemetry(): Promise<void> {\n if (!this.thread.state.conversation) {\n throw new GenerateCallTelemetryStepError('Conversation data is not available', {\n code: ErrorCode.VALIDATION,\n });\n }\n\n const { id, type, callback } = this.thread.state.conversation;\n\n const event = {\n target: this.thread.helpers.providersAccountId,\n name: `out/voice/${type}`,\n params: {\n id,\n async: true,\n hbs: 99, // heartbeat seconds\n commands: [\n {\n name: 'start-telemetry',\n params: { ack: true }, // expect acknowledge from voicer\n },\n ],\n step: {\n key: this.session.key,\n trd: this.thread.id,\n },\n },\n\n reporting: {\n ...this.session.getSessionRef(),\n },\n };\n\n this.log.DEBUG?.('startTelemetry event', event);\n\n const result = await this.thread.eventManager.emit(event, {\n target: callback,\n invocationType: 'async',\n timeout: 5000,\n });\n this.log.DEBUG?.('startTelemetry result', result);\n\n if (result == undefined) {\n // TODO: test how parent thread will react on this error\n throw new GenerateCallTelemetryStepError('Failed to start telemetry', {\n code: ErrorCode.SERVER_ERROR,\n data: event,\n });\n }\n }\n\n /** Maximum timestamp in milliseconds before the heartbeat is expected */\n public get expectHeartbeatBefore(): number {\n return Date.now() + 300_000;\n }\n\n /** Called when the heartbeat is not received before the deadline */\n public onHeartbeatTimeout(): void {\n this.log.WARN?.('Heartbeat was not received before the deadline');\n this.thread.end();\n }\n\n /** id of the thread where conversation data is stored */\n private get conversationThreadId(): IThreadId {\n const { conversationThread } = this.data;\n return conversationThread || this.thread.state.parentThreadId;\n }\n\n /** Fetch conversation data from the conversation data thread */\n private async fetchConversationData({\n conversation,\n conversationThread,\n }: ConversationParameters): Promise<ConversationData | undefined> {\n const conversationDataThread = this.process.getSafeThread(conversationThread);\n return await conversationDataThread.get<Promise<ConversationData>>(conversation);\n }\n}\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport type { IThreadId, IThread, IStepId } from '@onereach/flow-sdk/types/index.js';\nimport { Memoize } from 'typescript-memoize';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport { mainEvents } from '../main/constants.ts';\nimport type { GenerateCallTelemetryConfig, MainEventTelemetryActivated } from '../main/types.ts';\n\nimport { eventsAggregatorClassId, eventsAggregatorEvents } from './constants.ts';\nimport { TurnsAggregatorService } from './services/turns-aggregator/turns-aggregator.ts';\nimport { TurnsManagerService } from './services/turns-manager/turns-manager.ts';\nimport type { VoiceEvent } from './services/voice/types.ts';\nimport { VoiceService } from './services/voice/voice.ts';\nimport type { EventsAggregatorConfig } from './types.ts';\n\nexport class EventsAggregator extends BaseStep<EventsAggregatorConfig> {\n public static readonly class = eventsAggregatorClassId;\n\n public static async start(thread: IThread<GenerateCallTelemetryConfig>): Promise<void> {\n const interceptorThreadId = this.getThreadId(thread.step.id);\n const interceptorThread = thread.process.getThread<EventsAggregatorConfig>(interceptorThreadId);\n\n if (interceptorThread != undefined) return;\n\n // create thread\n await thread.process.runThread<EventsAggregatorConfig>({\n id: interceptorThreadId,\n background: true,\n state: {\n ...TurnsManagerService.statePlaceholder,\n ...TurnsAggregatorService.statePlaceholder,\n\n step: thread.step.id,\n class: this.class,\n\n parentThreadId: thread.id,\n },\n });\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // -------------------------------------\n\n @BackgroundThreadErrorFilter\n public async runStep(): Promise<void> {\n const { id } = await this.voiceService.getConversationData();\n\n this.triggers.local(`in/voice/${id}`, this.onVoiceEvent);\n this.triggers.local(eventsAggregatorEvents.refreshTurnContext, this.onRefreshTurnContext);\n this.triggers.deadline(this.voiceService.expectHeartbeatBefore, this.onDeadline);\n this.triggers.otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n public onVoiceEvent(event: VoiceEvent): void {\n this.log.DEBUG?.('onVoiceEvent', event);\n\n // TODO: validate event based on zod schema\n\n switch (event.params.type) {\n case 'ack': {\n void this.resumeParentThread();\n break;\n }\n\n case 'tts-audio/started':\n case 'tts-audio/finished':\n case 'tts-audio/interrupted':\n case 'asr-input/started':\n case 'asr-input/ended':\n case 'asr-input/processed': {\n this.turnsAggregatorService.addEvent(event);\n break;\n }\n\n case 'hangup': {\n const { turns, rawEvents } = this.state;\n this.log.WARN?.('Hangup event received', { turns, rawEvents });\n // TODO: end EventsAggregator thread\n break;\n }\n\n case 'heartbeat': {\n // do nothing\n break;\n }\n\n default: {\n this.log.WARN?.('Unexpected type of event', event);\n }\n }\n }\n\n @BackgroundThreadErrorFilter\n public async initialize(): Promise<void> {\n this.log.DEBUG?.('Initializing EventsAggregator thread');\n await this.turnsManagerService.initializeTurnContext();\n await this.voiceService.enableTelemetry();\n }\n\n @BackgroundThreadErrorFilter\n public onDeadline(): void {\n this.voiceService.onHeartbeatTimeout();\n }\n\n @BackgroundThreadErrorFilter\n public async onRefreshTurnContext(): Promise<void> {\n await this.turnsManagerService.refreshTurnContext();\n }\n\n private async resumeParentThread(): Promise<void> {\n const event: MainEventTelemetryActivated = {\n name: mainEvents.telemetryActivated,\n params: { turn: this.state.turn },\n thread: this.state.parentThreadId,\n };\n await this.process.enqueueAndRun(event);\n }\n\n private get voiceService(): VoiceService {\n return new VoiceService(this.thread, this.data);\n }\n\n @Memoize()\n private get turnsManagerService(): TurnsManagerService {\n return new TurnsManagerService(this.thread);\n }\n\n @Memoize()\n private get turnsAggregatorService(): TurnsAggregatorService {\n return new TurnsAggregatorService(this.thread);\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\nexport async function validateFlowSdkVersion(minVersion: string): Promise<void> {\n if (typeof minVersion !== 'string' || !/^\\d+\\.\\d+\\.\\d+$/.test(minVersion)) {\n throw new Error(`Invalid minimum version format: ${minVersion}`);\n }\n\n const packageJsonPath = require.resolve('@onereach/flow-sdk/package.json');\n if (!packageJsonPath) {\n throw new Error(`Could not find package.json for @onereach/flow-sdk`);\n }\n // Read the package.json file to get the version\n const packageJsonContent = await readFile(packageJsonPath, 'utf8');\n\n const { version } = JSON.parse(packageJsonContent) as { version: string };\n const { groups } = /^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)/.exec(version) || {};\n\n if (!groups) throw new Error(`Invalid Flow SDK version format: ${version}`);\n\n const major = Number.parseInt(groups.major ?? '0', 10);\n const minor = Number.parseInt(groups.minor ?? '0', 10);\n const patch = Number.parseInt(groups.patch ?? '0', 10);\n\n if (\n major == undefined ||\n minor == undefined ||\n patch == undefined ||\n Number.isNaN(major) ||\n Number.isNaN(minor) ||\n Number.isNaN(patch)\n ) {\n throw new Error(`Invalid version format: ${version}`);\n }\n\n const [minMajor, minMinor, minPatch] = minVersion.split('.').map((x) => Number.parseInt(x, 10));\n\n if (\n minMajor == undefined ||\n minMinor == undefined ||\n minPatch == undefined ||\n Number.isNaN(minMajor) ||\n Number.isNaN(minMinor) ||\n Number.isNaN(minPatch)\n ) {\n throw new Error(`Invalid minimum version format: ${minVersion}`);\n }\n\n if (\n major < minMajor ||\n (major === minMajor && minor < minMinor) ||\n (major === minMajor && minor === minMinor && patch < minPatch)\n ) {\n throw new Error(\n `Flow SDK version '${version}' is lower than required minimum version '${minVersion}' for the step`,\n );\n }\n}\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport { performance } from 'node:perf_hooks';\n\nimport { ErrorFilter } from '../../decorators/error-filter.ts';\nimport { validateFlowSdkVersion } from '../../utils/validate-flow-sdk-version.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { EventsAggregator } from '../events-aggregator/events-aggregator.ts';\n\nimport { mainEvents, MINIMAL_FLOW_SDK_VERSION } from './constants.ts';\nimport type { GenerateCallTelemetryConfig, MainEventTelemetryActivated } from './types.ts';\n\nexport class GenerateCallTelemetryStep extends BaseStep<GenerateCallTelemetryConfig> {\n @ErrorFilter\n public async runStep(): Promise<void> {\n await validateFlowSdkVersion(MINIMAL_FLOW_SDK_VERSION);\n\n this.triggers.local(mainEvents.telemetryActivated, this.onTelemetryActivated);\n this.triggers.otherwise(this.initialize);\n }\n\n public async initialize(): Promise<void> {\n this.state.activationStart = performance.now();\n await EventsAggregator.start(this.thread);\n }\n\n public onTelemetryActivated(event: MainEventTelemetryActivated): void {\n const activationMs = performance.now() - this.state.activationStart;\n this.log.DEBUG?.('onTelemetryActivated', { event, activationMs });\n\n this.exitStep('next', { turn: event.params.turn });\n }\n}\n","import { install } from 'source-map-support';\n\nimport { EventsAggregator } from './threads/events-aggregator/events-aggregator.ts';\n\n// enable source map support for better error stack traces\ninstall();\n\nexport const states = {\n [EventsAggregator.class]: EventsAggregator,\n};\nexport { GenerateCallTelemetryStep as step } from './threads/main/step.ts';\n\nexport type * from './types.ts';\n"],"mappings":"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"}
|