@onereach/step-generate-call-telemetry 0.0.2-rc.1 → 0.0.2-rc.10

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 CHANGED
@@ -1,94 +1,12 @@
1
- import { ACTION, AnyConfig, CONFIG, IActionEvent, IEvent, IStepId, IThread, IThreadId } from "@onereach/flow-sdk/types/index.js";
2
- import { z } from "zod/v4-mini";
1
+ import { CONFIG, ICallback, IEvent, IStepId, IThread, IThreadId } from "@onereach/flow-sdk/types/index.js";
3
2
  import Step from "@onereach/flow-sdk/step.js";
3
+ import * as z from "zod/mini";
4
+ import { SpanContext } from "@opentelemetry/api";
4
5
 
5
6
  //#region src/schemas/data-in.d.ts
6
- declare const logLevelSchema: z.ZodMiniEnum<{
7
- TRACE: "TRACE";
8
- DEBUG: "DEBUG";
9
- INFO: "INFO";
10
- WARNING: "WARNING";
11
- ERROR: "ERROR";
12
- OFF: "OFF";
13
- }>;
14
- type LogLevel = z.infer<typeof logLevelSchema>;
15
- declare const authSchema: z.ZodMiniObject<{
16
- auth: z.ZodMiniObject<{
17
- account: z.ZodMiniString<string>;
18
- authenticator: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
19
- username: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
20
- warehouse: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
21
- role: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
22
- host: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
23
- schema: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
24
- database: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
25
- }, z.core.$loose>;
26
- privateKey: z.ZodMiniObject<{
27
- pemKey: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
28
- keyPass: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
29
- }, z.core.$strip>;
30
- logLevel: z.ZodMiniDefault<z.ZodMiniEnum<{
31
- TRACE: "TRACE";
32
- DEBUG: "DEBUG";
33
- INFO: "INFO";
34
- WARNING: "WARNING";
35
- ERROR: "ERROR";
36
- OFF: "OFF";
37
- }>>;
38
- checkConnectionDelayMs: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniNumber<unknown>]>, z.ZodMiniTransform<number | undefined, number | "" | undefined>>;
39
- cacheConnection: z.ZodMiniDefault<z.ZodMiniEnum<{
40
- process: "process";
41
- thread: "thread";
42
- }>>;
43
- preCreateConnection: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
44
- }, z.core.$strip>;
45
- type SnowflakeAuth = z.infer<typeof authSchema>;
46
7
  declare const dataInSchema: z.ZodMiniObject<{
47
- auth: z.ZodMiniObject<{
48
- account: z.ZodMiniString<string>;
49
- authenticator: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
50
- username: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
51
- warehouse: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
52
- role: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
53
- host: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
54
- schema: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
55
- database: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
56
- }, z.core.$loose>;
57
- privateKey: z.ZodMiniObject<{
58
- pemKey: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
59
- keyPass: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniString<string>]>, z.ZodMiniTransform<string | undefined, string | undefined>>;
60
- }, z.core.$strip>;
61
- logLevel: z.ZodMiniDefault<z.ZodMiniEnum<{
62
- TRACE: "TRACE";
63
- DEBUG: "DEBUG";
64
- INFO: "INFO";
65
- WARNING: "WARNING";
66
- ERROR: "ERROR";
67
- OFF: "OFF";
68
- }>>;
69
- checkConnectionDelayMs: z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniLiteral<"">, z.ZodMiniNumber<unknown>]>, z.ZodMiniTransform<number | undefined, number | "" | undefined>>;
70
- cacheConnection: z.ZodMiniDefault<z.ZodMiniEnum<{
71
- process: "process";
72
- thread: "thread";
73
- }>>;
74
- preCreateConnection: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
75
- sqlText: z.ZodMiniString<string>;
76
- binds: z.ZodMiniUnion<readonly [z.ZodMiniUnion<readonly [z.ZodMiniArray<z.ZodMiniUnion<readonly [z.ZodMiniNumber<unknown>, z.ZodMiniString<string>, z.ZodMiniBoolean<boolean>, z.ZodMiniNull]>>, z.ZodMiniArray<z.ZodMiniArray<z.ZodMiniUnion<readonly [z.ZodMiniNumber<unknown>, z.ZodMiniString<string>, z.ZodMiniBoolean<boolean>, z.ZodMiniNull]>>>]>, z.ZodMiniPipe<z.ZodMiniArray<z.ZodMiniObject<{
77
- value: z.ZodMiniUnion<readonly [z.ZodMiniNumber<unknown>, z.ZodMiniString<string>, z.ZodMiniBoolean<boolean>, z.ZodMiniNull]>;
78
- }, z.core.$strip>>, z.ZodMiniTransform<(string | number | boolean | null)[], {
79
- value: string | number | boolean | null;
80
- }[]>>, z.ZodMiniPipe<z.ZodMiniArray<z.ZodMiniObject<{
81
- value: z.ZodMiniArray<z.ZodMiniUnion<readonly [z.ZodMiniNumber<unknown>, z.ZodMiniString<string>, z.ZodMiniBoolean<boolean>, z.ZodMiniNull]>>;
82
- }, z.core.$strip>>, z.ZodMiniTransform<(string | number | boolean | null)[][], {
83
- value: (string | number | boolean | null)[];
84
- }[]>>]>;
85
- fetchAsString: z.ZodMiniArray<z.ZodMiniEnum<{
86
- Boolean: "Boolean";
87
- Number: "Number";
88
- Date: "Date";
89
- Buffer: "Buffer";
90
- JSON: "JSON";
91
- }>>;
8
+ conversation: z.ZodMiniString<string>;
9
+ conversationThread: z.ZodMiniString<string>;
92
10
  }, z.core.$strip>;
93
11
  type DataIn = z.infer<typeof dataInSchema>;
94
12
  //#endregion
@@ -100,59 +18,44 @@ interface BaseConfig extends CONFIG {
100
18
  //#region src/threads/base/base.d.ts
101
19
  declare class BaseStep<T extends BaseConfig> extends Step<T> {
102
20
  resolveDataIn(): Promise<{
103
- auth: {
104
- [x: string]: unknown;
105
- account: string;
106
- authenticator: string | undefined;
107
- username: string | undefined;
108
- warehouse: string | undefined;
109
- role: string | undefined;
110
- host: string | undefined;
111
- schema: string | undefined;
112
- database: string | undefined;
113
- };
114
- privateKey: {
115
- pemKey: string | undefined;
116
- keyPass: string | undefined;
117
- };
118
- logLevel: "TRACE" | "DEBUG" | "INFO" | "WARNING" | "ERROR" | "OFF";
119
- checkConnectionDelayMs: number | undefined;
120
- cacheConnection: "process" | "thread";
121
- preCreateConnection: boolean;
122
- sqlText: string;
123
- binds: (string | number | boolean | null)[] | (string | number | boolean | null)[][];
124
- fetchAsString: ("Boolean" | "Number" | "Date" | "Buffer" | "JSON")[];
21
+ conversation: string;
22
+ conversationThread: string;
125
23
  }>;
126
24
  }
127
25
  //#endregion
128
- //#region src/threads/main/types.d.ts
129
- interface GenerateCallTelemetryConfig extends CONFIG {
130
- dataIn: DataIn;
131
- }
26
+ //#region src/threads/telemetry-aggregator/services/turns-manager/constants.d.ts
27
+ declare const turnsManagerEvents: {
28
+ readonly telemetryActivated: "trn_mgr_tel_act";
29
+ };
132
30
  //#endregion
133
- //#region src/threads/events-aggregator/constants.d.ts
134
- declare const eventsAggregatorClassId = "evt_aggr";
135
- declare const eventsAggregatorEvents: {
31
+ //#region src/threads/telemetry-aggregator/constants.d.ts
32
+ declare const telemetryAggregatorClassId = "evt_aggr";
33
+ declare const telemetryAggregatorEvents: {
136
34
  readonly refreshTurnContext: "aggr_ctx_rsh";
137
35
  };
138
36
  //#endregion
139
- //#region src/threads/events-aggregator/services/context-manager/types.d.ts
140
- type ContextManagerTurnId = string;
141
- type ContextManagerContext = {
142
- turnId: ContextManagerTurnId;
37
+ //#region src/threads/telemetry-aggregator/services/turns-manager/types.d.ts
38
+ type TurnId = string;
39
+ type TurnContext = {
40
+ turnId: TurnId;
143
41
  turnIndex: number;
144
42
  };
145
- type ContextManagerState = {
146
- context: ContextManagerContext;
147
- turnsContextMap: Record<ContextManagerTurnId, ContextManagerContext>;
148
- };
149
- //#endregion
150
- //#region src/threads/events-aggregator/services/turns-aggregator/types.d.ts
151
- type VoiceTurn = {
152
- id: string;
153
- finished: boolean;
154
- startTimestamp: number;
155
- endTimestamp?: number;
43
+ type Turn = {
44
+ /** unique turn id */id: TurnId; /** turn index in the conversation */
45
+ index: number; /** if true turn was sent to turn handler */
46
+ processed: boolean; /** if true turn can be emitted as telemetry event */
47
+ finished: boolean; /** turn start timestamp */
48
+ startTimestamp?: number; /** turn end timestamp */
49
+ endTimestamp?: number; /** turn span attributes */
50
+ attributes?: {
51
+ /** call id */'voice.call_id'?: string; /** id of the flow that produced the turn */
52
+ 'flow.id'?: string; /** id of the bot that flow is part of */
53
+ 'flow.bot_id'?: string; /** id of the session that produced the turn */
54
+ 'flow.sid'?: string; /** id of the beginning session that produced the turn */
55
+ 'flow.bsid'?: string;
56
+ }; /** otel span context for the turn */
57
+ otelSpanContext?: SpanContext; /** otel carrier for the turn. Use this to pass the span context to the next turn */
58
+ otelCarrier?: Record<string, unknown>;
156
59
  damaged?: boolean;
157
60
  damagedReasons?: string[];
158
61
  asrInputId?: string;
@@ -174,28 +77,59 @@ type VoiceTurn = {
174
77
  ttsMessage?: string;
175
78
  ttsInterruptedAfterText?: string;
176
79
  ttsProvider?: string;
177
- ttsContext?: {
178
- turnId: string;
179
- turnIndex: number;
80
+ ttsUsageMeta?: {
81
+ provider?: string;
82
+ voiceId?: string;
83
+ characterCount?: number;
180
84
  };
181
85
  };
182
- type TurnsAggregatorState = {
183
- /** raw intercepted events */rawEvents: InterceptedEvent[]; /** aggregated voice turns */
184
- turns: VoiceTurn[];
86
+ type TurnsManagerEventName = typeof turnsManagerEvents;
87
+ type TelemetryActivatedEventParameters = {
88
+ turnContext: TurnContext;
89
+ turnOtelCarrier: Record<string, unknown>;
90
+ };
91
+ type TelemetryActivatedEvent = IEvent<TelemetryActivatedEventParameters, TurnsManagerEventName['telemetryActivated']>;
92
+ type TurnsManagerDataOut = {
93
+ turnContext: TurnContext;
94
+ turnOtelCarrier: Record<string, unknown>;
95
+ telemetryThreadId: IThreadId;
96
+ };
97
+ type TurnsManagerState = {
98
+ /** current turn */turn?: Turn; /** map of all turns by turn id */
99
+ turnsMap: Record<TurnId, Turn>;
185
100
  };
186
101
  //#endregion
187
- //#region src/threads/events-aggregator/types.d.ts
188
- type EventsAggregatorEventName = typeof eventsAggregatorEvents;
189
- type EventsAggregatorEventRefreshContext = IEvent<unknown, EventsAggregatorEventName['refreshTurnContext']>;
190
- type EventsAggregatorEvent = EventsAggregatorEventRefreshContext;
191
- type InterceptedEventParameters = {
102
+ //#region src/threads/telemetry-aggregator/services/voice/types.d.ts
103
+ type ConversationParameters = {
104
+ conversation: string;
105
+ conversationThread: IThreadId;
106
+ };
107
+ type ConversationData = {
108
+ id: string;
109
+ type: string;
110
+ inbound: boolean;
111
+ botNumber: string;
112
+ endUserNumber: string;
113
+ fromName: string;
114
+ vv: string;
115
+ callback: ICallback;
116
+ _conv: Record<string, unknown>;
117
+ };
118
+ type VoiceServiceState = {
119
+ conversation?: ConversationData;
120
+ };
121
+ type VoiceEventParameters = {
192
122
  type?: string;
193
123
  [key: string]: unknown;
194
124
  timestamp?: number;
195
- ttsContext?: ContextManagerContext;
125
+ ttsContext?: TurnContext;
196
126
  ttsProvider?: string;
197
127
  partialText?: string;
198
- ttsUsageMeta?: Record<string, unknown>;
128
+ ttsUsageMeta?: {
129
+ provider: string;
130
+ voiceId: string;
131
+ characterCount: number;
132
+ };
199
133
  inputId?: string;
200
134
  confidenceScore?: number;
201
135
  phrase?: {
@@ -208,44 +142,80 @@ type InterceptedEventParameters = {
208
142
  languageCode?: string;
209
143
  };
210
144
  };
211
- type InterceptedEvent = IEvent<InterceptedEventParameters, `otel/voice/${string}`>;
212
- type EventsAggregatorState = {
213
- class: typeof eventsAggregatorClassId; /** id of a phone call from voicer */
214
- callId: string;
215
- } & ContextManagerState & TurnsAggregatorState;
216
- type EventsAggregatorLocal = {
217
- disableHookEvents: boolean;
218
- };
219
- interface EventsAggregatorConfig extends BaseConfig {
220
- state: EventsAggregatorState;
221
- local: EventsAggregatorLocal;
222
- events: EventsAggregatorEvent;
145
+ type VoiceEvent = IEvent<VoiceEventParameters, `in/voice/${string}`>;
146
+ //#endregion
147
+ //#region src/threads/telemetry-aggregator/services/events-reducer/types.d.ts
148
+ type EventsReducerState = {
149
+ /** raw intercepted events */rawEvents: VoiceEvent[];
150
+ };
151
+ type VoiceTurnHandler = (turn: Turn) => void | Promise<void>;
152
+ //#endregion
153
+ //#region src/threads/telemetry-aggregator/services/otel-emitter/types.d.ts
154
+ type OtelEmitterState = {
155
+ /** otel span context for the turn */otelCallSpanContext?: SpanContext; /** otel carrier for the turn. Use this to pass the span context to the next turn */
156
+ otelCallCarrier?: Record<string, unknown>;
157
+ };
158
+ //#endregion
159
+ //#region src/threads/telemetry-aggregator/types.d.ts
160
+ type TelemetryAggregatorEventName = typeof telemetryAggregatorEvents;
161
+ type TelemetryAggregatorEventRefreshContext = IEvent<unknown, TelemetryAggregatorEventName['refreshTurnContext']>;
162
+ type TelemetryAggregatorEvent = TelemetryAggregatorEventRefreshContext;
163
+ type TelemetryAggregatorState = {
164
+ class: typeof telemetryAggregatorClassId;
165
+ parentThreadId: IThreadId;
166
+ callStartedTimestamp: number;
167
+ } & VoiceServiceState & TurnsManagerState & EventsReducerState & OtelEmitterState;
168
+ interface TelemetryAggregatorConfig extends BaseConfig {
169
+ state: TelemetryAggregatorState;
170
+ events: TelemetryAggregatorEvent;
171
+ dataOut: TurnsManagerDataOut;
223
172
  }
224
173
  //#endregion
225
- //#region src/threads/events-aggregator/events-aggregator.d.ts
226
- declare class EventsAggregator extends BaseStep<EventsAggregatorConfig> {
174
+ //#region src/threads/main/types.d.ts
175
+ type MainEvent = TelemetryActivatedEvent;
176
+ type MainDataOut = {
177
+ turnContext: TurnContext;
178
+ turnOtelCarrier: Record<string, unknown>;
179
+ telemetryThreadId: IThreadId;
180
+ };
181
+ type MainState = {
182
+ activationStart: number;
183
+ };
184
+ interface GenerateCallTelemetryConfig extends CONFIG {
185
+ dataIn: DataIn;
186
+ state: MainState;
187
+ events: MainEvent;
188
+ dataOut: MainDataOut;
189
+ }
190
+ //#endregion
191
+ //#region src/threads/telemetry-aggregator/telemetry-aggregator.d.ts
192
+ declare class TelemetryAggregator extends BaseStep<TelemetryAggregatorConfig> {
227
193
  static readonly class = "evt_aggr";
228
- static start(thread: IThread<GenerateCallTelemetryConfig>, callId: string): Promise<void>;
194
+ static start(thread: IThread<GenerateCallTelemetryConfig>): Promise<void>;
229
195
  static getThreadId(stepId: IStepId): IThreadId;
230
- runStep(): void;
196
+ runStep(): Promise<void>;
197
+ onVoiceEvent(event: VoiceEvent): void;
231
198
  initialize(): Promise<void>;
232
- onTelemetryEvent(event: InterceptedEvent): void;
233
- onEventAction(eventAction: IActionEvent<AnyConfig, ACTION.event>): void;
199
+ onDeadline(): void;
234
200
  onRefreshTurnContext(): Promise<void>;
235
- private shouldInterceptEvent;
236
- private get contextManagerService();
237
- private get turnsAggregatorService();
201
+ private resumeParentThread;
202
+ private get voiceService();
203
+ private get otelEmitterService();
204
+ private get turnsManagerService();
205
+ private get eventsReducerService();
238
206
  }
239
207
  //#endregion
240
208
  //#region src/threads/main/step.d.ts
241
209
  declare class GenerateCallTelemetryStep extends BaseStep<GenerateCallTelemetryConfig> {
242
210
  runStep(): Promise<void>;
211
+ initialize(): Promise<void>;
212
+ onTelemetryActivated(event: TelemetryActivatedEvent): void;
243
213
  }
244
214
  //#endregion
245
215
  //#region src/index.d.ts
246
216
  declare const states: {
247
- evt_aggr: typeof EventsAggregator;
217
+ evt_aggr: typeof TelemetryAggregator;
248
218
  };
249
219
  //#endregion
250
- export { BaseConfig, ContextManagerContext, ContextManagerState, ContextManagerTurnId, DataIn, EventsAggregatorConfig, EventsAggregatorEvent, EventsAggregatorEventName, EventsAggregatorEventRefreshContext, EventsAggregatorLocal, EventsAggregatorState, GenerateCallTelemetryConfig, InterceptedEvent, InterceptedEventParameters, LogLevel, SnowflakeAuth, dataInSchema, states, GenerateCallTelemetryStep as step };
220
+ export { type BaseConfig, type ConversationData, type ConversationParameters, type DataIn, type EventsReducerState, type GenerateCallTelemetryConfig, type MainDataOut, type MainEvent, type MainState, type TelemetryActivatedEvent, type TelemetryActivatedEventParameters, type TelemetryAggregatorConfig, type TelemetryAggregatorEvent, type TelemetryAggregatorEventName, type TelemetryAggregatorEventRefreshContext, type TelemetryAggregatorState, type Turn, type TurnContext, type TurnId, type TurnsManagerDataOut, type TurnsManagerEventName, type TurnsManagerState, type VoiceEvent, type VoiceEventParameters, type VoiceServiceState, type VoiceTurnHandler, type dataInSchema, states, GenerateCallTelemetryStep as step };
251
221
  //# sourceMappingURL=index.d.mts.map
@@ -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":"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"}
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/telemetry-aggregator/services/turns-manager/constants.ts","../src/threads/telemetry-aggregator/constants.ts","../src/threads/telemetry-aggregator/services/turns-manager/types.ts","../src/threads/telemetry-aggregator/services/voice/types.ts","../src/threads/telemetry-aggregator/services/events-reducer/types.ts","../src/threads/telemetry-aggregator/services/otel-emitter/types.ts","../src/threads/telemetry-aggregator/types.ts","../src/threads/main/types.ts","../src/threads/telemetry-aggregator/telemetry-aggregator.ts","../src/threads/main/step.ts","../src/index.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{createRequire as e}from"node:module";import{install as t}from"source-map-support";import{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{en as c}from"zod/v4/locales";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)}}},{});a.config(c());const b=a.string().check(a.trim(),a.refine(e=>![`undefined`,`null`].includes(e),{error:`Unexpected undefined or null merge-field value`})),x=a.union([a.coerce.number(),b,a.boolean(),a.null()]),S=a.array(a.array(x)),C=a.union([a.array(x),S]),w=a.union([C,a.pipe(a.array(a.object({value:x})),a.transform(e=>e.map(e=>e.value))),a.pipe(a.array(a.object({value:a.array(x)})),a.transform(e=>e.map(e=>e.value)))]),T=a.enum([`TRACE`,`DEBUG`,`INFO`,`WARNING`,`ERROR`,`OFF`]),E=a.object({auth:a.looseObject({account:b.check(a.minLength(1)),authenticator:O(b),username:O(b),warehouse:O(b),role:O(b),host:O(b.check(a.hostname())),schema:O(b),database:O(b)}),privateKey:a.object({pemKey:O(b.check(a.minLength(1))),keyPass:O(b)}),logLevel:a._default(T,`OFF`),checkConnectionDelayMs:O(a.coerce.number().check(a.int(),a.gte(1))),cacheConnection:a._default(a.enum([`process`,`thread`]),`process`),preCreateConnection:a._default(a.boolean(),!1)}).check(a.refine(e=>!e.preCreateConnection||e.cacheConnection===`process`,{error:`Pre-creating connection is only possible for process level caching`})),D=a.safeExtend(E,{sqlText:b.check(a.minLength(1)),binds:w,fetchAsString:a.array(a.enum([`Boolean`,`Number`,`Date`,`Buffer`,`JSON`]))});function O(e){return a.pipe(a.union([a.undefined(),a.literal(``),e]),a.transform(e=>e===``?void 0:e))}function k(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function A(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 j=class extends s{async resolveDataIn(){let e=await super.resolveDataIn();return D.parse(e)}};A([y,k(`design:type`,Function),k(`design:paramtypes`,[]),k(`design:returntype`,Promise)],j.prototype,`resolveDataIn`,null);const M={refreshTurnContext:`aggr_ctx_rsh`};var N=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})}},P=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)}}},F,I,L=class extends j{static class=`evt_aggr`;static async start(e,t){let n=this.getThreadId(e.step.id);e.process.getThread(n)??await e.process.runThread({id:n,background:!0,state:{...N.statePlaceholder,...P.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.once(`otel/voice/${this.state.callId}`,this.onTelemetryEvent),this.triggers.local(M.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 N(this.thread)}get turnsAggregatorService(){return new P(this.thread)}};A([_,k(`design:type`,Function),k(`design:paramtypes`,[]),k(`design:returntype`,void 0)],L.prototype,`runStep`,null),A([_,k(`design:type`,Function),k(`design:paramtypes`,[]),k(`design:returntype`,Promise)],L.prototype,`initialize`,null),A([_,k(`design:type`,Function),k(`design:paramtypes`,[Object]),k(`design:returntype`,void 0)],L.prototype,`onTelemetryEvent`,null),A([_,k(`design:type`,Function),k(`design:paramtypes`,[Object]),k(`design:returntype`,void 0)],L.prototype,`onEventAction`,null),A([_,k(`design:type`,Function),k(`design:paramtypes`,[]),k(`design:returntype`,Promise)],L.prototype,`onRefreshTurnContext`,null),A([r(),k(`design:type`,typeof(F=N!==void 0&&N)==`function`?F:Object),k(`design:paramtypes`,[])],L.prototype,`contextManagerService`,null),A([r(),k(`design:type`,typeof(I=P!==void 0&&P)==`function`?I:Object),k(`design:paramtypes`,[])],L.prototype,`turnsAggregatorService`,null);const R=e(import.meta.url);async function z(e){if(typeof e!=`string`||!/^\d+\.\d+\.\d+$/.test(e))throw Error(`Invalid minimum version format: ${e}`);let t=R.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 B=class extends j{async runStep(){await z(`8.0.72`),this.exitStep(`next`,{context:{}})}};A([y,k(`design:type`,Function),k(`design:paramtypes`,[]),k(`design:returntype`,Promise)],B.prototype,`runStep`,null),t();const V={[L.class]:L};export{V as states,B 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{SpanStatusCode as u,context as d,metrics as f,propagation as p,trace as m}from"@opentelemetry/api";import{performance as h}from"node:perf_hooks";import{readFile as g}from"node:fs/promises";const _={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 v=class extends o{};const y=[v,i];function b(e,t={}){let{preserveErrors:n=y,unknownMessage:r=`Unknown error`,unknownCode:o=_.UNKNOWN}=t;if(n?.some(t=>e instanceof t))return e;if(e instanceof a.core.$ZodError)return new v(a.prettifyError(e),e,{code:_.VALIDATION});if(typeof e==`string`)return new v(e,{code:_.UNKNOWN});if(e instanceof Error){if(e.message.includes(`Request timed out`))return new i(`Timeout`,e,{code:_.TIMEOUT});let t=e?.response?.data?.error?.message;return t==null?new v(r,e,{code:o}):new v(t,e,{code:_.SERVER_ERROR})}return new v(r,{code:o,data:e})}function x(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 S=x((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=>C.call(this,e,t,n)):r}catch(t){return C.call(this,e,t,n)}}},{allowHandleError:!1,useErrorFilter:!0});function C(e,t,n){let i=n.toString();this.log.DEBUG?.(`Error in method '${i}'`,t);let a=e.useErrorFilter?b(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 w=x((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),b(e)}):t}catch(e){let t=n.toString();throw this.log.DEBUG?.(`Error in method '${t}'`,e),b(e)}}},{});c.config(c.locales.en());const T=c.string().check(c.trim(),c.refine(e=>![`undefined`,`null`].includes(e),{error:`Unexpected undefined or null merge-field value`})),E=c.object({conversation:T.check(c.minLength(1)),conversationThread:T});function D(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function O(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 k=class extends s{async resolveDataIn(){let e=await super.resolveDataIn();return E.parse(e)}};O([w,D(`design:type`,Function),D(`design:paramtypes`,[]),D(`design:returntype`,Promise)],k.prototype,`resolveDataIn`,null);const A={telemetryActivated:`trn_mgr_tel_act`},j={refreshTurnContext:`aggr_ctx_rsh`};var M=class extends l{onVoiceTurn;constructor(e,t){super(e),this.onVoiceTurn=t}static get statePlaceholder(){return{rawEvents:[]}}addEvent(e){this.thread.state.rawEvents.push(e);let t=this.findRelevantTurn(e);this.reduceEvent(t,e),t.finished&&!t.processed&&(this.onVoiceTurn(t),t.processed=!0)}findRelevantTurn(e){let t=Object.values(this.thread.state.turnsMap).findLast(t=>e.params.type?.startsWith?.(`asr-input/`)&&t.asrInputId===e.params?.inputId||e.params.type?.startsWith?.(`tts-audio/`)&&t.id===e.params?.ttsContext?.turnId||e.params.type===`tts-audio/started`&&t.ttsStartedTimestamp==null);if(t==null)throw new v(`Turn not found for event`,{code:`STEP_LOGIC_ISSUE`,data:{event:e}});return t}reduceEvent(e,t){switch(t.params.type){case`asr-input/started`:this.validateAsrInputEvent(t,e),e.asrInputId=t.params.inputId,e.asrStartedTimestamp=t.params.timestamp;break;case`asr-input/ended`:this.validateAsrInputEvent(t,e),e.asrEndedTimestamp=t.params.timestamp;break;case`asr-input/processed`:this.validateAsrInputEvent(t,e),e.asrProcessedTimestamp=t.params.timestamp,e.asrConfidenceScore=t.params.confidenceScore,e.asrRecognitionText=t.params.phrase?.text,e.asrProvider=t.params.asrProvider,e.asrUsageMeta=t.params.asrUsageMeta;break;case`tts-audio/started`:this.validateTtsAudioEvent(t,e),e.ttsProvider=t.params.ttsProvider,e.ttsStartedTimestamp=t.params.timestamp;break;case`tts-audio/interrupted`:this.validateTtsAudioEvent(t,e),e.ttsInterruptedAfterText=t.params.partialText,e.ttsEndedReason=`interrupted`,e.ttsEndedTimestamp=t.params.timestamp,e.ttsUsageMeta=t.params.ttsUsageMeta,e.endTimestamp=t.params.timestamp,e.finished=!0;break;case`tts-audio/finished`:this.validateTtsAudioEvent(t,e),e.ttsEndedReason=`ended`,e.ttsEndedTimestamp=t.params.timestamp,e.ttsUsageMeta=t.params.ttsUsageMeta,e.endTimestamp=t.params.timestamp,e.finished=!0;break;default:this.log.WARN?.(`Unknown event type`,t)}}validateAsrInputEvent(e,t){if(t.asrInputId&&t.asrInputId!==e.params.inputId){let n=`Received ${e.params.type} for wrong inputId`;this.log.WARN?.(n,{expected:t.asrInputId,actual:e.params.inputId,event:e}),this.markTurnAsDamaged(t,n)}}validateTtsAudioEvent(e,t){if(t.id&&t.id!==e.params.ttsContext?.turnId){let n=`Received ${e.params.type} for wrong turn id`;this.log.WARN?.(n,{expected:t.id,actual:e.params.ttsContext?.turnId,event:e}),this.markTurnAsDamaged(t,n)}}markTurnAsDamaged(e,t){e.damaged=!0,e.damagedReasons??=[],e.damagedReasons.push(t)}},N=class extends l{emitVoiceSpan(e){if(!e.startTimestamp||!e.endTimestamp)throw new v(`Turn start or end timestamp of turn is missing`,{code:_.STEP_LOGIC_ISSUE});let t=this.tracer.startSpan(`voice.turn`,{attributes:this.getTurnAttributes(e),startTime:e.startTimestamp},this.callContext),n=m.setSpan(d.active(),t);if(e.asrStartedTimestamp&&e.asrEndedTimestamp){let t=this.tracer.startSpan(`voice.stt`,{startTime:e.asrStartedTimestamp,attributes:{...this.getTurnAttributes(e),"stt.provider":e.asrProvider,"stt.input_id":e.asrInputId,"stt.confidence_score":e.asrConfidenceScore,"stt.recognition_text":e.asrRecognitionText}},n),r=m.setSpan(d.active(),t);t.setStatus({code:u.OK}),t.end(e.asrEndedTimestamp),this.sttDuration.record(e.asrEndedTimestamp-e.asrStartedTimestamp,{...this.getTurnAttributes(e),"stt.provider":e.asrProvider,"stt.input_id":e.asrInputId},r),e.asrConfidenceScore!=null&&this.sttConfidenceScore.record(e.asrConfidenceScore*100,{...this.getTurnAttributes(e),"stt.provider":e.asrProvider,"stt.input_id":e.asrInputId},r)}if(e.ttsStartedTimestamp&&e.ttsEndedTimestamp){let t=this.tracer.startSpan(`voice.tts`,{startTime:e.ttsStartedTimestamp,attributes:{...this.getTurnAttributes(e),"tts.provider":e.ttsProvider,"tts.ended_reason":e.ttsEndedReason,"tts.interrupted_after":e.ttsInterruptedAfterText}},n),r=m.setSpan(d.active(),t);t.setStatus({code:u.OK}),t.end(e.ttsEndedTimestamp),this.ttsDuration.record(e.ttsEndedTimestamp-e.ttsStartedTimestamp,{...this.getTurnAttributes(e),"tts.provider":e.ttsProvider,"tts.ended_reason":e.ttsEndedReason},r)}t.setStatus({code:u.OK}),t.end(e.endTimestamp),this.turnsCounter.add(1,this.getTurnAttributes(e),n),this.turnDuration.record(e.endTimestamp-e.startTimestamp,this.getTurnAttributes(e),n),e.ttsStartedTimestamp&&e.asrEndedTimestamp&&this.timeToFirstResponse.record(e.ttsStartedTimestamp-e.asrEndedTimestamp,this.getTurnAttributes(e),n),e.ttsEndedReason===`interrupted`&&this.bargeInCount.add(1,this.getTurnAttributes(e),n);let r=Object.values(this.thread.state.turnsMap).find(t=>t.index===e.index-1);r&&r.ttsEndedReason===`interrupted`&&r.ttsEndedTimestamp&&e.asrStartedTimestamp&&(this.bargeInLatency.record(r.ttsEndedTimestamp-e.asrStartedTimestamp,this.getTurnAttributes(e),n),this.bargeInRate.record(100*(r.ttsEndedTimestamp-e.asrStartedTimestamp)/(e.endTimestamp-e.startTimestamp),this.getTurnAttributes(e),n))}recordCallEnd(){this.callSpan.setStatus({code:u.OK}),this.callSpan.end(),this.activeCallsCounter.add(-1,this.callAttributes,this.callContext)}initCallSpan(){if(this.thread.state.otelCallSpanContext!=null)throw new v(`Call span already exists`,{code:_.STEP_LOGIC_ISSUE});let e=this.tracer.startSpan(`voice.call`,{root:!0,startTime:this.thread.state.callStartedTimestamp,attributes:this.callAttributes});this.thread.state.otelCallSpanContext=e.spanContext();let t=m.setSpan(d.active(),e),n={};return p.inject(t,n),this.thread.state.otelCallCarrier=n,this.totalCallsCounter.add(1,this.callAttributes,this.callContext),this.activeCallsCounter.add(1,this.callAttributes,this.callContext),e}getTurnAttributes(e){return{...e.attributes,"voice.turn.id":e.id,"voice.turn.index":e.index,"voice.call_id":this.thread.state.conversation?.id,"voice.user_phone":this.thread.state.conversation?.endUserNumber}}get callSpan(){let e=this.tracer.startSpan(`voice.call`,{root:!0,startTime:this.thread.state.callStartedTimestamp,attributes:this.callAttributes});return this.thread.state.otelCallSpanContext??(e=this.initCallSpan()),e._spanContext=this.thread.state.otelCallSpanContext,e}get callContext(){return m.setSpan(d.active(),this.callSpan)}get meter(){return f.getMeter(`voicer`)}get tracer(){return m.getTracer(`voicer`)}get activeCallsCounter(){return this.meter.createUpDownCounter(`voice_active_calls_count`,{description:`Number of active voice calls`,unit:`1`})}get totalCallsCounter(){return this.meter.createCounter(`voice_calls_count_total`,{description:`Total number of voice calls`,unit:`1`})}get timeToFirstResponse(){return this.meter.createHistogram(`voice_time_to_first_response`,{description:`Time to the first response from the agent`,unit:`ms`})}get sttDuration(){return this.meter.createHistogram(`voice_stt_duration`,{description:`Duration of the speech-to-text`,unit:`ms`})}get sttConfidenceScore(){return this.meter.createHistogram(`voice_stt_confidence_score`,{description:`Confidence score of the speech-to-text`,unit:`%`})}get ttsDuration(){return this.meter.createHistogram(`voice_tts_duration`,{description:`Duration of the text-to-speech`,unit:`ms`})}get turnsCounter(){return this.meter.createCounter(`voice_turns_count`,{description:`Count of the voice turns in the phone call`,unit:`1`})}get turnDuration(){return this.meter.createHistogram(`voice_turn_duration`,{description:`Duration of a voice turn`,unit:`ms`})}get bargeInCount(){return this.meter.createCounter(`voice_barge_in_count`,{description:`Count of the barge-in`,unit:`1`})}get bargeInLatency(){return this.meter.createHistogram(`voice_barge_in_latency`,{description:`Latency of the barge-in`,unit:`ms`})}get bargeInRate(){return this.meter.createHistogram(`voice_barge_in_rate`,{description:`Percentage of turns that were barged in per call`,unit:`%`})}get callAttributes(){return{"voice.call_id":this.thread.state.conversation?.id,"voice.call_direction":this.thread.state.conversation?.inbound?`inbound`:`outbound`,"voice.ai_agent_phone":this.thread.state.conversation?.botNumber,"voice.user_phone":this.thread.state.conversation?.endUserNumber,"voice.user_name":this.thread.state.conversation?.fromName,"voice.voicer_protocol":this.thread.state.conversation?.vv}}};O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`callSpan`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`callContext`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`meter`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`tracer`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`activeCallsCounter`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`totalCallsCounter`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`timeToFirstResponse`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`sttDuration`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`sttConfidenceScore`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`ttsDuration`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`turnsCounter`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`turnDuration`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`bargeInCount`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`bargeInLatency`,null),O([n(),D(`design:type`,Object),D(`design:paramtypes`,[])],N.prototype,`bargeInRate`,null);var P=class extends l{static get statePlaceholder(){return{turn:void 0,turnsMap:{}}}async initializeFirstTurn(){if(this.thread.state.turn!=null){this.thread.log.WARN?.(`Turn context already initialized. Skipping initialization.`);return}this.thread.log.DEBUG?.(`Initializing turn context`),await this.initNextTurn()}async generateNextTurn(){if(this.thread.state.turn==null){this.thread.log.WARN?.(`Turn context was not initialized. Initializing new turn context.`),await this.initializeFirstTurn();return}this.thread.log.DEBUG?.(`Refreshing turn context`),await this.initNextTurn()}getTelemetryActivatedEvent(){let{turnContext:e,turnOtelCarrier:t}=this.getTurnDataOut();return{name:A.telemetryActivated,params:{turnContext:e,turnOtelCarrier:t},thread:this.thread.state.parentThreadId}}async initNextTurn(){let e=this.thread.state.turn?.index??-1,t=this.createTurn(e);this.thread.state.turn=t,this.thread.state.turnsMap[t.id]=t,await this.refreshStepDataOut()}createTurn(e){return{id:crypto.randomUUID(),index:e+1,processed:!1,finished:!1,attributes:{"voice.call_id":this.thread.state.conversation?.id,"flow.id":this.thread.flow.config.flowId,"flow.bot_id":this.thread.flow.config.botId,"flow.sid":this.thread.session.reporting.sessionId,"flow.bsid":this.thread.session.reporting.beginningSessionId}}}async refreshStepDataOut(){let{turnContext:e,turnOtelCarrier:t}=this.getTurnDataOut();await this.thread.setDataOut({turnContext:e,turnOtelCarrier:t,telemetryThreadId:this.thread.id})}getTurnDataOut(){if(this.thread.state.turn==null||this.thread.state.turn.otelCarrier==null)throw new v(`Turn is not initialized`,{code:_.STEP_LOGIC_ISSUE});return{turnContext:{turnId:this.thread.state.turn.id,turnIndex:this.thread.state.turn.index},turnOtelCarrier:this.thread.state.turn.otelCarrier}}},F=class extends l{data;constructor(e,t){super(e),this.data=t}},I=class extends F{async getConversationData({force:e}={}){let t=this.thread.state.conversation;if(t&&e!==!0)return t;let{conversation:n}=this.data,r={conversation:n,conversationThread:this.conversationThreadId},i=await this.fetchConversationData(r);if(!i||i._conv==null)throw new v(`Missing conversation data`,{code:_.VALIDATION,data:r});return this.thread.state.conversation=i,i}async enableTelemetry(){if(!this.thread.state.conversation)throw new v(`Conversation data is not available`,{code:_.VALIDATION});let{id:e,type:t,callback:n}=this.thread.state.conversation,r={target:this.thread.helpers.providersAccountId,name:`out/voice/${t}`,params:{id:e,async:!0,hbs:99,commands:[{name:`start-telemetry`,params:{ack:!0}}],step:{key:this.session.key,trd:this.thread.id}},reporting:{...this.session.getSessionRef()}};this.log.DEBUG?.(`startTelemetry event`,r);let i=await this.thread.eventManager.emit(r,{target:n,invocationType:`async`,timeout:5e3});if(this.log.DEBUG?.(`startTelemetry result`,i),i==null)throw new v(`Failed to start telemetry`,{code:_.SERVER_ERROR,data:r})}get expectHeartbeatBefore(){return Date.now()+3e5}onHeartbeatTimeout(){this.log.WARN?.(`Heartbeat was not received before the deadline`),this.thread.end()}get conversationThreadId(){let{conversationThread:e}=this.data;return e||this.thread.state.parentThreadId}async fetchConversationData({conversation:e,conversationThread:t}){return await this.process.getSafeThread(t).get(e)}},L,R,z,B=class extends k{static class=`evt_aggr`;static async start(e){let t=this.getThreadId(e.step.id);e.process.getThread(t)??await e.process.runThread({id:t,background:!0,state:{...P.statePlaceholder,...M.statePlaceholder,step:e.step.id,class:this.class,parentThreadId:e.id,callStartedTimestamp:Date.now()}})}static getThreadId(e){return`vce_otel_${this.class}_${e}`}async runStep(){let{id:e}=await this.voiceService.getConversationData();this.triggers.local(`in/voice/${e}`,this.onVoiceEvent),this.triggers.local(j.refreshTurnContext,this.onRefreshTurnContext),this.triggers.deadline(this.voiceService.expectHeartbeatBefore,this.onDeadline),this.triggers.otherwise(this.initialize)}onVoiceEvent(e){switch(this.log.DEBUG?.(`onVoiceEvent`,e),e.params.type){case`ack`:this.resumeParentThread();break;case`tts-audio/started`:case`tts-audio/finished`:case`tts-audio/interrupted`:case`asr-input/started`:case`asr-input/ended`:case`asr-input/processed`:this.eventsReducerService.addEvent(e);break;case`hangup`:{let{turnsMap:t,rawEvents:n}=this.state;this.log.WARN?.(`Hangup event received`,{turnsMap:t,rawEvents:n,event:e});break}case`heartbeat`:break;default:this.log.WARN?.(`Unexpected type of event`,e)}}async initialize(){this.log.DEBUG?.(`Initializing TelemetryAggregator thread`),await this.turnsManagerService.initializeFirstTurn(),await this.voiceService.enableTelemetry()}onDeadline(){this.voiceService.onHeartbeatTimeout()}async onRefreshTurnContext(){await this.turnsManagerService.generateNextTurn()}async resumeParentThread(){await this.process.enqueueAndRun(this.turnsManagerService.getTelemetryActivatedEvent())}get voiceService(){return new I(this.thread,this.data)}get otelEmitterService(){return new N(this.thread)}get turnsManagerService(){return new P(this.thread)}get eventsReducerService(){return new M(this.thread,e=>this.otelEmitterService.emitVoiceSpan(e))}};O([S,D(`design:type`,Function),D(`design:paramtypes`,[]),D(`design:returntype`,Promise)],B.prototype,`runStep`,null),O([S,D(`design:type`,Function),D(`design:paramtypes`,[Object]),D(`design:returntype`,void 0)],B.prototype,`onVoiceEvent`,null),O([S,D(`design:type`,Function),D(`design:paramtypes`,[]),D(`design:returntype`,Promise)],B.prototype,`initialize`,null),O([S,D(`design:type`,Function),D(`design:paramtypes`,[]),D(`design:returntype`,void 0)],B.prototype,`onDeadline`,null),O([S,D(`design:type`,Function),D(`design:paramtypes`,[]),D(`design:returntype`,Promise)],B.prototype,`onRefreshTurnContext`,null),O([n(),D(`design:type`,typeof(L=N!==void 0&&N)==`function`?L:Object),D(`design:paramtypes`,[])],B.prototype,`otelEmitterService`,null),O([n(),D(`design:type`,typeof(R=P!==void 0&&P)==`function`?R:Object),D(`design:paramtypes`,[])],B.prototype,`turnsManagerService`,null),O([n(),D(`design:type`,typeof(z=M!==void 0&&M)==`function`?z:Object),D(`design:paramtypes`,[])],B.prototype,`eventsReducerService`,null);const V=e(import.meta.url);async function H(e){if(typeof e!=`string`||!/^\d+\.\d+\.\d+$/.test(e))throw Error(`Invalid minimum version format: ${e}`);let t=V.resolve(`@onereach/flow-sdk/package.json`);if(!t)throw Error(`Could not find package.json for @onereach/flow-sdk`);let n=await g(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 U=class extends k{async runStep(){await H(`8.0.72`),this.triggers.local(A.telemetryActivated,this.onTelemetryActivated),this.triggers.otherwise(this.initialize)}async initialize(){this.state.activationStart=h.now(),await B.start(this.thread)}onTelemetryActivated(e){let t=h.now()-this.state.activationStart;this.log.DEBUG?.(`onTelemetryActivated`,{event:e,activationMs:t});let{turnContext:n,turnOtelCarrier:r}=e.params;this.exitStep(`next`,{turnContext:n,turnOtelCarrier:r,telemetryThreadId:B.getThreadId(this.currentStepId)})}};O([w,D(`design:type`,Function),D(`design:paramtypes`,[]),D(`design:returntype`,Promise)],U.prototype,`runStep`,null),t();const W={[B.class]:B};export{W as states,U as step};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["defaultOptions","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/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 type { Bind, Binds, InsertBinds /* , LogLevel as SnowflakeLogLevel */ } from 'snowflake-sdk';\nimport { en } from 'zod/v4/locales';\nimport { z } from 'zod/v4-mini';\nz.config(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\nconst bindSchema = z.union([\n z.coerce.number(),\n stringNoUndefinedSchema,\n z.boolean(),\n z.null(),\n]) satisfies z.core.$ZodType<Bind>;\n\nconst insertBindsSchema = z.array(z.array(bindSchema)) satisfies z.core.$ZodType<InsertBinds>;\nconst bindsSchema = z.union([z.array(bindSchema), insertBindsSchema]) satisfies z.core.$ZodType<Binds>;\nconst extendedBindsSchema = z.union([\n bindsSchema,\n\n // binds wrapped in object with \"value\" key from UI\n z.pipe(\n z.array(z.object({ value: bindSchema })),\n z.transform((array) => array.map((o) => o.value)),\n ),\n\n // insert binds wrapped in object with \"value\" key from UI\n z.pipe(\n z.array(z.object({ value: z.array(bindSchema) })),\n z.transform((array) => array.map((o) => o.value)),\n ),\n]);\n\nconst logLevelSchema = z.enum(['TRACE', 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'OFF']); //satisfies z.core.$ZodType<SnowflakeLogLevel>;\nexport type LogLevel = z.infer<typeof logLevelSchema>;\n\nconst authSchema = z\n .object({\n auth: z.looseObject({\n account: stringNoUndefinedSchema.check(z.minLength(1)),\n authenticator: optionalStringValue(stringNoUndefinedSchema),\n username: optionalStringValue(stringNoUndefinedSchema),\n\n warehouse: optionalStringValue(stringNoUndefinedSchema),\n role: optionalStringValue(stringNoUndefinedSchema),\n host: optionalStringValue(stringNoUndefinedSchema.check(z.hostname())),\n schema: optionalStringValue(stringNoUndefinedSchema),\n database: optionalStringValue(stringNoUndefinedSchema),\n // TODO: add timeout\n }),\n privateKey: z.object({\n pemKey: optionalStringValue(stringNoUndefinedSchema.check(z.minLength(1))),\n keyPass: optionalStringValue(stringNoUndefinedSchema),\n }),\n logLevel: z._default(logLevelSchema, 'OFF'),\n checkConnectionDelayMs: optionalStringValue(z.coerce.number().check(z.int(), z.gte(1))),\n cacheConnection: z._default(z.enum(['process', 'thread']), 'process'),\n preCreateConnection: z._default(z.boolean(), false),\n })\n .check(\n z.refine((data) => !data.preCreateConnection || data.cacheConnection === 'process', {\n error: 'Pre-creating connection is only possible for process level caching',\n }),\n );\n\nexport type SnowflakeAuth = z.infer<typeof authSchema>;\n\nexport const dataInSchema = z.safeExtend(authSchema, {\n sqlText: stringNoUndefinedSchema.check(z.minLength(1)),\n binds: extendedBindsSchema,\n fetchAsString: z.array(z.enum(['Boolean', 'Number', 'Date', 'Buffer', 'JSON'])),\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 */\nfunction optionalStringValue<T extends z.core.SomeType>(schema: T) {\n return z.pipe(\n z.union([z.undefined(), z.literal(''), schema]),\n z.transform((value) => (value === '' ? undefined : value)),\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 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.once(`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 { ErrorFilter } from '../../decorators/error-filter.ts';\nimport { validateFlowSdkVersion } from '../../utils/validate-flow-sdk-version.ts';\nimport { BaseStep } from '../base/base.ts';\n\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 result = await this.snowflakeService.executeSql();\n\n this.exitStep('next', { context: {} });\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"],"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/telemetry-aggregator/services/turns-manager/constants.ts","../src/threads/telemetry-aggregator/constants.ts","../src/threads/telemetry-aggregator/services/events-reducer/events-reducer.ts","../src/threads/telemetry-aggregator/services/otel-emitter/otel-emitter.ts","../src/threads/telemetry-aggregator/services/turns-manager/turns-manager.ts","../src/services/thread-service-with-data.ts","../src/threads/telemetry-aggregator/services/voice/voice.ts","../src/threads/telemetry-aggregator/telemetry-aggregator.ts","../src/utils/validate-flow-sdk-version.ts","../src/threads/main/constants.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 turnsManagerEvents = {\n telemetryActivated: 'trn_mgr_tel_act',\n} as const;\n","export * from './services/turns-manager/constants.ts';\n\nexport const telemetryAggregatorClassId = 'evt_aggr';\n\nexport const telemetryAggregatorEvents = {\n refreshTurnContext: 'aggr_ctx_rsh',\n} as const;\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport type { IThread } from '@onereach/flow-sdk/types/index.js';\n\nimport { GenerateCallTelemetryStepError } from '../../../../errors/step-error.ts';\nimport type { TelemetryAggregatorConfig, Turn, VoiceEvent } from '../../types.ts';\n\nimport type { EventsReducerState, VoiceTurnHandler } from './types.ts';\n\nexport class EventsReducerService extends BasicThreadService<TelemetryAggregatorConfig> {\n private readonly onVoiceTurn: VoiceTurnHandler;\n\n public constructor(thread: IThread<TelemetryAggregatorConfig>, onVoiceTurn: VoiceTurnHandler) {\n super(thread);\n\n this.onVoiceTurn = onVoiceTurn;\n }\n\n public static get statePlaceholder(): EventsReducerState {\n return {\n // TODO: remove this in the future\n /** list of all events that were reduced into turns */\n rawEvents: [],\n };\n }\n\n public addEvent(event: VoiceEvent): void {\n this.thread.state.rawEvents.push(event);\n\n const turn = this.findRelevantTurn(event);\n this.reduceEvent(turn, event);\n\n if (turn.finished && !turn.processed) {\n void this.onVoiceTurn(turn);\n turn.processed = true;\n }\n }\n\n private findRelevantTurn(event: VoiceEvent): Turn {\n const currentTurn = Object.values(this.thread.state.turnsMap).findLast((turn) => {\n return (\n (event.params.type?.startsWith?.('asr-input/') && turn.asrInputId === event.params?.inputId) ||\n (event.params.type?.startsWith?.('tts-audio/') && turn.id === event.params?.ttsContext?.turnId) ||\n (event.params.type === 'tts-audio/started' && turn.ttsStartedTimestamp == undefined)\n );\n });\n\n if (currentTurn == undefined) {\n throw new GenerateCallTelemetryStepError('Turn not found for event', {\n code: 'STEP_LOGIC_ISSUE',\n data: {\n event,\n },\n });\n }\n return currentTurn;\n }\n\n private reduceEvent(turn: Turn, event: VoiceEvent): void {\n switch (event.params.type) {\n case 'asr-input/started': {\n this.validateAsrInputEvent(event, turn);\n turn.asrInputId = event.params.inputId;\n turn.asrStartedTimestamp = event.params.timestamp;\n break;\n }\n case 'asr-input/ended': {\n this.validateAsrInputEvent(event, turn);\n turn.asrEndedTimestamp = event.params.timestamp;\n break;\n }\n case 'asr-input/processed': {\n this.validateAsrInputEvent(event, turn);\n turn.asrProcessedTimestamp = event.params.timestamp;\n turn.asrConfidenceScore = event.params.confidenceScore;\n turn.asrRecognitionText = event.params.phrase?.text;\n turn.asrProvider = event.params.asrProvider;\n turn.asrUsageMeta = event.params.asrUsageMeta;\n break;\n }\n\n case 'tts-audio/started': {\n this.validateTtsAudioEvent(event, turn);\n turn.ttsProvider = event.params.ttsProvider;\n turn.ttsStartedTimestamp = event.params.timestamp;\n break;\n }\n case 'tts-audio/interrupted': {\n this.validateTtsAudioEvent(event, turn);\n turn.ttsInterruptedAfterText = event.params.partialText;\n turn.ttsEndedReason = 'interrupted';\n turn.ttsEndedTimestamp = event.params.timestamp;\n turn.ttsUsageMeta = event.params.ttsUsageMeta;\n // currentTurn.ttsMessage = ttsMsgs[currentTurn.ttsContext?.turnId as string]?.message;\n turn.endTimestamp = event.params.timestamp;\n\n turn.finished = true;\n break;\n }\n case 'tts-audio/finished': {\n this.validateTtsAudioEvent(event, turn);\n turn.ttsEndedReason = 'ended';\n turn.ttsEndedTimestamp = event.params.timestamp;\n turn.ttsUsageMeta = event.params.ttsUsageMeta;\n // currentTurn.ttsMessage = ttsMsgs[currentTurn.ttsContext?.turnId as string]?.message;\n turn.endTimestamp = event.params.timestamp;\n\n turn.finished = true;\n break;\n }\n\n default: {\n this.log.WARN?.('Unknown event type', event);\n }\n }\n }\n\n private validateAsrInputEvent(event: VoiceEvent, turn: Turn): void {\n if (turn.asrInputId && turn.asrInputId !== event.params.inputId) {\n const message = `Received ${event.params.type} for wrong inputId`;\n this.log.WARN?.(message, {\n expected: turn.asrInputId,\n actual: event.params.inputId,\n event,\n });\n this.markTurnAsDamaged(turn, message);\n }\n }\n\n private validateTtsAudioEvent(event: VoiceEvent, turn: Turn): void {\n if (turn.id && turn.id !== event.params.ttsContext?.turnId) {\n const message = `Received ${event.params.type} for wrong turn id`;\n this.log.WARN?.(message, {\n expected: turn.id,\n actual: event.params.ttsContext?.turnId,\n event,\n });\n this.markTurnAsDamaged(turn, message);\n }\n }\n\n private markTurnAsDamaged(turn: Turn, reason: string): void {\n turn.damaged = true;\n turn.damagedReasons ??= [];\n turn.damagedReasons.push(reason);\n }\n}\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport { context, metrics, propagation, SpanStatusCode, trace } from '@opentelemetry/api';\nimport type { Attributes, Context, Counter, Histogram, Meter, Span, Tracer, UpDownCounter } from '@opentelemetry/api';\nimport { Memoize } from 'typescript-memoize';\n\nimport { ErrorCode, GenerateCallTelemetryStepError } from '../../../../errors/step-error.ts';\nimport type { TelemetryAggregatorConfig } from '../../types.ts';\nimport type { Turn } from '../turns-manager/types.ts';\n\n// TODO: remove any throw errors and instead add warnings to the logs\nexport class OtelEmitterService extends BasicThreadService<TelemetryAggregatorConfig> {\n /** Emit a voice turn span with related metrics */\n public emitVoiceSpan(turn: Turn): void {\n if (!turn.startTimestamp || !turn.endTimestamp) {\n throw new GenerateCallTelemetryStepError('Turn start or end timestamp of turn is missing', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n // TODO: restore the span context from the span data if it exists\n const turnSpan = this.tracer.startSpan(\n 'voice.turn',\n {\n attributes: this.getTurnAttributes(turn),\n startTime: turn.startTimestamp,\n },\n this.callContext,\n );\n const turnContext = trace.setSpan(context.active(), turnSpan);\n\n // Speech to Text (STT) span and metrics\n if (turn.asrStartedTimestamp && turn.asrEndedTimestamp) {\n const sttSpan = this.tracer.startSpan(\n 'voice.stt',\n {\n startTime: turn.asrStartedTimestamp,\n attributes: {\n ...this.getTurnAttributes(turn),\n 'stt.provider': turn.asrProvider,\n 'stt.input_id': turn.asrInputId,\n 'stt.confidence_score': turn.asrConfidenceScore,\n 'stt.recognition_text': turn.asrRecognitionText,\n },\n },\n turnContext,\n );\n const sttContext = trace.setSpan(context.active(), sttSpan);\n\n sttSpan.setStatus({ code: SpanStatusCode.OK });\n sttSpan.end(turn.asrEndedTimestamp);\n\n // Speech to Text (STT) metrics\n this.sttDuration.record(\n turn.asrEndedTimestamp - turn.asrStartedTimestamp,\n {\n ...this.getTurnAttributes(turn),\n 'stt.provider': turn.asrProvider,\n 'stt.input_id': turn.asrInputId,\n },\n sttContext,\n );\n\n if (turn.asrConfidenceScore != undefined) {\n this.sttConfidenceScore.record(\n turn.asrConfidenceScore * 100,\n {\n ...this.getTurnAttributes(turn),\n 'stt.provider': turn.asrProvider,\n 'stt.input_id': turn.asrInputId,\n },\n sttContext,\n );\n }\n }\n\n // Text to Speech (TTS) span and metrics\n if (turn.ttsStartedTimestamp && turn.ttsEndedTimestamp) {\n const ttsSpan = this.tracer.startSpan(\n 'voice.tts',\n {\n startTime: turn.ttsStartedTimestamp,\n attributes: {\n ...this.getTurnAttributes(turn),\n 'tts.provider': turn.ttsProvider,\n 'tts.ended_reason': turn.ttsEndedReason,\n 'tts.interrupted_after': turn.ttsInterruptedAfterText,\n },\n },\n turnContext,\n );\n const ttsContext = trace.setSpan(context.active(), ttsSpan);\n ttsSpan.setStatus({ code: SpanStatusCode.OK });\n ttsSpan.end(turn.ttsEndedTimestamp);\n\n this.ttsDuration.record(\n turn.ttsEndedTimestamp - turn.ttsStartedTimestamp,\n {\n ...this.getTurnAttributes(turn),\n 'tts.provider': turn.ttsProvider,\n 'tts.ended_reason': turn.ttsEndedReason,\n },\n ttsContext,\n );\n }\n\n turnSpan.setStatus({ code: SpanStatusCode.OK });\n turnSpan.end(turn.endTimestamp);\n\n // metrics for the turn\n this.turnsCounter.add(1, this.getTurnAttributes(turn), turnContext);\n\n this.turnDuration.record(turn.endTimestamp - turn.startTimestamp, this.getTurnAttributes(turn), turnContext);\n\n if (turn.ttsStartedTimestamp && turn.asrEndedTimestamp) {\n this.timeToFirstResponse.record(\n turn.ttsStartedTimestamp - turn.asrEndedTimestamp,\n this.getTurnAttributes(turn),\n turnContext,\n );\n }\n\n if (turn.ttsEndedReason === 'interrupted') {\n this.bargeInCount.add(1, this.getTurnAttributes(turn), turnContext);\n }\n\n const previousTurn = Object.values(this.thread.state.turnsMap).find((t) => t.index === turn.index - 1);\n if (\n previousTurn &&\n previousTurn.ttsEndedReason === 'interrupted' &&\n previousTurn.ttsEndedTimestamp &&\n turn.asrStartedTimestamp\n ) {\n this.bargeInLatency.record(\n previousTurn.ttsEndedTimestamp - turn.asrStartedTimestamp,\n this.getTurnAttributes(turn),\n turnContext,\n );\n this.bargeInRate.record(\n (100 * (previousTurn.ttsEndedTimestamp - turn.asrStartedTimestamp)) / (turn.endTimestamp - turn.startTimestamp),\n this.getTurnAttributes(turn),\n turnContext,\n );\n }\n }\n\n /** End a voice call span with related metrics */\n public recordCallEnd(): void {\n this.callSpan.setStatus({ code: SpanStatusCode.OK });\n // TODO: set the end timestamp from hangup event\n this.callSpan.end();\n\n // Emit metrics for the call end\n this.activeCallsCounter.add(-1, this.callAttributes, this.callContext);\n }\n\n /** Initialize a voice call span with related metrics */\n private initCallSpan(): Span {\n if (this.thread.state.otelCallSpanContext != undefined) {\n throw new GenerateCallTelemetryStepError('Call span already exists', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n const callSpan = this.tracer.startSpan('voice.call', {\n root: true,\n startTime: this.thread.state.callStartedTimestamp,\n attributes: this.callAttributes,\n });\n\n // set the span context for the current call\n this.thread.state.otelCallSpanContext = callSpan.spanContext();\n\n // set the span carrier for the next call\n const callContext = trace.setSpan(context.active(), callSpan);\n const callCarrier: Record<string, string> = {};\n propagation.inject(callContext, callCarrier);\n this.thread.state.otelCallCarrier = callCarrier;\n\n // Emit metrics for the call start\n this.totalCallsCounter.add(1, this.callAttributes, this.callContext);\n this.activeCallsCounter.add(1, this.callAttributes, this.callContext);\n\n return callSpan;\n }\n\n /** Get the turn attributes */\n private getTurnAttributes(turn: Turn): Attributes {\n return {\n ...turn.attributes,\n 'voice.turn.id': turn.id,\n 'voice.turn.index': turn.index,\n 'voice.call_id': this.thread.state.conversation?.id,\n 'voice.user_phone': this.thread.state.conversation?.endUserNumber,\n };\n }\n\n /** Get the voice call span */\n @Memoize()\n private get callSpan(): Span {\n let callSpan = this.tracer.startSpan('voice.call', {\n root: true,\n startTime: this.thread.state.callStartedTimestamp,\n attributes: this.callAttributes,\n });\n\n if (this.thread.state.otelCallSpanContext == undefined) {\n // initialize the call span\n callSpan = this.initCallSpan();\n }\n\n // restore the span context from the previous call if it exists\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n (callSpan as any)._spanContext = this.thread.state.otelCallSpanContext;\n\n return callSpan;\n }\n\n /** Get the voice call context */\n @Memoize()\n private get callContext(): Context {\n return trace.setSpan(context.active(), this.callSpan);\n }\n\n /** Get the voicer meter */\n @Memoize()\n private get meter(): Meter {\n return metrics.getMeter('voicer');\n }\n\n /** Get the voicer tracer */\n @Memoize()\n private get tracer(): Tracer {\n return trace.getTracer('voicer');\n }\n\n /** Get the active calls counter */\n @Memoize()\n private get activeCallsCounter(): UpDownCounter<Attributes> {\n return this.meter.createUpDownCounter('voice_active_calls_count', {\n description: 'Number of active voice calls',\n unit: '1',\n });\n }\n\n /** Get the total calls counter */\n @Memoize()\n private get totalCallsCounter(): Counter<Attributes> {\n return this.meter.createCounter('voice_calls_count_total', {\n description: 'Total number of voice calls',\n unit: '1',\n });\n }\n\n // /** Get the call QoS Mean Opinion Score histogram */\n // @Memoize()\n // private get callQosMosHistogram(): Histogram<Attributes> {\n // return this.meter.createHistogram('voice_call_qos_mos', {\n // description: 'Mean Opinion Score for call quality',\n // unit: '1', // dimensionless, 1–5 scale\n // });\n // }\n\n // /** Get the call QoS Jitter histogram */\n // private get callQosJitterHistogram(): Histogram<Attributes> {\n // return this.meter.createHistogram('voice_call_qos_jitter', {\n // description: 'Jitter value of the voice call',\n // unit: 'ms',\n // });\n // }\n\n // /** Get the call QoS RTP packet loss percentage histogram */\n // private get callQosPktLostHistogram(): Histogram<Attributes> {\n // return this.meter.createHistogram('voice_call_qos_pkt_lost', {\n // description: 'RTP packet loss percentage',\n // unit: '%',\n // });\n // }\n\n // metrics for agent\n @Memoize()\n private get timeToFirstResponse(): Histogram<Attributes> {\n return this.meter.createHistogram('voice_time_to_first_response', {\n description: 'Time to the first response from the agent',\n unit: 'ms',\n });\n }\n\n // metrics for the speech-to-text\n @Memoize()\n private get sttDuration(): Histogram<Attributes> {\n return this.meter.createHistogram('voice_stt_duration', {\n description: 'Duration of the speech-to-text',\n unit: 'ms',\n });\n }\n\n @Memoize()\n private get sttConfidenceScore(): Histogram<Attributes> {\n return this.meter.createHistogram('voice_stt_confidence_score', {\n description: 'Confidence score of the speech-to-text',\n unit: '%',\n });\n }\n\n // metrics for the text-to-speech\n @Memoize()\n private get ttsDuration(): Histogram<Attributes> {\n return this.meter.createHistogram('voice_tts_duration', {\n description: 'Duration of the text-to-speech',\n unit: 'ms',\n });\n }\n\n // metrics for the voice turn\n @Memoize()\n private get turnsCounter(): Counter<Attributes> {\n return this.meter.createCounter('voice_turns_count', {\n description: 'Count of the voice turns in the phone call',\n unit: '1',\n });\n }\n\n @Memoize()\n private get turnDuration(): Histogram<Attributes> {\n return this.meter.createHistogram('voice_turn_duration', {\n description: 'Duration of a voice turn',\n unit: 'ms',\n });\n }\n\n // metrics for the barge-in\n @Memoize()\n private get bargeInCount(): Counter<Attributes> {\n return this.meter.createCounter('voice_barge_in_count', {\n description: 'Count of the barge-in',\n unit: '1',\n });\n }\n\n @Memoize()\n private get bargeInLatency(): Histogram<Attributes> {\n return this.meter.createHistogram('voice_barge_in_latency', {\n description: 'Latency of the barge-in',\n unit: 'ms',\n });\n }\n\n @Memoize()\n private get bargeInRate(): Histogram<Attributes> {\n return this.meter.createHistogram('voice_barge_in_rate', {\n description: 'Percentage of turns that were barged in per call',\n unit: '%',\n });\n }\n\n /** Get the voice call attributes */\n private get callAttributes(): Attributes {\n return {\n 'voice.call_id': this.thread.state.conversation?.id,\n 'voice.call_direction': this.thread.state.conversation?.inbound ? 'inbound' : 'outbound',\n 'voice.ai_agent_phone': this.thread.state.conversation?.botNumber,\n 'voice.user_phone': this.thread.state.conversation?.endUserNumber,\n 'voice.user_name': this.thread.state.conversation?.fromName,\n 'voice.voicer_protocol': this.thread.state.conversation?.vv,\n };\n }\n}\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\n\nimport { ErrorCode, GenerateCallTelemetryStepError } from '../../../../errors/step-error.ts';\nimport type { TelemetryAggregatorConfig } from '../../types.ts';\n\nimport { turnsManagerEvents } from './constants.ts';\nimport type { TelemetryActivatedEvent, Turn, TurnsManagerState } from './types.ts';\n\nexport class TurnsManagerService extends BasicThreadService<TelemetryAggregatorConfig> {\n public static get statePlaceholder(): TurnsManagerState {\n return {\n turn: undefined,\n turnsMap: {},\n };\n }\n\n // -----------------------------\n\n /** Use this to initialize the turn for the first time */\n public async initializeFirstTurn(): Promise<void> {\n if (this.thread.state.turn != undefined) {\n this.thread.log.WARN?.(`Turn context already initialized. Skipping initialization.`);\n return;\n }\n\n this.thread.log.DEBUG?.(`Initializing turn context`);\n await this.initNextTurn();\n }\n\n /** Use this to generate the next turn */\n public async generateNextTurn(): Promise<void> {\n if (this.thread.state.turn == undefined) {\n this.thread.log.WARN?.(`Turn context was not initialized. Initializing new turn context.`);\n await this.initializeFirstTurn();\n return;\n }\n\n this.thread.log.DEBUG?.(`Refreshing turn context`);\n await this.initNextTurn();\n }\n\n /**\n * Use this to get the telemetry activated event\n * This event is used to notify the main thread that telemetry delivery was activated for the call.\n */\n public getTelemetryActivatedEvent(): TelemetryActivatedEvent {\n const { turnContext, turnOtelCarrier } = this.getTurnDataOut();\n return {\n name: turnsManagerEvents.telemetryActivated,\n params: { turnContext, turnOtelCarrier },\n thread: this.thread.state.parentThreadId,\n };\n }\n\n private async initNextTurn(): Promise<void> {\n const lastTurnIndex = this.thread.state.turn?.index ?? -1;\n const nextTurn = this.createTurn(lastTurnIndex);\n this.thread.state.turn = nextTurn;\n this.thread.state.turnsMap[nextTurn.id] = nextTurn;\n\n await this.refreshStepDataOut();\n }\n\n private createTurn(lastTurnIndex: number): Turn {\n const turnId = crypto.randomUUID();\n const turnIndex = lastTurnIndex + 1;\n const turn: Turn = {\n id: turnId,\n index: turnIndex,\n processed: false,\n finished: false,\n attributes: {\n 'voice.call_id': this.thread.state.conversation?.id,\n 'flow.id': this.thread.flow.config.flowId,\n 'flow.bot_id': this.thread.flow.config.botId,\n 'flow.sid': this.thread.session.reporting.sessionId,\n 'flow.bsid': this.thread.session.reporting.beginningSessionId,\n },\n };\n return turn;\n }\n\n private async refreshStepDataOut(): Promise<void> {\n const { turnContext, turnOtelCarrier } = this.getTurnDataOut();\n\n // refresh step data out to have new turn data\n await this.thread.setDataOut({\n turnContext,\n turnOtelCarrier,\n telemetryThreadId: this.thread.id,\n });\n }\n\n private getTurnDataOut() {\n if (this.thread.state.turn == undefined || this.thread.state.turn.otelCarrier == undefined) {\n throw new GenerateCallTelemetryStepError('Turn is not initialized', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n return {\n turnContext: {\n turnId: this.thread.state.turn.id,\n turnIndex: this.thread.state.turn.index,\n },\n turnOtelCarrier: this.thread.state.turn.otelCarrier,\n };\n }\n}\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport type { CONFIG, IN, IThread } from '@onereach/flow-sdk/types/index.js';\n\nexport class ThreadServiceWithData<\n TConfig extends CONFIG,\n TData extends IN<CONFIG> = IN<TConfig>,\n> extends BasicThreadService<TConfig> {\n protected readonly data: TData;\n\n constructor(thread: IThread<TConfig>, data: TData) {\n super(thread);\n this.data = data;\n }\n}\n","import type { IThreadId } from '@onereach/flow-sdk/types/index.js';\n\nimport { ErrorCode, GenerateCallTelemetryStepError } from '../../../../errors/step-error.ts';\nimport { ThreadServiceWithData } from '../../../../services/thread-service-with-data.ts';\nimport type { TelemetryAggregatorConfig } from '../../types.ts';\n\nimport type { ConversationData, ConversationParameters } from './types.ts';\n\nexport class VoiceService extends ThreadServiceWithData<TelemetryAggregatorConfig> {\n /** Fetch conversation data from the conversation data thread */\n public async getConversationData({ force }: { force?: boolean } = {}): Promise<ConversationData> {\n const voiceConversation = this.thread.state.conversation;\n if (voiceConversation && force !== true) return voiceConversation;\n\n const { conversation } = this.data;\n\n const conversationParameters: ConversationParameters = {\n conversation,\n conversationThread: this.conversationThreadId,\n };\n const data = await this.fetchConversationData(conversationParameters);\n if (!data || data._conv == undefined) {\n throw new GenerateCallTelemetryStepError('Missing conversation data', {\n code: ErrorCode.VALIDATION,\n data: conversationParameters,\n });\n }\n\n this.thread.state.conversation = data;\n\n return data;\n }\n\n /** Enable telemetry for the phone call */\n public async enableTelemetry(): Promise<void> {\n if (!this.thread.state.conversation) {\n throw new GenerateCallTelemetryStepError('Conversation data is not available', {\n code: ErrorCode.VALIDATION,\n });\n }\n\n const { id, type, callback } = this.thread.state.conversation;\n\n const event = {\n target: this.thread.helpers.providersAccountId,\n name: `out/voice/${type}`,\n params: {\n id,\n async: true,\n hbs: 99, // heartbeat seconds\n commands: [\n {\n name: 'start-telemetry',\n params: { ack: true }, // expect acknowledge from voicer\n },\n ],\n step: {\n key: this.session.key,\n trd: this.thread.id,\n },\n },\n\n reporting: {\n ...this.session.getSessionRef(),\n },\n };\n\n this.log.DEBUG?.('startTelemetry event', event);\n\n const result = await this.thread.eventManager.emit(event, {\n target: callback,\n invocationType: 'async',\n timeout: 5000,\n });\n this.log.DEBUG?.('startTelemetry result', result);\n\n if (result == undefined) {\n // TODO: test how parent thread will react on this error\n throw new GenerateCallTelemetryStepError('Failed to start telemetry', {\n code: ErrorCode.SERVER_ERROR,\n data: event,\n });\n }\n }\n\n /** Maximum timestamp in milliseconds before the heartbeat is expected */\n public get expectHeartbeatBefore(): number {\n return Date.now() + 300_000;\n }\n\n /** Called when the heartbeat is not received before the deadline */\n public onHeartbeatTimeout(): void {\n this.log.WARN?.('Heartbeat was not received before the deadline');\n this.thread.end();\n }\n\n /** id of the thread where conversation data is stored */\n private get conversationThreadId(): IThreadId {\n const { conversationThread } = this.data;\n return conversationThread || this.thread.state.parentThreadId;\n }\n\n /** Fetch conversation data from the conversation data thread */\n private async fetchConversationData({\n conversation,\n conversationThread,\n }: ConversationParameters): Promise<ConversationData | undefined> {\n const conversationDataThread = this.process.getSafeThread(conversationThread);\n return await conversationDataThread.get<Promise<ConversationData>>(conversation);\n }\n}\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport type { IThreadId, IThread, IStepId } from '@onereach/flow-sdk/types/index.js';\nimport { Memoize } from 'typescript-memoize';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport type { GenerateCallTelemetryConfig } from '../main/types.ts';\n\nimport { telemetryAggregatorClassId, telemetryAggregatorEvents } from './constants.ts';\nimport { EventsReducerService } from './services/events-reducer/events-reducer.ts';\nimport { OtelEmitterService } from './services/otel-emitter/otel-emitter.ts';\nimport { TurnsManagerService } from './services/turns-manager/turns-manager.ts';\nimport type { VoiceEvent } from './services/voice/types.ts';\nimport { VoiceService } from './services/voice/voice.ts';\nimport type { TelemetryAggregatorConfig } from './types.ts';\n\nexport class TelemetryAggregator extends BaseStep<TelemetryAggregatorConfig> {\n public static readonly class = telemetryAggregatorClassId;\n\n public static async start(thread: IThread<GenerateCallTelemetryConfig>): Promise<void> {\n const interceptorThreadId = this.getThreadId(thread.step.id);\n const interceptorThread = thread.process.getThread<TelemetryAggregatorConfig>(interceptorThreadId);\n\n if (interceptorThread != undefined) return;\n\n // create thread\n await thread.process.runThread<TelemetryAggregatorConfig>({\n id: interceptorThreadId,\n background: true,\n state: {\n ...TurnsManagerService.statePlaceholder,\n ...EventsReducerService.statePlaceholder,\n\n step: thread.step.id,\n class: this.class,\n\n parentThreadId: thread.id,\n callStartedTimestamp: Date.now(),\n },\n });\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // -------------------------------------\n\n @BackgroundThreadErrorFilter\n public async runStep(): Promise<void> {\n const { id } = await this.voiceService.getConversationData();\n\n this.triggers.local(`in/voice/${id}`, this.onVoiceEvent);\n this.triggers.local(telemetryAggregatorEvents.refreshTurnContext, this.onRefreshTurnContext);\n this.triggers.deadline(this.voiceService.expectHeartbeatBefore, this.onDeadline);\n this.triggers.otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n public onVoiceEvent(event: VoiceEvent): void {\n this.log.DEBUG?.('onVoiceEvent', event);\n\n // TODO: validate event based on zod schema\n\n switch (event.params.type) {\n case 'ack': {\n void this.resumeParentThread();\n break;\n }\n\n case 'tts-audio/started':\n case 'tts-audio/finished':\n case 'tts-audio/interrupted':\n case 'asr-input/started':\n case 'asr-input/ended':\n case 'asr-input/processed': {\n this.eventsReducerService.addEvent(event);\n break;\n }\n\n case 'hangup': {\n const { turnsMap, rawEvents } = this.state;\n this.log.WARN?.('Hangup event received', { turnsMap, rawEvents, event });\n // TODO: end TelemetryAggregator thread\n break;\n }\n\n case 'heartbeat': {\n // do nothing\n break;\n }\n\n default: {\n this.log.WARN?.('Unexpected type of event', event);\n }\n }\n }\n\n @BackgroundThreadErrorFilter\n public async initialize(): Promise<void> {\n this.log.DEBUG?.('Initializing TelemetryAggregator thread');\n await this.turnsManagerService.initializeFirstTurn();\n await this.voiceService.enableTelemetry();\n }\n\n @BackgroundThreadErrorFilter\n public onDeadline(): void {\n this.voiceService.onHeartbeatTimeout();\n }\n\n @BackgroundThreadErrorFilter\n public async onRefreshTurnContext(): Promise<void> {\n await this.turnsManagerService.generateNextTurn();\n }\n\n private async resumeParentThread(): Promise<void> {\n await this.process.enqueueAndRun(this.turnsManagerService.getTelemetryActivatedEvent());\n }\n\n private get voiceService(): VoiceService {\n return new VoiceService(this.thread, this.data);\n }\n\n @Memoize()\n private get otelEmitterService(): OtelEmitterService {\n return new OtelEmitterService(this.thread);\n }\n\n @Memoize()\n private get turnsManagerService(): TurnsManagerService {\n return new TurnsManagerService(this.thread);\n }\n\n @Memoize()\n private get eventsReducerService(): EventsReducerService {\n return new EventsReducerService(this.thread, (turn) => this.otelEmitterService.emitVoiceSpan(turn));\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","export const MINIMAL_FLOW_SDK_VERSION = '8.0.72';\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport { performance } from 'node:perf_hooks';\n\nimport { ErrorFilter } from '../../decorators/error-filter.ts';\nimport { validateFlowSdkVersion } from '../../utils/validate-flow-sdk-version.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { turnsManagerEvents } from '../telemetry-aggregator/constants.ts';\nimport { TelemetryAggregator } from '../telemetry-aggregator/telemetry-aggregator.ts';\nimport type { TelemetryActivatedEvent } from '../telemetry-aggregator/types.ts';\n\nimport { MINIMAL_FLOW_SDK_VERSION } from './constants.ts';\nimport type { GenerateCallTelemetryConfig } from './types.ts';\n\nexport class GenerateCallTelemetryStep extends BaseStep<GenerateCallTelemetryConfig> {\n @ErrorFilter\n public async runStep(): Promise<void> {\n await validateFlowSdkVersion(MINIMAL_FLOW_SDK_VERSION);\n\n this.triggers.local(turnsManagerEvents.telemetryActivated, this.onTelemetryActivated);\n this.triggers.otherwise(this.initialize);\n }\n\n public async initialize(): Promise<void> {\n this.state.activationStart = performance.now();\n await TelemetryAggregator.start(this.thread);\n }\n\n public onTelemetryActivated(event: TelemetryActivatedEvent): void {\n const activationMs = performance.now() - this.state.activationStart;\n this.log.DEBUG?.('onTelemetryActivated', { event, activationMs });\n const { turnContext, turnOtelCarrier } = event.params;\n\n this.exitStep('next', {\n turnContext,\n turnOtelCarrier,\n telemetryThreadId: TelemetryAggregator.getThreadId(this.currentStepId),\n });\n }\n}\n","import { install } from 'source-map-support';\n\nimport { TelemetryAggregator } from './threads/telemetry-aggregator/telemetry-aggregator.ts';\n\n// enable source map support for better error stack traces\ninstall();\n\nexport const states = {\n [TelemetryAggregator.class]: TelemetryAggregator,\n};\nexport { GenerateCallTelemetryStep as step } from './threads/main/step.ts';\n\nexport type * from './types.ts';\n"],"mappings":"ypBAEA,MAAa,EAAY,CACvB,QAAS,UACT,iBAAkB,mBAClB,KAAM,OACN,QAAS,UACT,WAAY,aACZ,gBAAiB,kBACjB,aAAc,eACd,aAAc,eACd,YAAa,aACf,EAEA,IAAa,EAAb,cAAoD,CAGjD,CAAC,ECZJ,MAAM,EAAwB,CAAC,EAAgC,CAAY,EAC3E,SAAgB,EACd,EACA,EAAiC,CAAC,EAC8B,CAChE,GAAM,CACJ,iBAAiB,EACjB,iBAAiB,gBACjB,cAAc,EAAU,SACtB,EAGJ,GAAI,GAAgB,KAAM,GAAe,aAAiB,CAAU,EAClE,OAAO,EAIT,GAAI,aAAiB,EAAE,KAAK,UAC1B,OAAO,IAAI,EAA+B,EAAE,cAAc,CAAK,EAAG,EAAO,CACvE,KAAM,EAAU,UAClB,CAAC,EAIH,GAAI,OAAO,GAAU,SACnB,OAAO,IAAI,EAA+B,EAAO,CAC/C,KAAM,EAAU,OAClB,CAAC,EAGH,GAAI,aAAiB,MAAO,CAE1B,GAAI,EAAM,QAAQ,SAAS,mBAAmB,EAC5C,OAAO,IAAI,EAAa,UAAW,EAAO,CAAE,KAAM,EAAU,OAAQ,CAAC,EAKvE,IAAM,EAA4C,GAA0B,UAAU,MAAM,OAAO,QAOnG,OANI,GAAwB,KAMrB,IAAI,EAA+B,EAAgB,EAAO,CAC/D,KAAM,CACR,CAAC,EAPQ,IAAI,EAA+B,EAAsB,EAAO,CACrE,KAAM,EAAU,YAClB,CAAC,CAML,CAGA,OAAO,IAAI,EAA+B,EAAgB,CACxD,KAAM,EACN,KAAM,CACR,CAAC,CACH,CCrDA,SAAgB,EACd,EAMA,EAC4C,CAC5C,SAAS,EACP,EACA,EACA,EACA,EACmC,CACnC,IAAM,EAAQ,EAAM,EAAS,EAAQ,EAAa,CAAU,EAG5D,GAAI,OAAO,GAAU,WAAY,CAC/B,IAAM,EAAiB,EAAW,MAC5B,EAAgB,EAEtB,GAAI,GAAgB,MAAQ,KAC1B,GAAI,CACF,OAAO,eAAe,EAAe,OAAQ,CAAE,MAAO,EAAe,IAAK,CAAC,CAC7E,MAAQ,CAER,CAIF,MADA,GAAW,MAAQ,EACZ,CACT,CAGA,OAAO,GAAS,CAClB,CAEA,OAAO,SACL,EACA,EACA,EACK,CACL,GAEE,OAAO,GAAc,UADrB,IAEC,OAAO,GAAc,UAAY,OAAO,GAAc,WAEvD,OAAO,GAAc,UADrB,EAIA,OAAO,EAAS,EAAgB,EAAW,EAAW,CAAS,EAC1D,CAEL,IAAM,EAAW,GAAmB,EACpC,OAAQ,EAAgB,EAA8B,IAC7C,EAAS,EAAS,EAAQ,EAAa,CAAU,CAE5D,CACF,CACF,CCrDA,MAAa,EAA8B,GACxC,EAAS,EAAS,EAAa,IAAe,CAC7C,IAAM,EAAiB,EAAW,MAC9B,MAAC,GAAkB,OAAO,GAAmB,YAEjD,OAAO,SAAsB,GAAG,EAAkF,CAChH,GAAI,CACF,IAAM,EAAkB,EAAe,MAAM,KAAM,CAAU,EAM7D,OAJI,aAAkB,QACb,EAAO,MAAO,GAAU,EAAa,KAAK,KAAM,EAAS,EAAO,CAAW,CAAC,EAG9E,CACT,OAAS,EAAO,CACd,OAAO,EAAa,KAAK,KAAM,EAAS,EAAO,CAAW,CAC5D,CACF,CACF,EACAA,CA3B2D,iBAAkB,GAAO,eAAgB,EA2BpGA,CACF,EAEA,SAAS,EAEP,EACA,EACA,EACM,CACN,IAAM,EAAa,EAAY,SAAS,EACxC,KAAK,IAAI,QAAQ,oBAAoB,EAAW,GAAI,CAAK,EACzD,IAAM,EAAgB,EAAQ,eAAiB,EAAY,CAAK,EAAI,EAEpE,GAAI,aAAyB,MAC3B,GAAI,EAAQ,iBAAkB,CAE5B,KAAK,OAAO,QAAQ,CAAE,KAAM,EAAO,MAAO,MAAO,CAAc,CAAC,EAChE,MACF,KAAO,CAEL,KAAK,IAAI,CAAa,EACtB,MACF,CAIF,MAAM,CACR,CClDA,MAAa,EAAc,GAA4C,EAAU,EAAS,EAAa,IAAe,CACpH,IAAM,EAAiB,EAAW,MAE9B,MAAC,GAAkB,OAAO,GAAmB,YAEjD,OAAO,SAAsB,GAAG,EAAkF,CAChH,GAAI,CACF,IAAM,EAAkB,EAAe,MAAM,KAAM,CAAU,EAU7D,OARI,aAAkB,QACb,EAAO,MAAO,GAAmB,CACtC,IAAM,EAAa,EAAY,SAAS,EAExC,MADA,KAAK,IAAI,QAAQ,oBAAoB,EAAW,GAAI,CAAK,EACnD,EAAY,CAAK,CACzB,CAAC,EAGI,CACT,OAAS,EAAO,CACd,IAAM,EAAa,EAAY,SAAS,EAExC,MADA,KAAK,IAAI,QAAQ,oBAAoB,EAAW,GAAI,CAAK,EACnD,EAAY,CAAK,CACzB,CACF,CACF,EAAG,CAAA,CAAc,EChCjBC,EAAE,OAAOA,EAAE,QAAQ,GAAG,CAAC,EAGvB,MAAM,EAA0BA,EAAE,OAAO,EAAE,MACzCA,EAAE,KAAK,EACPA,EAAE,OAAQ,GAAU,CAAC,CAAC,YAAa,MAAM,EAAE,SAAS,CAAK,EAAG,CAC1D,MAAO,gDACT,CAAC,CACH,EAEa,EAAeA,EAAE,OAAO,CACnC,aAAc,EAAwB,MAAMA,EAAE,UAAU,CAAC,CAAC,EAC1D,mBAAoB,CACtB,CAAC,qbCPD,IAAa,EAAb,cAAoD,CAAQ,CAC1D,MACa,eAAgB,CAC3B,IAAM,EAAS,MAAM,MAAM,cAAc,EACzC,OAAO,EAAa,MAAM,CAAM,CAClC,CACF,KALG,wHCTH,MCAa,EAAqB,CAChC,mBAAoB,iBACtB,ECEa,EAA4B,CACvC,mBAAoB,cACtB,ECEA,IAAa,EAAb,cAA0C,CAA8C,CACtF,YAEA,YAAmB,EAA4C,EAA+B,CAC5F,MAAM,CAAM,EAEZ,KAAK,YAAc,CACrB,CAEA,WAAkB,kBAAuC,CACvD,MAAO,CAGL,UAAW,CAAC,CACd,CACF,CAEA,SAAgB,EAAyB,CACvC,KAAK,OAAO,MAAM,UAAU,KAAK,CAAK,EAEtC,IAAM,EAAO,KAAK,iBAAiB,CAAK,EACxC,KAAK,YAAY,EAAM,CAAK,EAExB,EAAK,UAAY,CAAC,EAAK,YACzB,KAAU,YAAY,CAAI,EAC1B,EAAK,UAAY,GAErB,CAEA,iBAAyB,EAAyB,CAChD,IAAM,EAAc,OAAO,OAAO,KAAK,OAAO,MAAM,QAAQ,EAAE,SAAU,GAEnE,EAAM,OAAO,MAAM,aAAa,YAAY,GAAK,EAAK,aAAe,EAAM,QAAQ,SACnF,EAAM,OAAO,MAAM,aAAa,YAAY,GAAK,EAAK,KAAO,EAAM,QAAQ,YAAY,QACvF,EAAM,OAAO,OAAS,qBAAuB,EAAK,qBAAuB,IAE7E,EAED,GAAI,GAAe,KACjB,MAAM,IAAI,EAA+B,2BAA4B,CACnE,KAAM,mBACN,KAAM,CACJ,OACF,CACF,CAAC,EAEH,OAAO,CACT,CAEA,YAAoB,EAAY,EAAyB,CACvD,OAAQ,EAAM,OAAO,KAArB,CACE,IAAK,oBACH,KAAK,sBAAsB,EAAO,CAAI,EACtC,EAAK,WAAa,EAAM,OAAO,QAC/B,EAAK,oBAAsB,EAAM,OAAO,UACxC,MAEF,IAAK,kBACH,KAAK,sBAAsB,EAAO,CAAI,EACtC,EAAK,kBAAoB,EAAM,OAAO,UACtC,MAEF,IAAK,sBACH,KAAK,sBAAsB,EAAO,CAAI,EACtC,EAAK,sBAAwB,EAAM,OAAO,UAC1C,EAAK,mBAAqB,EAAM,OAAO,gBACvC,EAAK,mBAAqB,EAAM,OAAO,QAAQ,KAC/C,EAAK,YAAc,EAAM,OAAO,YAChC,EAAK,aAAe,EAAM,OAAO,aACjC,MAGF,IAAK,oBACH,KAAK,sBAAsB,EAAO,CAAI,EACtC,EAAK,YAAc,EAAM,OAAO,YAChC,EAAK,oBAAsB,EAAM,OAAO,UACxC,MAEF,IAAK,wBACH,KAAK,sBAAsB,EAAO,CAAI,EACtC,EAAK,wBAA0B,EAAM,OAAO,YAC5C,EAAK,eAAiB,cACtB,EAAK,kBAAoB,EAAM,OAAO,UACtC,EAAK,aAAe,EAAM,OAAO,aAEjC,EAAK,aAAe,EAAM,OAAO,UAEjC,EAAK,SAAW,GAChB,MAEF,IAAK,qBACH,KAAK,sBAAsB,EAAO,CAAI,EACtC,EAAK,eAAiB,QACtB,EAAK,kBAAoB,EAAM,OAAO,UACtC,EAAK,aAAe,EAAM,OAAO,aAEjC,EAAK,aAAe,EAAM,OAAO,UAEjC,EAAK,SAAW,GAChB,MAGF,QACE,KAAK,IAAI,OAAO,qBAAsB,CAAK,CAE/C,CACF,CAEA,sBAA8B,EAAmB,EAAkB,CACjE,GAAI,EAAK,YAAc,EAAK,aAAe,EAAM,OAAO,QAAS,CAC/D,IAAM,EAAU,YAAY,EAAM,OAAO,KAAK,oBAC9C,KAAK,IAAI,OAAO,EAAS,CACvB,SAAU,EAAK,WACf,OAAQ,EAAM,OAAO,QACrB,OACF,CAAC,EACD,KAAK,kBAAkB,EAAM,CAAO,CACtC,CACF,CAEA,sBAA8B,EAAmB,EAAkB,CACjE,GAAI,EAAK,IAAM,EAAK,KAAO,EAAM,OAAO,YAAY,OAAQ,CAC1D,IAAM,EAAU,YAAY,EAAM,OAAO,KAAK,oBAC9C,KAAK,IAAI,OAAO,EAAS,CACvB,SAAU,EAAK,GACf,OAAQ,EAAM,OAAO,YAAY,OACjC,OACF,CAAC,EACD,KAAK,kBAAkB,EAAM,CAAO,CACtC,CACF,CAEA,kBAA0B,EAAY,EAAsB,CAC1D,EAAK,QAAU,GACf,EAAK,iBAAmB,CAAC,EACzB,EAAK,eAAe,KAAK,CAAM,CACjC,CACF,ECvIa,EAAb,cAAwC,CAA8C,CAEpF,cAAqB,EAAkB,CACrC,GAAI,CAAC,EAAK,gBAAkB,CAAC,EAAK,aAChC,MAAM,IAAI,EAA+B,iDAAkD,CACzF,KAAM,EAAU,gBAClB,CAAC,EAIH,IAAM,EAAW,KAAK,OAAO,UAC3B,aACA,CACE,WAAY,KAAK,kBAAkB,CAAI,EACvC,UAAW,EAAK,cAClB,EACA,KAAK,WACP,EACM,EAAc,EAAM,QAAQ,EAAQ,OAAO,EAAG,CAAQ,EAG5D,GAAI,EAAK,qBAAuB,EAAK,kBAAmB,CACtD,IAAM,EAAU,KAAK,OAAO,UAC1B,YACA,CACE,UAAW,EAAK,oBAChB,WAAY,CACV,GAAG,KAAK,kBAAkB,CAAI,EAC9B,eAAgB,EAAK,YACrB,eAAgB,EAAK,WACrB,uBAAwB,EAAK,mBAC7B,uBAAwB,EAAK,kBAC/B,CACF,EACA,CACF,EACM,EAAa,EAAM,QAAQ,EAAQ,OAAO,EAAG,CAAO,EAE1D,EAAQ,UAAU,CAAE,KAAM,EAAe,EAAG,CAAC,EAC7C,EAAQ,IAAI,EAAK,iBAAiB,EAGlC,KAAK,YAAY,OACf,EAAK,kBAAoB,EAAK,oBAC9B,CACE,GAAG,KAAK,kBAAkB,CAAI,EAC9B,eAAgB,EAAK,YACrB,eAAgB,EAAK,UACvB,EACA,CACF,EAEI,EAAK,oBAAsB,MAC7B,KAAK,mBAAmB,OACtB,EAAK,mBAAqB,IAC1B,CACE,GAAG,KAAK,kBAAkB,CAAI,EAC9B,eAAgB,EAAK,YACrB,eAAgB,EAAK,UACvB,EACA,CACF,CAEJ,CAGA,GAAI,EAAK,qBAAuB,EAAK,kBAAmB,CACtD,IAAM,EAAU,KAAK,OAAO,UAC1B,YACA,CACE,UAAW,EAAK,oBAChB,WAAY,CACV,GAAG,KAAK,kBAAkB,CAAI,EAC9B,eAAgB,EAAK,YACrB,mBAAoB,EAAK,eACzB,wBAAyB,EAAK,uBAChC,CACF,EACA,CACF,EACM,EAAa,EAAM,QAAQ,EAAQ,OAAO,EAAG,CAAO,EAC1D,EAAQ,UAAU,CAAE,KAAM,EAAe,EAAG,CAAC,EAC7C,EAAQ,IAAI,EAAK,iBAAiB,EAElC,KAAK,YAAY,OACf,EAAK,kBAAoB,EAAK,oBAC9B,CACE,GAAG,KAAK,kBAAkB,CAAI,EAC9B,eAAgB,EAAK,YACrB,mBAAoB,EAAK,cAC3B,EACA,CACF,CACF,CAEA,EAAS,UAAU,CAAE,KAAM,EAAe,EAAG,CAAC,EAC9C,EAAS,IAAI,EAAK,YAAY,EAG9B,KAAK,aAAa,IAAI,EAAG,KAAK,kBAAkB,CAAI,EAAG,CAAW,EAElE,KAAK,aAAa,OAAO,EAAK,aAAe,EAAK,eAAgB,KAAK,kBAAkB,CAAI,EAAG,CAAW,EAEvG,EAAK,qBAAuB,EAAK,mBACnC,KAAK,oBAAoB,OACvB,EAAK,oBAAsB,EAAK,kBAChC,KAAK,kBAAkB,CAAI,EAC3B,CACF,EAGE,EAAK,iBAAmB,eAC1B,KAAK,aAAa,IAAI,EAAG,KAAK,kBAAkB,CAAI,EAAG,CAAW,EAGpE,IAAM,EAAe,OAAO,OAAO,KAAK,OAAO,MAAM,QAAQ,EAAE,KAAM,GAAM,EAAE,QAAU,EAAK,MAAQ,CAAC,EAEnG,GACA,EAAa,iBAAmB,eAChC,EAAa,mBACb,EAAK,sBAEL,KAAK,eAAe,OAClB,EAAa,kBAAoB,EAAK,oBACtC,KAAK,kBAAkB,CAAI,EAC3B,CACF,EACA,KAAK,YAAY,OACd,KAAO,EAAa,kBAAoB,EAAK,sBAAyB,EAAK,aAAe,EAAK,gBAChG,KAAK,kBAAkB,CAAI,EAC3B,CACF,EAEJ,CAGA,eAA6B,CAC3B,KAAK,SAAS,UAAU,CAAE,KAAM,EAAe,EAAG,CAAC,EAEnD,KAAK,SAAS,IAAI,EAGlB,KAAK,mBAAmB,IAAI,GAAI,KAAK,eAAgB,KAAK,WAAW,CACvE,CAGA,cAA6B,CAC3B,GAAI,KAAK,OAAO,MAAM,qBAAuB,KAC3C,MAAM,IAAI,EAA+B,2BAA4B,CACnE,KAAM,EAAU,gBAClB,CAAC,EAGH,IAAM,EAAW,KAAK,OAAO,UAAU,aAAc,CACnD,KAAM,GACN,UAAW,KAAK,OAAO,MAAM,qBAC7B,WAAY,KAAK,cACnB,CAAC,EAGD,KAAK,OAAO,MAAM,oBAAsB,EAAS,YAAY,EAG7D,IAAM,EAAc,EAAM,QAAQ,EAAQ,OAAO,EAAG,CAAQ,EACtD,EAAsC,CAAC,EAQ7C,OAPA,EAAY,OAAO,EAAa,CAAW,EAC3C,KAAK,OAAO,MAAM,gBAAkB,EAGpC,KAAK,kBAAkB,IAAI,EAAG,KAAK,eAAgB,KAAK,WAAW,EACnE,KAAK,mBAAmB,IAAI,EAAG,KAAK,eAAgB,KAAK,WAAW,EAE7D,CACT,CAGA,kBAA0B,EAAwB,CAChD,MAAO,CACL,GAAG,EAAK,WACR,gBAAiB,EAAK,GACtB,mBAAoB,EAAK,MACzB,gBAAiB,KAAK,OAAO,MAAM,cAAc,GACjD,mBAAoB,KAAK,OAAO,MAAM,cAAc,aACtD,CACF,CAGA,IACY,UAAiB,CAC3B,IAAI,EAAW,KAAK,OAAO,UAAU,aAAc,CACjD,KAAM,GACN,UAAW,KAAK,OAAO,MAAM,qBAC7B,WAAY,KAAK,cACnB,CAAC,EAWD,OATI,KAAK,OAAO,MAAM,sBAEpB,EAAW,KAAK,aAAa,GAK/B,EAAkB,aAAe,KAAK,OAAO,MAAM,oBAE5C,CACT,CAGA,IACY,aAAuB,CACjC,OAAO,EAAM,QAAQ,EAAQ,OAAO,EAAG,KAAK,QAAQ,CACtD,CAGA,IACY,OAAe,CACzB,OAAO,EAAQ,SAAS,QAAQ,CAClC,CAGA,IACY,QAAiB,CAC3B,OAAO,EAAM,UAAU,QAAQ,CACjC,CAGA,IACY,oBAAgD,CAC1D,OAAO,KAAK,MAAM,oBAAoB,2BAA4B,CAChE,YAAa,+BACb,KAAM,GACR,CAAC,CACH,CAGA,IACY,mBAAyC,CACnD,OAAO,KAAK,MAAM,cAAc,0BAA2B,CACzD,YAAa,8BACb,KAAM,GACR,CAAC,CACH,CA4BA,IACY,qBAA6C,CACvD,OAAO,KAAK,MAAM,gBAAgB,+BAAgC,CAChE,YAAa,4CACb,KAAM,IACR,CAAC,CACH,CAGA,IACY,aAAqC,CAC/C,OAAO,KAAK,MAAM,gBAAgB,qBAAsB,CACtD,YAAa,iCACb,KAAM,IACR,CAAC,CACH,CAEA,IACY,oBAA4C,CACtD,OAAO,KAAK,MAAM,gBAAgB,6BAA8B,CAC9D,YAAa,yCACb,KAAM,GACR,CAAC,CACH,CAGA,IACY,aAAqC,CAC/C,OAAO,KAAK,MAAM,gBAAgB,qBAAsB,CACtD,YAAa,iCACb,KAAM,IACR,CAAC,CACH,CAGA,IACY,cAAoC,CAC9C,OAAO,KAAK,MAAM,cAAc,oBAAqB,CACnD,YAAa,6CACb,KAAM,GACR,CAAC,CACH,CAEA,IACY,cAAsC,CAChD,OAAO,KAAK,MAAM,gBAAgB,sBAAuB,CACvD,YAAa,2BACb,KAAM,IACR,CAAC,CACH,CAGA,IACY,cAAoC,CAC9C,OAAO,KAAK,MAAM,cAAc,uBAAwB,CACtD,YAAa,wBACb,KAAM,GACR,CAAC,CACH,CAEA,IACY,gBAAwC,CAClD,OAAO,KAAK,MAAM,gBAAgB,yBAA0B,CAC1D,YAAa,0BACb,KAAM,IACR,CAAC,CACH,CAEA,IACY,aAAqC,CAC/C,OAAO,KAAK,MAAM,gBAAgB,sBAAuB,CACvD,YAAa,mDACb,KAAM,GACR,CAAC,CACH,CAGA,IAAY,gBAA6B,CACvC,MAAO,CACL,gBAAiB,KAAK,OAAO,MAAM,cAAc,GACjD,uBAAwB,KAAK,OAAO,MAAM,cAAc,QAAU,UAAY,WAC9E,uBAAwB,KAAK,OAAO,MAAM,cAAc,UACxD,mBAAoB,KAAK,OAAO,MAAM,cAAc,cACpD,kBAAmB,KAAK,OAAO,MAAM,cAAc,SACnD,wBAAyB,KAAK,OAAO,MAAM,cAAc,EAC3D,CACF,CACF,KAzKG,EAAQ,qFAqBR,EAAQ,wFAMR,EAAQ,kFAMR,EAAQ,mFAMR,EAAQ,+FASR,EAAQ,8FAkCR,EAAQ,gGASR,EAAQ,wFAQR,EAAQ,+FASR,EAAQ,wFASR,EAAQ,yFAQR,EAAQ,yFASR,EAAQ,yFAQR,EAAQ,2FAQR,EAAQ,qFCnVX,IAAa,EAAb,cAAyC,CAA8C,CACrF,WAAkB,kBAAsC,CACtD,MAAO,CACL,KAAM,IAAA,GACN,SAAU,CAAC,CACb,CACF,CAKA,MAAa,qBAAqC,CAChD,GAAI,KAAK,OAAO,MAAM,MAAQ,KAAW,CACvC,KAAK,OAAO,IAAI,OAAO,4DAA4D,EACnF,MACF,CAEA,KAAK,OAAO,IAAI,QAAQ,2BAA2B,EACnD,MAAM,KAAK,aAAa,CAC1B,CAGA,MAAa,kBAAkC,CAC7C,GAAI,KAAK,OAAO,MAAM,MAAQ,KAAW,CACvC,KAAK,OAAO,IAAI,OAAO,kEAAkE,EACzF,MAAM,KAAK,oBAAoB,EAC/B,MACF,CAEA,KAAK,OAAO,IAAI,QAAQ,yBAAyB,EACjD,MAAM,KAAK,aAAa,CAC1B,CAMA,4BAA6D,CAC3D,GAAM,CAAE,cAAa,mBAAoB,KAAK,eAAe,EAC7D,MAAO,CACL,KAAM,EAAmB,mBACzB,OAAQ,CAAE,cAAa,iBAAgB,EACvC,OAAQ,KAAK,OAAO,MAAM,cAC5B,CACF,CAEA,MAAc,cAA8B,CAC1C,IAAM,EAAgB,KAAK,OAAO,MAAM,MAAM,OAAS,GACjD,EAAW,KAAK,WAAW,CAAa,EAC9C,KAAK,OAAO,MAAM,KAAO,EACzB,KAAK,OAAO,MAAM,SAAS,EAAS,IAAM,EAE1C,MAAM,KAAK,mBAAmB,CAChC,CAEA,WAAmB,EAA6B,CAgB9C,MAAO,CAZL,GAHa,OAAO,WAGX,EACT,MAHgB,EAAgB,EAIhC,UAAW,GACX,SAAU,GACV,WAAY,CACV,gBAAiB,KAAK,OAAO,MAAM,cAAc,GACjD,UAAW,KAAK,OAAO,KAAK,OAAO,OACnC,cAAe,KAAK,OAAO,KAAK,OAAO,MACvC,WAAY,KAAK,OAAO,QAAQ,UAAU,UAC1C,YAAa,KAAK,OAAO,QAAQ,UAAU,kBAC7C,CAEQ,CACZ,CAEA,MAAc,oBAAoC,CAChD,GAAM,CAAE,cAAa,mBAAoB,KAAK,eAAe,EAG7D,MAAM,KAAK,OAAO,WAAW,CAC3B,cACA,kBACA,kBAAmB,KAAK,OAAO,EACjC,CAAC,CACH,CAEA,gBAAyB,CACvB,GAAI,KAAK,OAAO,MAAM,MAAQ,MAAa,KAAK,OAAO,MAAM,KAAK,aAAe,KAC/E,MAAM,IAAI,EAA+B,0BAA2B,CAClE,KAAM,EAAU,gBAClB,CAAC,EAGH,MAAO,CACL,YAAa,CACX,OAAQ,KAAK,OAAO,MAAM,KAAK,GAC/B,UAAW,KAAK,OAAO,MAAM,KAAK,KACpC,EACA,gBAAiB,KAAK,OAAO,MAAM,KAAK,WAC1C,CACF,CACF,ECzGa,EAAb,cAGU,CAA4B,CACpC,KAEA,YAAY,EAA0B,EAAa,CACjD,MAAM,CAAM,EACZ,KAAK,KAAO,CACd,CACF,ECLa,EAAb,cAAkC,CAAiD,CAEjF,MAAa,oBAAoB,CAAE,SAA+B,CAAC,EAA8B,CAC/F,IAAM,EAAoB,KAAK,OAAO,MAAM,aAC5C,GAAI,GAAqB,IAAU,GAAM,OAAO,EAEhD,GAAM,CAAE,gBAAiB,KAAK,KAExB,EAAiD,CACrD,eACA,mBAAoB,KAAK,oBAC3B,EACM,EAAO,MAAM,KAAK,sBAAsB,CAAsB,EACpE,GAAI,CAAC,GAAQ,EAAK,OAAS,KACzB,MAAM,IAAI,EAA+B,4BAA6B,CACpE,KAAM,EAAU,WAChB,KAAM,CACR,CAAC,EAKH,MAFA,MAAK,OAAO,MAAM,aAAe,EAE1B,CACT,CAGA,MAAa,iBAAiC,CAC5C,GAAI,CAAC,KAAK,OAAO,MAAM,aACrB,MAAM,IAAI,EAA+B,qCAAsC,CAC7E,KAAM,EAAU,UAClB,CAAC,EAGH,GAAM,CAAE,KAAI,OAAM,YAAa,KAAK,OAAO,MAAM,aAE3C,EAAQ,CACZ,OAAQ,KAAK,OAAO,QAAQ,mBAC5B,KAAM,aAAa,IACnB,OAAQ,CACN,KACA,MAAO,GACP,IAAK,GACL,SAAU,CACR,CACE,KAAM,kBACN,OAAQ,CAAE,IAAK,EAAK,CACtB,CACF,EACA,KAAM,CACJ,IAAK,KAAK,QAAQ,IAClB,IAAK,KAAK,OAAO,EACnB,CACF,EAEA,UAAW,CACT,GAAG,KAAK,QAAQ,cAAc,CAChC,CACF,EAEA,KAAK,IAAI,QAAQ,uBAAwB,CAAK,EAE9C,IAAM,EAAS,MAAM,KAAK,OAAO,aAAa,KAAK,EAAO,CACxD,OAAQ,EACR,eAAgB,QAChB,QAAS,GACX,CAAC,EAGD,GAFA,KAAK,IAAI,QAAQ,wBAAyB,CAAM,EAE5C,GAAU,KAEZ,MAAM,IAAI,EAA+B,4BAA6B,CACpE,KAAM,EAAU,aAChB,KAAM,CACR,CAAC,CAEL,CAGA,IAAW,uBAAgC,CACzC,OAAO,KAAK,IAAI,EAAI,GACtB,CAGA,oBAAkC,CAChC,KAAK,IAAI,OAAO,gDAAgD,EAChE,KAAK,OAAO,IAAI,CAClB,CAGA,IAAY,sBAAkC,CAC5C,GAAM,CAAE,sBAAuB,KAAK,KACpC,OAAO,GAAsB,KAAK,OAAO,MAAM,cACjD,CAGA,MAAc,sBAAsB,CAClC,eACA,sBACgE,CAEhE,OAAO,MADwB,KAAK,QAAQ,cAAc,CACxB,EAAE,IAA+B,CAAY,CACjF,CACF,QC5Fa,EAAb,cAAyC,CAAoC,CAC3E,OAAuB,MAAQ,WAE/B,aAAoB,MAAM,EAA6D,CACrF,IAAM,EAAsB,KAAK,YAAY,EAAO,KAAK,EAAE,EACjC,EAAO,QAAQ,UAAqC,CAE1D,GAGpB,MAAM,EAAO,QAAQ,UAAqC,CACxD,GAAI,EACJ,WAAY,GACZ,MAAO,CACL,GAAG,EAAoB,iBACvB,GAAG,EAAqB,iBAExB,KAAM,EAAO,KAAK,GAClB,MAAO,KAAK,MAEZ,eAAgB,EAAO,GACvB,qBAAsB,KAAK,IAAI,CACjC,CACF,CAAC,CACH,CAEA,OAAc,YAAY,EAA4B,CACpD,MAAO,YAAwB,KAAK,MAAM,GAAG,GAC/C,CAIA,MACa,SAAyB,CACpC,GAAM,CAAE,MAAO,MAAM,KAAK,aAAa,oBAAoB,EAE3D,KAAK,SAAS,MAAM,YAAY,IAAM,KAAK,YAAY,EACvD,KAAK,SAAS,MAAM,EAA0B,mBAAoB,KAAK,oBAAoB,EAC3F,KAAK,SAAS,SAAS,KAAK,aAAa,sBAAuB,KAAK,UAAU,EAC/E,KAAK,SAAS,UAAU,KAAK,UAAU,CACzC,CAEA,aACoB,EAAyB,CAK3C,OAJA,KAAK,IAAI,QAAQ,eAAgB,CAAK,EAI9B,EAAM,OAAO,KAArB,CACE,IAAK,MACH,KAAU,mBAAmB,EAC7B,MAGF,IAAK,oBACL,IAAK,qBACL,IAAK,wBACL,IAAK,oBACL,IAAK,kBACL,IAAK,sBACH,KAAK,qBAAqB,SAAS,CAAK,EACxC,MAGF,IAAK,SAAU,CACb,GAAM,CAAE,WAAU,aAAc,KAAK,MACrC,KAAK,IAAI,OAAO,wBAAyB,CAAE,WAAU,YAAW,OAAM,CAAC,EAEvE,KACF,CAEA,IAAK,YAEH,MAGF,QACE,KAAK,IAAI,OAAO,2BAA4B,CAAK,CAErD,CACF,CAEA,MACa,YAA4B,CACvC,KAAK,IAAI,QAAQ,yCAAyC,EAC1D,MAAM,KAAK,oBAAoB,oBAAoB,EACnD,MAAM,KAAK,aAAa,gBAAgB,CAC1C,CAEA,YAC0B,CACxB,KAAK,aAAa,mBAAmB,CACvC,CAEA,MACa,sBAAsC,CACjD,MAAM,KAAK,oBAAoB,iBAAiB,CAClD,CAEA,MAAc,oBAAoC,CAChD,MAAM,KAAK,QAAQ,cAAc,KAAK,oBAAoB,2BAA2B,CAAC,CACxF,CAEA,IAAY,cAA6B,CACvC,OAAO,IAAI,EAAa,KAAK,OAAQ,KAAK,IAAI,CAChD,CAEA,IACY,oBAAyC,CACnD,OAAO,IAAI,EAAmB,KAAK,MAAM,CAC3C,CAEA,IACY,qBAA2C,CACrD,OAAO,IAAI,EAAoB,KAAK,MAAM,CAC5C,CAEA,IACY,sBAA6C,CACvD,OAAO,IAAI,EAAqB,KAAK,OAAS,GAAS,KAAK,mBAAmB,cAAc,CAAI,CAAC,CACpG,CACF,KAzFG,qHAUA,+HAwCA,wHAOA,uHAKA,kIAaA,EAAQ,qIAKR,EAAQ,sIAKR,EAAQ,oICpIX,MAAM,EAAU,EAAc,OAAO,KAAK,GAAG,EAE7C,eAAsB,EAAuB,EAAmC,CAC9E,GAAI,OAAO,GAAe,UAAY,CAAC,kBAAkB,KAAK,CAAU,EACtE,MAAU,MAAM,mCAAmC,GAAY,EAGjE,IAAM,EAAkB,EAAQ,QAAQ,iCAAiC,EACzE,GAAI,CAAC,EACH,MAAU,MAAM,oDAAoD,EAGtE,IAAM,EAAqB,MAAM,EAAS,EAAiB,MAAM,EAE3D,CAAE,WAAY,KAAK,MAAM,CAAkB,EAC3C,CAAE,UAAW,+CAA+C,KAAK,CAAO,GAAK,CAAC,EAEpF,GAAI,CAAC,EAAQ,MAAU,MAAM,oCAAoC,GAAS,EAE1E,IAAM,EAAQ,OAAO,SAAS,EAAO,OAAS,IAAK,EAAE,EAC/C,EAAQ,OAAO,SAAS,EAAO,OAAS,IAAK,EAAE,EAC/C,EAAQ,OAAO,SAAS,EAAO,OAAS,IAAK,EAAE,EAErD,GACE,GAAS,MACT,GAAS,MACT,GAAS,MACT,OAAO,MAAM,CAAK,GAClB,OAAO,MAAM,CAAK,GAClB,OAAO,MAAM,CAAK,EAElB,MAAU,MAAM,2BAA2B,GAAS,EAGtD,GAAM,CAAC,EAAU,EAAU,GAAY,EAAW,MAAM,GAAG,EAAE,IAAK,GAAM,OAAO,SAAS,EAAG,EAAE,CAAC,EAE9F,GACE,GAAY,MACZ,GAAY,MACZ,GAAY,MACZ,OAAO,MAAM,CAAQ,GACrB,OAAO,MAAM,CAAQ,GACrB,OAAO,MAAM,CAAQ,EAErB,MAAU,MAAM,mCAAmC,GAAY,EAGjE,GACE,EAAQ,GACP,IAAU,GAAY,EAAQ,GAC9B,IAAU,GAAY,IAAU,GAAY,EAAQ,EAErD,MAAU,MACR,qBAAqB,EAAQ,4CAA4C,EAAW,eACtF,CAEJ,CE7CA,IAAa,EAAb,cAA+C,CAAsC,CACnF,MACa,SAAyB,CACpC,MAAM,EAAuB,QAAwB,EAErD,KAAK,SAAS,MAAM,EAAmB,mBAAoB,KAAK,oBAAoB,EACpF,KAAK,SAAS,UAAU,KAAK,UAAU,CACzC,CAEA,MAAa,YAA4B,CACvC,KAAK,MAAM,gBAAkB,EAAY,IAAI,EAC7C,MAAM,EAAoB,MAAM,KAAK,MAAM,CAC7C,CAEA,qBAA4B,EAAsC,CAChE,IAAM,EAAe,EAAY,IAAI,EAAI,KAAK,MAAM,gBACpD,KAAK,IAAI,QAAQ,uBAAwB,CAAE,QAAO,cAAa,CAAC,EAChE,GAAM,CAAE,cAAa,mBAAoB,EAAM,OAE/C,KAAK,SAAS,OAAQ,CACpB,cACA,kBACA,kBAAmB,EAAoB,YAAY,KAAK,aAAa,CACvE,CAAC,CACH,CACF,KAxBG,kHCVH,EAAQ,EAER,MAAa,EAAS,EACnB,EAAoB,OAAQ,CAC/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onereach/step-generate-call-telemetry",
3
- "version": "0.0.2-rc.1",
3
+ "version": "0.0.2-rc.10",
4
4
  "description": "Logic for generating call telemetry step",
5
5
  "keywords": [],
6
6
  "license": "MIT",
@@ -15,18 +15,20 @@
15
15
  "dist"
16
16
  ],
17
17
  "dependencies": {
18
+ "@opentelemetry/api": "^1.9.1",
19
+ "@opentelemetry/semantic-conventions": "^1.41.1",
18
20
  "source-map-support": "^0.5.21",
19
21
  "timestring": "^7.0.0",
20
22
  "tslib": "^2.8.1",
21
23
  "typescript-memoize": "^1.1.1",
22
- "zod": "^4.3.6"
24
+ "zod": "^4.4.3"
23
25
  },
24
26
  "devDependencies": {
25
- "@aws-sdk/client-kms": "^3.1014.0",
26
- "@onereach/flow-sdk": "^8.0.76",
27
- "@onereach/orb-em-core": "^8.0.13",
28
- "@onereach/orb-em-plugin-emitter": "^8.0.13",
29
- "@onereach/orb-test-helpers": "^8.0.13",
27
+ "@aws-sdk/client-kms": "^3.1049.0",
28
+ "@onereach/flow-sdk": "^8.1.8",
29
+ "@onereach/orb-em-core": "^8.0.26",
30
+ "@onereach/orb-em-plugin-emitter": "^8.0.26",
31
+ "@onereach/orb-test-helpers": "^8.0.26",
30
32
  "@types/source-map-support": "^0.5.10",
31
33
  "@types/timestring": "^7.0.0"
32
34
  },
@@ -36,7 +38,7 @@
36
38
  "scripts": {
37
39
  "build": "tsdown --config tsdown.config.ts",
38
40
  "build:visualize": "VISUALIZE=1 pnpm build",
39
- "publish:rc": "pnpm version prerelease --preid rc && pnpm publish --tag rc",
41
+ "publish:rc": "pnpm version prerelease --preid rc --no-git-tag-version && pnpm publish --tag rc --no-git-checks",
40
42
  "test": "pnpm unit",
41
43
  "unit": "exit 0 ||vitest run",
42
44
  "preversion": "pnpm build && pnpm test"