@onereach/step-generate-call-telemetry 0.0.2-rc.4 → 0.0.2-rc.6
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 +20 -16
- 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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CONFIG, ICallback, IEvent, IStepId, IThread, IThreadId } from "@onereach/flow-sdk/types/index.js";
|
|
2
2
|
import Step from "@onereach/flow-sdk/step.js";
|
|
3
3
|
import * as z from "zod/mini";
|
|
4
4
|
|
|
@@ -77,7 +77,7 @@ type VoiceTurn = {
|
|
|
77
77
|
};
|
|
78
78
|
};
|
|
79
79
|
type TurnsAggregatorState = {
|
|
80
|
-
/** raw intercepted events */rawEvents:
|
|
80
|
+
/** raw intercepted events */rawEvents: VoiceEvent[]; /** aggregated voice turns */
|
|
81
81
|
turns: VoiceTurn[];
|
|
82
82
|
};
|
|
83
83
|
//#endregion
|
|
@@ -85,7 +85,7 @@ type TurnsAggregatorState = {
|
|
|
85
85
|
type EventsAggregatorEventName = typeof eventsAggregatorEvents;
|
|
86
86
|
type EventsAggregatorEventRefreshContext = IEvent<unknown, EventsAggregatorEventName['refreshTurnContext']>;
|
|
87
87
|
type EventsAggregatorEvent = EventsAggregatorEventRefreshContext;
|
|
88
|
-
type
|
|
88
|
+
type VoiceEventParameters = {
|
|
89
89
|
type?: string;
|
|
90
90
|
[key: string]: unknown;
|
|
91
91
|
timestamp?: number;
|
|
@@ -105,38 +105,42 @@ type InterceptedEventParameters = {
|
|
|
105
105
|
languageCode?: string;
|
|
106
106
|
};
|
|
107
107
|
};
|
|
108
|
-
type
|
|
108
|
+
type VoiceEvent = IEvent<VoiceEventParameters, `in/voice/${string}`>;
|
|
109
|
+
type VoiceConversation = {
|
|
110
|
+
id: string;
|
|
111
|
+
type: string;
|
|
112
|
+
callback: ICallback;
|
|
113
|
+
};
|
|
109
114
|
type EventsAggregatorState = {
|
|
110
|
-
class: typeof eventsAggregatorClassId;
|
|
111
|
-
|
|
115
|
+
class: typeof eventsAggregatorClassId;
|
|
116
|
+
parentThreadId: IThreadId;
|
|
117
|
+
voiceConversation: VoiceConversation;
|
|
112
118
|
} & ContextManagerState & TurnsAggregatorState;
|
|
113
|
-
type EventsAggregatorLocal = {
|
|
114
|
-
disableHookEvents: boolean;
|
|
115
|
-
};
|
|
116
119
|
interface EventsAggregatorConfig extends BaseConfig {
|
|
117
120
|
state: EventsAggregatorState;
|
|
118
|
-
local: EventsAggregatorLocal;
|
|
119
121
|
events: EventsAggregatorEvent;
|
|
120
122
|
}
|
|
121
123
|
//#endregion
|
|
122
124
|
//#region src/threads/events-aggregator/events-aggregator.d.ts
|
|
123
125
|
declare class EventsAggregator extends BaseStep<EventsAggregatorConfig> {
|
|
124
126
|
static readonly class = "evt_aggr";
|
|
125
|
-
static start(thread: IThread<GenerateCallTelemetryConfig>,
|
|
127
|
+
static start(thread: IThread<GenerateCallTelemetryConfig>, voiceConversation: VoiceConversation): Promise<void>;
|
|
126
128
|
static getThreadId(stepId: IStepId): IThreadId;
|
|
129
|
+
onVoiceEvent(event: VoiceEvent): Promise<void>;
|
|
130
|
+
private startTelemetry;
|
|
127
131
|
runStep(): void;
|
|
128
132
|
initialize(): Promise<void>;
|
|
129
|
-
onTelemetryEvent(event: InterceptedEvent): void;
|
|
130
|
-
onEventAction(eventAction: IActionEvent<AnyConfig, ACTION.event>): void;
|
|
131
133
|
onRefreshTurnContext(): Promise<void>;
|
|
132
|
-
private shouldInterceptEvent;
|
|
133
134
|
private get contextManagerService();
|
|
134
|
-
private get turnsAggregatorService();
|
|
135
135
|
}
|
|
136
136
|
//#endregion
|
|
137
137
|
//#region src/threads/main/step.d.ts
|
|
138
138
|
declare class GenerateCallTelemetryStep extends BaseStep<GenerateCallTelemetryConfig> {
|
|
139
139
|
runStep(): Promise<void>;
|
|
140
|
+
initialize(): Promise<void>;
|
|
141
|
+
onAcknowledge(event: IEvent<{
|
|
142
|
+
context: unknown;
|
|
143
|
+
}, `ack`>): void;
|
|
140
144
|
private get conversationContext();
|
|
141
145
|
}
|
|
142
146
|
//#endregion
|
|
@@ -145,5 +149,5 @@ declare const states: {
|
|
|
145
149
|
evt_aggr: typeof EventsAggregator;
|
|
146
150
|
};
|
|
147
151
|
//#endregion
|
|
148
|
-
export { BaseConfig, ContextManagerContext, ContextManagerState, ContextManagerTurnId, DataIn, EventsAggregatorConfig, EventsAggregatorEvent, EventsAggregatorEventName, EventsAggregatorEventRefreshContext,
|
|
152
|
+
export { BaseConfig, ContextManagerContext, ContextManagerState, ContextManagerTurnId, DataIn, EventsAggregatorConfig, EventsAggregatorEvent, EventsAggregatorEventName, EventsAggregatorEventRefreshContext, EventsAggregatorState, GenerateCallTelemetryConfig, VoiceConversation, VoiceEvent, VoiceEventParameters, dataInSchema, states, GenerateCallTelemetryStep as step };
|
|
149
153
|
//# 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/main/types.ts","../src/threads/events-aggregator/constants.ts","../src/threads/events-aggregator/services/context-manager/types.ts","../src/threads/events-aggregator/services/turns-aggregator/types.ts","../src/threads/events-aggregator/types.ts","../src/threads/events-aggregator/events-aggregator.ts","../src/threads/main/step.ts","../src/index.ts"],"mappings":";;;;;cAYa,YAAA,EAAY,CAAA,CAAA,aAAA;;;;KAKb,MAAA,GAAS,CAAA,CAAE,KAAA,QAAa,YAAA;;;UCbnB,UAAA,SAAmB,MAAA;EAClC,MAAA,EAAQ,MAAA;AAAA;;;cCGG,QAAA,WAAmB,UAAA,UAAoB,IAAA,CAAK,CAAA;EAE1C,aAAA,CAAA,GAAa,OAAA;;;;;;;UCNX,2BAAA,SAAoC,MAAA;EACnD,MAAA,EAAQ,MAAA;AAAA;;;cCLG,uBAAA;AAAA,cAEA,sBAAA;EAAA,SAEH,kBAAA;AAAA;;;KCJE,oBAAA;AAAA,KACA,qBAAA;EACV,MAAA,EAAQ,oBAAA;EACR,SAAA;AAAA;AAAA,KAGU,mBAAA;EACV,OAAA,EAAS,qBAAA;EACT,eAAA,EAAiB,MAAA,CAAO,oBAAA,EAAsB,qBAAA;AAAA;;;KCApC,SAAA;EACV,EAAA;EACA,QAAA;EACA,cAAA;EACA,YAAA;EAKA,OAAA;EACA,cAAA;EAEA,UAAA;EACA,mBAAA;EACA,iBAAA;EACA,qBAAA;EACA,kBAAA;EACA,kBAAA;EACA,WAAA;EACA,YAAA;IACE,QAAA;IACA,OAAA;IACA,YAAA;IACA,UAAA;EAAA;EAGF,mBAAA;EACA,iBAAA;EACA,cAAA;EACA,UAAA;EACA,uBAAA;EACA,WAAA;EACA,UAAA;IACE,MAAA;IACA,SAAA;EAAA;AAAA;AAAA,KAMQ,oBAAA;EN/BwB,6BMiClC,SAAA,EAAW,
|
|
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/main/types.ts","../src/threads/events-aggregator/constants.ts","../src/threads/events-aggregator/services/context-manager/types.ts","../src/threads/events-aggregator/services/turns-aggregator/types.ts","../src/threads/events-aggregator/types.ts","../src/threads/events-aggregator/events-aggregator.ts","../src/threads/main/step.ts","../src/index.ts"],"mappings":";;;;;cAYa,YAAA,EAAY,CAAA,CAAA,aAAA;;;;KAKb,MAAA,GAAS,CAAA,CAAE,KAAA,QAAa,YAAA;;;UCbnB,UAAA,SAAmB,MAAA;EAClC,MAAA,EAAQ,MAAA;AAAA;;;cCGG,QAAA,WAAmB,UAAA,UAAoB,IAAA,CAAK,CAAA;EAE1C,aAAA,CAAA,GAAa,OAAA;;;;;;;UCNX,2BAAA,SAAoC,MAAA;EACnD,MAAA,EAAQ,MAAA;AAAA;;;cCLG,uBAAA;AAAA,cAEA,sBAAA;EAAA,SAEH,kBAAA;AAAA;;;KCJE,oBAAA;AAAA,KACA,qBAAA;EACV,MAAA,EAAQ,oBAAA;EACR,SAAA;AAAA;AAAA,KAGU,mBAAA;EACV,OAAA,EAAS,qBAAA;EACT,eAAA,EAAiB,MAAA,CAAO,oBAAA,EAAsB,qBAAA;AAAA;;;KCApC,SAAA;EACV,EAAA;EACA,QAAA;EACA,cAAA;EACA,YAAA;EAKA,OAAA;EACA,cAAA;EAEA,UAAA;EACA,mBAAA;EACA,iBAAA;EACA,qBAAA;EACA,kBAAA;EACA,kBAAA;EACA,WAAA;EACA,YAAA;IACE,QAAA;IACA,OAAA;IACA,YAAA;IACA,UAAA;EAAA;EAGF,mBAAA;EACA,iBAAA;EACA,cAAA;EACA,UAAA;EACA,uBAAA;EACA,WAAA;EACA,UAAA;IACE,MAAA;IACA,SAAA;EAAA;AAAA;AAAA,KAMQ,oBAAA;EN/BwB,6BMiClC,SAAA,EAAW,UAAA,INjCmC;EMoC9C,KAAA,EAAO,SAAA;AAAA;;;KC1CG,yBAAA,UAAmC,sBAAA;AAAA,KACnC,mCAAA,GAAsC,MAAA,UAAgB,yBAAA;AAAA,KACtD,qBAAA,GAAwB,mCAAA;AAAA,KAGxB,oBAAA;EAEV,IAAA;EAAA,CACC,GAAA;EAGD,SAAA;EACA,UAAA,GAAa,qBAAA;EACb,WAAA;EACA,WAAA;EACA,YAAA,GAAe,MAAA;EAGf,OAAA;EACA,eAAA;EACA,MAAA;IACE,IAAA;EAAA;EAEF,WAAA;EACA,YAAA;IACE,QAAA;IACA,OAAA;IACA,YAAA;EAAA;AAAA;AAAA,KAGQ,UAAA,GAAa,MAAA,CAAO,oBAAA;AAAA,KAEpB,iBAAA;EACV,EAAA;EACA,IAAA;EACA,QAAA,EAAU,SAAA;AAAA;AAAA,KAGA,qBAAA;EACV,KAAA,SAAc,uBAAA;EAEd,cAAA,EAAgB,SAAA;EAChB,iBAAA,EAAmB,iBAAA;AAAA,IACjB,mBAAA,GACF,oBAAA;AAAA,UAGe,sBAAA,SAA+B,UAAA;EAC9C,KAAA,EAAO,qBAAA;EACP,MAAA,EAAQ,qBAAA;AAAA;;;cC5CG,gBAAA,SAAyB,QAAA,CAAS,sBAAA;EAAA,gBACtB,KAAA;EAAA,OAEH,KAAA,CAClB,MAAA,EAAQ,OAAA,CAAQ,2BAAA,GAChB,iBAAA,EAAmB,iBAAA,GAClB,OAAA;EAAA,OA0BW,WAAA,CAAY,MAAA,EAAQ,OAAA,GAAU,SAAA;EAM/B,YAAA,CAAa,KAAA,EAAO,UAAA,GAAa,OAAA;EAAA,QA8BhC,cAAA;EAgDP,OAAA,CAAA;EAQM,UAAA,CAAA,GAAc,OAAA;EAsBd,oBAAA,CAAA,GAAwB,OAAA;EAAA,YAUzB,qBAAA,CAAA;AAAA;;;cC7JD,yBAAA,SAAkC,QAAA,CAAS,2BAAA;EAEzC,OAAA,CAAA,GAAW,OAAA;EAQX,UAAA,CAAA,GAAc,OAAA;EAKpB,aAAA,CAAc,KAAA,EAAO,MAAA;IAAS,OAAA;EAAA;EAAA,YAOzB,mBAAA,CAAA;AAAA;;;cC9BD,MAAA;mBAEZ,gBAAA;AAAA"}
|
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{ACTION as n}from"@onereach/flow-sdk/types/index.js";import{Memoize as r}from"typescript-memoize";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,r){let i=r.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:n.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,A=class extends w{static class=`evt_aggr`;static async start(e,t){if(!t||typeof t!=`string`)throw Error(`Call ID is required`);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,callId:t},local:{disableHookEvents:!0}})}static getThreadId(e){return`vce_otel_${this.class}_${e}`}runStep(){this.triggers.hook({name:n.event,thread:`*`},this.onEventAction),this.triggers.local(`otel/voice/${this.state.callId}`,this.onTelemetryEvent),this.triggers.local(T.refreshTurnContext,this.onRefreshTurnContext),this.triggers.otherwise(this.initialize)}async initialize(){this.log.DEBUG?.(`Initializing EventsAggregator thread`),await this.contextManagerService.initializeTurnContext()}onTelemetryEvent(e){this.log.WARN?.(`>>>Telemetry event`,e)}onEventAction(e){let t=e?.params?.action?.event;!t||!this.shouldInterceptEvent(t)||(this.log.DEBUG?.(`Aggregating event...`,t),this.turnsAggregatorService.addEvent(t))}async onRefreshTurnContext(){await this.contextManagerService.refreshTurnContext()}shouldInterceptEvent(e){return!e||!e.name?.startsWith?.(`in/voice/`)?!1:!!(e.params?.type?.startsWith?.(`tts-audio/`)||e.params?.type?.startsWith?.(`asr-input/`))}get contextManagerService(){return new E(this.thread)}get turnsAggregatorService(){return new D(this.thread)}};C([_,S(`design:type`,Function),S(`design:paramtypes`,[]),S(`design:returntype`,void 0)],A.prototype,`runStep`,null),C([_,S(`design:type`,Function),S(`design:paramtypes`,[]),S(`design:returntype`,Promise)],A.prototype,`initialize`,null),C([_,S(`design:type`,Function),S(`design:paramtypes`,[Object]),S(`design:returntype`,void 0)],A.prototype,`onTelemetryEvent`,null),C([_,S(`design:type`,Function),S(`design:paramtypes`,[Object]),S(`design:returntype`,void 0)],A.prototype,`onEventAction`,null),C([_,S(`design:type`,Function),S(`design:paramtypes`,[]),S(`design:returntype`,Promise)],A.prototype,`onRefreshTurnContext`,null),C([r(),S(`design:type`,typeof(O=E!==void 0&&E)==`function`?O:Object),S(`design:paramtypes`,[])],A.prototype,`contextManagerService`,null),C([r(),S(`design:type`,typeof(k=D!==void 0&&D)==`function`?k:Object),S(`design:paramtypes`,[])],A.prototype,`turnsAggregatorService`,null);const j=e(import.meta.url);async function M(e){if(typeof e!=`string`||!/^\d+\.\d+\.\d+$/.test(e))throw Error(`Invalid minimum version format: ${e}`);let t=j.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 N=class extends l{data;constructor(e,t){super(e),this.data=t}},P=class extends N{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([r(),S(`design:type`,Function),S(`design:paramtypes`,[Object]),S(`design:returntype`,Promise)],P.prototype,`fetchConversationData`,null);var F,I=class extends w{async runStep(){await M(`8.0.72`);let e=await this.conversationContext.getCallId();await A.start(this.thread,e),this.exitStep(`next`,{context:{}})}get conversationContext(){return new P(this.thread,this.data)}};C([y,S(`design:type`,Function),S(`design:paramtypes`,[]),S(`design:returntype`,Promise)],I.prototype,`runStep`,null),C([r(),S(`design:type`,typeof(F=P!==void 0&&P)==`function`?F:Object),S(`design:paramtypes`,[])],I.prototype,`conversationContext`,null),t();const L={[A.class]:A};export{L as states,I 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{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};
|
|
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, InterceptedEvent } 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: InterceptedEvent) {\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, IActionEvent, AnyConfig } from '@onereach/flow-sdk/types/index.js';\nimport { ACTION } 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 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, InterceptedEvent } 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>, callId: string): Promise<void> {\n if (!callId || typeof callId !== 'string') throw new Error('Call ID is required');\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 callId,\n },\n local: {\n disableHookEvents: true,\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 runStep(): void {\n this.triggers.hook({ name: ACTION.event, thread: '*' }, this.onEventAction);\n this.triggers.local(`otel/voice/${this.state.callId}`, this.onTelemetryEvent);\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 }\n\n @BackgroundThreadErrorFilter\n public onTelemetryEvent(event: InterceptedEvent): void {\n this.log.WARN?.('>>>Telemetry 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: InterceptedEvent): 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 protected 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","import { 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 const callId = await this.conversationContext.getCallId();\n await EventsAggregator.start(this.thread, callId);\n\n this.exitStep('next', { 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/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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"}
|