@absolutejs/voice 0.0.22-beta.14 → 0.0.22-beta.141

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.
Files changed (160) hide show
  1. package/README.md +781 -5
  2. package/dist/agent.d.ts +24 -0
  3. package/dist/agentSquadContract.d.ts +64 -0
  4. package/dist/angular/index.d.ts +9 -0
  5. package/dist/angular/index.js +1418 -46
  6. package/dist/angular/voice-campaign-dialer-proof.service.d.ts +14 -0
  7. package/dist/angular/voice-controller.service.d.ts +1 -0
  8. package/dist/angular/voice-ops-status.component.d.ts +15 -0
  9. package/dist/angular/voice-ops-status.service.d.ts +12 -0
  10. package/dist/angular/voice-provider-capabilities.service.d.ts +12 -0
  11. package/dist/angular/voice-provider-status.service.d.ts +12 -0
  12. package/dist/angular/voice-routing-status.service.d.ts +11 -0
  13. package/dist/angular/voice-stream.service.d.ts +3 -0
  14. package/dist/angular/voice-trace-timeline.service.d.ts +12 -0
  15. package/dist/angular/voice-turn-latency.service.d.ts +13 -0
  16. package/dist/angular/voice-turn-quality.service.d.ts +12 -0
  17. package/dist/angular/voice-workflow-status.service.d.ts +12 -0
  18. package/dist/assistantHealth.d.ts +81 -0
  19. package/dist/audit.d.ts +128 -0
  20. package/dist/auditDeliveryRoutes.d.ts +85 -0
  21. package/dist/auditExport.d.ts +34 -0
  22. package/dist/auditRoutes.d.ts +66 -0
  23. package/dist/auditSinks.d.ts +133 -0
  24. package/dist/bargeInRoutes.d.ts +56 -0
  25. package/dist/campaign.d.ts +610 -0
  26. package/dist/campaignDialers.d.ts +90 -0
  27. package/dist/client/actions.d.ts +105 -0
  28. package/dist/client/bargeInMonitor.d.ts +7 -0
  29. package/dist/client/campaignDialerProof.d.ts +23 -0
  30. package/dist/client/connection.d.ts +3 -0
  31. package/dist/client/duplex.d.ts +1 -1
  32. package/dist/client/htmxBootstrap.js +747 -15
  33. package/dist/client/index.d.ts +40 -0
  34. package/dist/client/index.js +2162 -10
  35. package/dist/client/liveTurnLatency.d.ts +41 -0
  36. package/dist/client/opsStatus.d.ts +19 -0
  37. package/dist/client/opsStatusWidget.d.ts +40 -0
  38. package/dist/client/providerCapabilities.d.ts +19 -0
  39. package/dist/client/providerCapabilitiesWidget.d.ts +32 -0
  40. package/dist/client/providerSimulationControls.d.ts +33 -0
  41. package/dist/client/providerSimulationControlsWidget.d.ts +20 -0
  42. package/dist/client/providerStatus.d.ts +19 -0
  43. package/dist/client/providerStatusWidget.d.ts +32 -0
  44. package/dist/client/routingStatus.d.ts +19 -0
  45. package/dist/client/routingStatusWidget.d.ts +28 -0
  46. package/dist/client/traceTimeline.d.ts +19 -0
  47. package/dist/client/traceTimelineWidget.d.ts +32 -0
  48. package/dist/client/turnLatency.d.ts +22 -0
  49. package/dist/client/turnLatencyWidget.d.ts +33 -0
  50. package/dist/client/turnQuality.d.ts +19 -0
  51. package/dist/client/turnQualityWidget.d.ts +32 -0
  52. package/dist/client/workflowStatus.d.ts +19 -0
  53. package/dist/dataControl.d.ts +47 -0
  54. package/dist/demoReadyRoutes.d.ts +98 -0
  55. package/dist/diagnosticsRoutes.d.ts +44 -0
  56. package/dist/evalRoutes.d.ts +213 -0
  57. package/dist/fileStore.d.ts +11 -2
  58. package/dist/handoff.d.ts +54 -0
  59. package/dist/handoffHealth.d.ts +94 -0
  60. package/dist/index.d.ts +104 -9
  61. package/dist/index.js +17439 -4717
  62. package/dist/liveLatency.d.ts +78 -0
  63. package/dist/modelAdapters.d.ts +23 -2
  64. package/dist/openaiRealtime.d.ts +27 -0
  65. package/dist/openaiTTS.d.ts +18 -0
  66. package/dist/opsConsoleRoutes.d.ts +77 -0
  67. package/dist/opsStatus.d.ts +68 -0
  68. package/dist/opsStatusRoutes.d.ts +33 -0
  69. package/dist/opsWebhook.d.ts +126 -0
  70. package/dist/outcomeContract.d.ts +112 -0
  71. package/dist/phoneAgent.d.ts +62 -0
  72. package/dist/phoneAgentProductionSmoke.d.ts +115 -0
  73. package/dist/postgresStore.d.ts +13 -2
  74. package/dist/productionReadiness.d.ts +267 -0
  75. package/dist/providerAdapters.d.ts +48 -0
  76. package/dist/providerCapabilities.d.ts +92 -0
  77. package/dist/providerHealth.d.ts +79 -0
  78. package/dist/providerRoutingContract.d.ts +38 -0
  79. package/dist/qualityRoutes.d.ts +76 -0
  80. package/dist/queue.d.ts +61 -0
  81. package/dist/react/VoiceOpsStatus.d.ts +6 -0
  82. package/dist/react/VoiceProviderCapabilities.d.ts +6 -0
  83. package/dist/react/VoiceProviderSimulationControls.d.ts +5 -0
  84. package/dist/react/VoiceProviderStatus.d.ts +6 -0
  85. package/dist/react/VoiceRoutingStatus.d.ts +6 -0
  86. package/dist/react/VoiceTraceTimeline.d.ts +6 -0
  87. package/dist/react/VoiceTurnLatency.d.ts +6 -0
  88. package/dist/react/VoiceTurnQuality.d.ts +6 -0
  89. package/dist/react/index.d.ts +18 -0
  90. package/dist/react/index.js +2750 -14
  91. package/dist/react/useVoiceCampaignDialerProof.d.ts +10 -0
  92. package/dist/react/useVoiceController.d.ts +3 -0
  93. package/dist/react/useVoiceOpsStatus.d.ts +8 -0
  94. package/dist/react/useVoiceProviderCapabilities.d.ts +8 -0
  95. package/dist/react/useVoiceProviderSimulationControls.d.ts +10 -0
  96. package/dist/react/useVoiceProviderStatus.d.ts +8 -0
  97. package/dist/react/useVoiceRoutingStatus.d.ts +8 -0
  98. package/dist/react/useVoiceStream.d.ts +3 -0
  99. package/dist/react/useVoiceTraceTimeline.d.ts +8 -0
  100. package/dist/react/useVoiceTurnLatency.d.ts +9 -0
  101. package/dist/react/useVoiceTurnQuality.d.ts +8 -0
  102. package/dist/react/useVoiceWorkflowStatus.d.ts +8 -0
  103. package/dist/reconnectContract.d.ts +87 -0
  104. package/dist/resilienceRoutes.d.ts +142 -0
  105. package/dist/sessionReplay.d.ts +185 -0
  106. package/dist/simulationSuite.d.ts +120 -0
  107. package/dist/sqliteStore.d.ts +13 -2
  108. package/dist/svelte/createVoiceCampaignDialerProof.d.ts +9 -0
  109. package/dist/svelte/createVoiceOpsStatus.d.ts +9 -0
  110. package/dist/svelte/createVoiceProviderCapabilities.d.ts +10 -0
  111. package/dist/svelte/createVoiceProviderSimulationControls.d.ts +11 -0
  112. package/dist/svelte/createVoiceProviderStatus.d.ts +10 -0
  113. package/dist/svelte/createVoiceRoutingStatus.d.ts +10 -0
  114. package/dist/svelte/createVoiceTraceTimeline.d.ts +10 -0
  115. package/dist/svelte/createVoiceTurnLatency.d.ts +11 -0
  116. package/dist/svelte/createVoiceTurnQuality.d.ts +10 -0
  117. package/dist/svelte/createVoiceWorkflowStatus.d.ts +8 -0
  118. package/dist/svelte/index.d.ts +10 -0
  119. package/dist/svelte/index.js +2176 -202
  120. package/dist/telephony/contract.d.ts +61 -0
  121. package/dist/telephony/matrix.d.ts +97 -0
  122. package/dist/telephony/plivo.d.ts +254 -0
  123. package/dist/telephony/telnyx.d.ts +247 -0
  124. package/dist/telephony/twilio.d.ts +135 -2
  125. package/dist/telephonyOutcome.d.ts +201 -0
  126. package/dist/testing/index.d.ts +2 -0
  127. package/dist/testing/index.js +2973 -156
  128. package/dist/testing/ioProviderSimulator.d.ts +41 -0
  129. package/dist/testing/providerSimulator.d.ts +44 -0
  130. package/dist/toolContract.d.ts +130 -0
  131. package/dist/toolRuntime.d.ts +50 -0
  132. package/dist/trace.d.ts +1 -1
  133. package/dist/traceDeliveryRoutes.d.ts +86 -0
  134. package/dist/traceTimeline.d.ts +93 -0
  135. package/dist/turnLatency.d.ts +95 -0
  136. package/dist/turnQuality.d.ts +94 -0
  137. package/dist/types.d.ts +170 -4
  138. package/dist/vue/VoiceOpsStatus.d.ts +30 -0
  139. package/dist/vue/VoiceProviderCapabilities.d.ts +51 -0
  140. package/dist/vue/VoiceProviderSimulationControls.d.ts +88 -0
  141. package/dist/vue/VoiceProviderStatus.d.ts +51 -0
  142. package/dist/vue/VoiceRoutingStatus.d.ts +51 -0
  143. package/dist/vue/VoiceTurnLatency.d.ts +69 -0
  144. package/dist/vue/VoiceTurnQuality.d.ts +51 -0
  145. package/dist/vue/index.d.ts +17 -0
  146. package/dist/vue/index.js +2660 -31
  147. package/dist/vue/useVoiceCampaignDialerProof.d.ts +11 -0
  148. package/dist/vue/useVoiceController.d.ts +2 -1
  149. package/dist/vue/useVoiceOpsStatus.d.ts +9 -0
  150. package/dist/vue/useVoiceProviderCapabilities.d.ts +9 -0
  151. package/dist/vue/useVoiceProviderSimulationControls.d.ts +24 -0
  152. package/dist/vue/useVoiceProviderStatus.d.ts +9 -0
  153. package/dist/vue/useVoiceRoutingStatus.d.ts +8 -0
  154. package/dist/vue/useVoiceStream.d.ts +4 -1
  155. package/dist/vue/useVoiceTraceTimeline.d.ts +9 -0
  156. package/dist/vue/useVoiceTurnLatency.d.ts +10 -0
  157. package/dist/vue/useVoiceTurnQuality.d.ts +9 -0
  158. package/dist/vue/useVoiceWorkflowStatus.d.ts +9 -0
  159. package/dist/workflowContract.d.ts +91 -0
  160. package/package.json +1 -1
@@ -69,9 +69,298 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
71
 
72
- // src/angular/voice-stream.service.ts
72
+ // src/angular/voice-ops-status.service.ts
73
73
  import { computed, Injectable, signal } from "@angular/core";
74
74
 
75
+ // src/client/opsStatus.ts
76
+ var fetchVoiceOpsStatus = async (path = "/api/voice/ops-status", options = {}) => {
77
+ const fetchImpl = options.fetch ?? globalThis.fetch;
78
+ const response = await fetchImpl(path);
79
+ if (!response.ok) {
80
+ throw new Error(`Voice ops status failed: HTTP ${response.status}`);
81
+ }
82
+ return await response.json();
83
+ };
84
+ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) => {
85
+ const listeners = new Set;
86
+ let closed = false;
87
+ let timer;
88
+ let snapshot = {
89
+ error: null,
90
+ isLoading: false
91
+ };
92
+ const emit = () => {
93
+ for (const listener of listeners) {
94
+ listener();
95
+ }
96
+ };
97
+ const refresh = async () => {
98
+ if (closed) {
99
+ return snapshot.report;
100
+ }
101
+ snapshot = {
102
+ ...snapshot,
103
+ error: null,
104
+ isLoading: true
105
+ };
106
+ emit();
107
+ try {
108
+ const report = await fetchVoiceOpsStatus(path, options);
109
+ snapshot = {
110
+ error: null,
111
+ isLoading: false,
112
+ report,
113
+ updatedAt: Date.now()
114
+ };
115
+ emit();
116
+ return report;
117
+ } catch (error) {
118
+ snapshot = {
119
+ ...snapshot,
120
+ error: error instanceof Error ? error.message : String(error),
121
+ isLoading: false
122
+ };
123
+ emit();
124
+ throw error;
125
+ }
126
+ };
127
+ const close = () => {
128
+ closed = true;
129
+ if (timer) {
130
+ clearInterval(timer);
131
+ timer = undefined;
132
+ }
133
+ listeners.clear();
134
+ };
135
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
136
+ timer = setInterval(() => {
137
+ refresh().catch(() => {});
138
+ }, options.intervalMs);
139
+ }
140
+ return {
141
+ close,
142
+ getServerSnapshot: () => snapshot,
143
+ getSnapshot: () => snapshot,
144
+ refresh,
145
+ subscribe: (listener) => {
146
+ listeners.add(listener);
147
+ return () => {
148
+ listeners.delete(listener);
149
+ };
150
+ }
151
+ };
152
+ };
153
+
154
+ // src/angular/voice-ops-status.service.ts
155
+ var _dec = [
156
+ Injectable({ providedIn: "root" })
157
+ ];
158
+ var _init = __decoratorStart(undefined);
159
+
160
+ class VoiceOpsStatusService {
161
+ connect(path = "/api/voice/ops-status", options = {}) {
162
+ const store = createVoiceOpsStatusStore(path, options);
163
+ const errorSignal = signal(null);
164
+ const isLoadingSignal = signal(false);
165
+ const reportSignal = signal(undefined);
166
+ const updatedAtSignal = signal(undefined);
167
+ const sync = () => {
168
+ const snapshot = store.getSnapshot();
169
+ errorSignal.set(snapshot.error);
170
+ isLoadingSignal.set(snapshot.isLoading);
171
+ reportSignal.set(snapshot.report);
172
+ updatedAtSignal.set(snapshot.updatedAt);
173
+ };
174
+ const unsubscribe = store.subscribe(sync);
175
+ sync();
176
+ if (typeof window !== "undefined") {
177
+ store.refresh().catch(() => {});
178
+ }
179
+ return {
180
+ close: () => {
181
+ unsubscribe();
182
+ store.close();
183
+ },
184
+ error: computed(() => errorSignal()),
185
+ isLoading: computed(() => isLoadingSignal()),
186
+ refresh: store.refresh,
187
+ report: computed(() => reportSignal()),
188
+ updatedAt: computed(() => updatedAtSignal())
189
+ };
190
+ }
191
+ }
192
+ VoiceOpsStatusService = __decorateElement(_init, 0, "VoiceOpsStatusService", _dec, VoiceOpsStatusService);
193
+ __runInitializers(_init, 1, VoiceOpsStatusService);
194
+ __decoratorMetadata(_init, VoiceOpsStatusService);
195
+ let _VoiceOpsStatusService = VoiceOpsStatusService;
196
+ // src/angular/voice-campaign-dialer-proof.service.ts
197
+ import { computed as computed2, Injectable as Injectable2, signal as signal2 } from "@angular/core";
198
+
199
+ // src/client/campaignDialerProof.ts
200
+ var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
201
+ const fetchImpl = options.fetch ?? globalThis.fetch;
202
+ const response = await fetchImpl(path);
203
+ if (!response.ok) {
204
+ throw new Error(`Voice campaign dialer proof status failed: HTTP ${response.status}`);
205
+ }
206
+ return await response.json();
207
+ };
208
+ var runVoiceCampaignDialerProofAction = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
209
+ const fetchImpl = options.fetch ?? globalThis.fetch;
210
+ const response = await fetchImpl(path, { method: "POST" });
211
+ if (!response.ok) {
212
+ throw new Error(`Voice campaign dialer proof failed: HTTP ${response.status}`);
213
+ }
214
+ return await response.json();
215
+ };
216
+ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
217
+ const listeners = new Set;
218
+ let closed = false;
219
+ let timer;
220
+ let snapshot = {
221
+ error: null,
222
+ isLoading: false
223
+ };
224
+ const emit = () => {
225
+ for (const listener of listeners) {
226
+ listener();
227
+ }
228
+ };
229
+ const refresh = async () => {
230
+ if (closed) {
231
+ return snapshot.status;
232
+ }
233
+ snapshot = { ...snapshot, error: null, isLoading: true };
234
+ emit();
235
+ try {
236
+ const status = await fetchVoiceCampaignDialerProofStatus(path, options);
237
+ snapshot = {
238
+ ...snapshot,
239
+ error: null,
240
+ isLoading: false,
241
+ status,
242
+ updatedAt: Date.now()
243
+ };
244
+ emit();
245
+ return status;
246
+ } catch (error) {
247
+ snapshot = {
248
+ ...snapshot,
249
+ error: error instanceof Error ? error.message : String(error),
250
+ isLoading: false
251
+ };
252
+ emit();
253
+ throw error;
254
+ }
255
+ };
256
+ const runProof = async () => {
257
+ const runPath = options.runPath ?? snapshot.status?.runPath ?? path;
258
+ snapshot = { ...snapshot, error: null, isLoading: true };
259
+ emit();
260
+ try {
261
+ const report = await runVoiceCampaignDialerProofAction(runPath, options);
262
+ snapshot = {
263
+ ...snapshot,
264
+ error: null,
265
+ isLoading: false,
266
+ report,
267
+ status: {
268
+ generatedAt: Date.now(),
269
+ mode: report.mode,
270
+ ok: report.ok,
271
+ providers: report.providers.map((provider) => provider.provider),
272
+ runPath,
273
+ safe: true
274
+ },
275
+ updatedAt: Date.now()
276
+ };
277
+ emit();
278
+ return report;
279
+ } catch (error) {
280
+ snapshot = {
281
+ ...snapshot,
282
+ error: error instanceof Error ? error.message : String(error),
283
+ isLoading: false
284
+ };
285
+ emit();
286
+ throw error;
287
+ }
288
+ };
289
+ const close = () => {
290
+ closed = true;
291
+ if (timer) {
292
+ clearInterval(timer);
293
+ timer = undefined;
294
+ }
295
+ listeners.clear();
296
+ };
297
+ if (options.intervalMs && options.intervalMs > 0) {
298
+ timer = setInterval(() => {
299
+ refresh().catch(() => {});
300
+ }, options.intervalMs);
301
+ }
302
+ return {
303
+ close,
304
+ getServerSnapshot: () => snapshot,
305
+ getSnapshot: () => snapshot,
306
+ refresh,
307
+ runProof,
308
+ subscribe: (listener) => {
309
+ listeners.add(listener);
310
+ return () => {
311
+ listeners.delete(listener);
312
+ };
313
+ }
314
+ };
315
+ };
316
+
317
+ // src/angular/voice-campaign-dialer-proof.service.ts
318
+ var _dec = [
319
+ Injectable2({ providedIn: "root" })
320
+ ];
321
+ var _init = __decoratorStart(undefined);
322
+
323
+ class VoiceCampaignDialerProofService {
324
+ connect(path = "/api/voice/campaigns/dialer-proof", options = {}) {
325
+ const store = createVoiceCampaignDialerProofStore(path, options);
326
+ const errorSignal = signal2(null);
327
+ const isLoadingSignal = signal2(false);
328
+ const reportSignal = signal2(undefined);
329
+ const statusSignal = signal2(undefined);
330
+ const updatedAtSignal = signal2(undefined);
331
+ const sync = () => {
332
+ const snapshot = store.getSnapshot();
333
+ errorSignal.set(snapshot.error);
334
+ isLoadingSignal.set(snapshot.isLoading);
335
+ reportSignal.set(snapshot.report);
336
+ statusSignal.set(snapshot.status);
337
+ updatedAtSignal.set(snapshot.updatedAt);
338
+ };
339
+ const unsubscribe = store.subscribe(sync);
340
+ sync();
341
+ store.refresh().catch(() => {});
342
+ return {
343
+ close: () => {
344
+ unsubscribe();
345
+ store.close();
346
+ },
347
+ error: computed2(() => errorSignal()),
348
+ isLoading: computed2(() => isLoadingSignal()),
349
+ refresh: store.refresh,
350
+ report: computed2(() => reportSignal()),
351
+ runProof: store.runProof,
352
+ status: computed2(() => statusSignal()),
353
+ updatedAt: computed2(() => updatedAtSignal())
354
+ };
355
+ }
356
+ }
357
+ VoiceCampaignDialerProofService = __decorateElement(_init, 0, "VoiceCampaignDialerProofService", _dec, VoiceCampaignDialerProofService);
358
+ __runInitializers(_init, 1, VoiceCampaignDialerProofService);
359
+ __decoratorMetadata(_init, VoiceCampaignDialerProofService);
360
+ let _VoiceCampaignDialerProofService = VoiceCampaignDialerProofService;
361
+ // src/angular/voice-stream.service.ts
362
+ import { computed as computed3, Injectable as Injectable3, signal as signal3 } from "@angular/core";
363
+
75
364
  // src/client/actions.ts
76
365
  var normalizeErrorMessage = (value) => {
77
366
  if (typeof value === "string" && value.trim()) {
@@ -120,6 +409,17 @@ var serverMessageToAction = (message) => {
120
409
  sessionId: message.sessionId,
121
410
  type: "complete"
122
411
  };
412
+ case "connection":
413
+ return {
414
+ reconnect: message.reconnect,
415
+ type: "connection"
416
+ };
417
+ case "call_lifecycle":
418
+ return {
419
+ event: message.event,
420
+ sessionId: message.sessionId,
421
+ type: "call_lifecycle"
422
+ };
123
423
  case "error":
124
424
  return {
125
425
  message: normalizeErrorMessage(message.message),
@@ -135,6 +435,17 @@ var serverMessageToAction = (message) => {
135
435
  transcript: message.transcript,
136
436
  type: "partial"
137
437
  };
438
+ case "replay":
439
+ return {
440
+ assistantTexts: message.assistantTexts,
441
+ call: message.call,
442
+ partial: message.partial,
443
+ scenarioId: message.scenarioId,
444
+ sessionId: message.sessionId,
445
+ status: message.status,
446
+ turns: message.turns,
447
+ type: "replay"
448
+ };
138
449
  case "session":
139
450
  return {
140
451
  sessionId: message.sessionId,
@@ -163,7 +474,7 @@ var DEFAULT_SCENARIO_QUERY_PARAM = "scenarioId";
163
474
  var noop = () => {};
164
475
  var noopUnsubscribe = () => noop;
165
476
  var NOOP_CONNECTION = {
166
- start: () => {},
477
+ callControl: noop,
167
478
  close: noop,
168
479
  endTurn: noop,
169
480
  getReadyState: () => WS_CLOSED,
@@ -171,6 +482,7 @@ var NOOP_CONNECTION = {
171
482
  getSessionId: () => "",
172
483
  send: noop,
173
484
  sendAudio: noop,
485
+ start: () => {},
174
486
  subscribe: noopUnsubscribe
175
487
  };
176
488
  var createSessionId = () => crypto.randomUUID();
@@ -192,11 +504,14 @@ var isVoiceServerMessage = (value) => {
192
504
  switch (value.type) {
193
505
  case "audio":
194
506
  case "assistant":
507
+ case "call_lifecycle":
195
508
  case "complete":
509
+ case "connection":
196
510
  case "error":
197
511
  case "final":
198
512
  case "partial":
199
513
  case "pong":
514
+ case "replay":
200
515
  case "session":
201
516
  case "turn":
202
517
  return true;
@@ -233,6 +548,9 @@ var createVoiceConnection = (path, options = {}) => {
233
548
  sessionId: options.sessionId ?? createSessionId(),
234
549
  ws: null
235
550
  };
551
+ const emitConnection = (reconnect) => {
552
+ listeners.forEach((listener) => listener(reconnect));
553
+ };
236
554
  const clearTimers = () => {
237
555
  if (state.pingInterval) {
238
556
  clearInterval(state.pingInterval);
@@ -255,9 +573,28 @@ var createVoiceConnection = (path, options = {}) => {
255
573
  }
256
574
  };
257
575
  const scheduleReconnect = () => {
576
+ const nextAttemptAt = Date.now() + RECONNECT_DELAY_MS;
258
577
  state.reconnectAttempts += 1;
578
+ emitConnection({
579
+ reconnect: {
580
+ attempts: state.reconnectAttempts,
581
+ lastDisconnectAt: Date.now(),
582
+ maxAttempts: maxReconnectAttempts,
583
+ nextAttemptAt,
584
+ status: "reconnecting"
585
+ },
586
+ type: "connection"
587
+ });
259
588
  state.reconnectTimeout = setTimeout(() => {
260
589
  if (state.reconnectAttempts > maxReconnectAttempts) {
590
+ emitConnection({
591
+ reconnect: {
592
+ attempts: state.reconnectAttempts,
593
+ maxAttempts: maxReconnectAttempts,
594
+ status: "exhausted"
595
+ },
596
+ type: "connection"
597
+ });
261
598
  return;
262
599
  }
263
600
  connect();
@@ -267,9 +604,21 @@ var createVoiceConnection = (path, options = {}) => {
267
604
  const ws = new WebSocket(buildWsUrl(path, state.sessionId, state.scenarioId));
268
605
  ws.binaryType = "arraybuffer";
269
606
  ws.onopen = () => {
607
+ const wasReconnecting = state.reconnectAttempts > 0;
270
608
  state.isConnected = true;
271
- state.reconnectAttempts = 0;
272
609
  flushPendingMessages();
610
+ if (wasReconnecting) {
611
+ emitConnection({
612
+ reconnect: {
613
+ attempts: state.reconnectAttempts,
614
+ lastResumedAt: Date.now(),
615
+ maxAttempts: maxReconnectAttempts,
616
+ status: "resumed"
617
+ },
618
+ type: "connection"
619
+ });
620
+ state.reconnectAttempts = 0;
621
+ }
273
622
  listeners.forEach((listener) => listener({
274
623
  scenarioId: state.scenarioId ?? undefined,
275
624
  sessionId: state.sessionId,
@@ -299,6 +648,16 @@ var createVoiceConnection = (path, options = {}) => {
299
648
  const reconnectable = shouldReconnect && event.code !== WS_NORMAL_CLOSURE && state.reconnectAttempts < maxReconnectAttempts;
300
649
  if (reconnectable) {
301
650
  scheduleReconnect();
651
+ } else if (shouldReconnect && event.code !== WS_NORMAL_CLOSURE) {
652
+ emitConnection({
653
+ reconnect: {
654
+ attempts: state.reconnectAttempts,
655
+ lastDisconnectAt: Date.now(),
656
+ maxAttempts: maxReconnectAttempts,
657
+ status: "exhausted"
658
+ },
659
+ type: "connection"
660
+ });
302
661
  }
303
662
  };
304
663
  state.ws = ws;
@@ -332,6 +691,12 @@ var createVoiceConnection = (path, options = {}) => {
332
691
  const endTurn = () => {
333
692
  send({ type: "end_turn" });
334
693
  };
694
+ const callControl = (message) => {
695
+ send({
696
+ ...message,
697
+ type: "call_control"
698
+ });
699
+ };
335
700
  const close = () => {
336
701
  clearTimers();
337
702
  if (state.ws) {
@@ -349,7 +714,7 @@ var createVoiceConnection = (path, options = {}) => {
349
714
  };
350
715
  connect();
351
716
  return {
352
- start,
717
+ callControl,
353
718
  close,
354
719
  endTurn,
355
720
  getReadyState: () => state.ws?.readyState ?? WS_CLOSED,
@@ -357,18 +722,26 @@ var createVoiceConnection = (path, options = {}) => {
357
722
  getSessionId: () => state.sessionId,
358
723
  send,
359
724
  sendAudio,
725
+ start,
360
726
  subscribe
361
727
  };
362
728
  };
363
729
 
364
730
  // src/client/store.ts
731
+ var createInitialReconnectState = () => ({
732
+ attempts: 0,
733
+ maxAttempts: 0,
734
+ status: "idle"
735
+ });
365
736
  var createInitialState = () => ({
366
737
  assistantAudio: [],
367
738
  assistantTexts: [],
739
+ call: null,
368
740
  error: null,
369
741
  isConnected: false,
370
742
  scenarioId: null,
371
743
  partial: "",
744
+ reconnect: createInitialReconnectState(),
372
745
  sessionId: null,
373
746
  status: "idle",
374
747
  turns: []
@@ -408,10 +781,36 @@ var createVoiceStreamStore = () => {
408
781
  status: "completed"
409
782
  };
410
783
  break;
784
+ case "call_lifecycle":
785
+ state = {
786
+ ...state,
787
+ call: {
788
+ ...state.call,
789
+ disposition: action.event.type === "end" ? action.event.disposition : state.call?.disposition,
790
+ endedAt: action.event.type === "end" ? action.event.at : state.call?.endedAt,
791
+ events: [...state.call?.events ?? [], action.event],
792
+ lastEventAt: action.event.at,
793
+ startedAt: state.call?.startedAt ?? action.event.at
794
+ },
795
+ sessionId: action.sessionId
796
+ };
797
+ break;
411
798
  case "connected":
412
799
  state = {
413
800
  ...state,
414
- isConnected: true
801
+ isConnected: true,
802
+ reconnect: state.reconnect.status === "reconnecting" ? {
803
+ ...state.reconnect,
804
+ lastResumedAt: Date.now(),
805
+ nextAttemptAt: undefined,
806
+ status: "resumed"
807
+ } : state.reconnect
808
+ };
809
+ break;
810
+ case "connection":
811
+ state = {
812
+ ...state,
813
+ reconnect: action.reconnect
415
814
  };
416
815
  break;
417
816
  case "disconnected":
@@ -439,6 +838,26 @@ var createVoiceStreamStore = () => {
439
838
  partial: action.transcript.text
440
839
  };
441
840
  break;
841
+ case "replay":
842
+ state = {
843
+ ...state,
844
+ assistantTexts: [...action.assistantTexts],
845
+ call: action.call ?? null,
846
+ error: null,
847
+ isConnected: action.status === "active",
848
+ partial: action.partial,
849
+ reconnect: state.reconnect.status === "reconnecting" ? {
850
+ ...state.reconnect,
851
+ lastResumedAt: Date.now(),
852
+ nextAttemptAt: undefined,
853
+ status: "resumed"
854
+ } : state.reconnect,
855
+ scenarioId: action.scenarioId ?? state.scenarioId,
856
+ sessionId: action.sessionId,
857
+ status: action.status,
858
+ turns: [...action.turns]
859
+ };
860
+ break;
442
861
  case "session":
443
862
  state = {
444
863
  ...state,
@@ -486,14 +905,41 @@ var createVoiceStream = (path, options = {}) => {
486
905
  const notify = () => {
487
906
  subscribers.forEach((subscriber) => subscriber());
488
907
  };
908
+ const reportReconnect = () => {
909
+ if (!options.reconnectReportPath || typeof fetch === "undefined") {
910
+ return;
911
+ }
912
+ const snapshot = store.getSnapshot();
913
+ const body = JSON.stringify({
914
+ at: Date.now(),
915
+ reconnect: snapshot.reconnect,
916
+ scenarioId: snapshot.scenarioId,
917
+ sessionId: connection.getSessionId(),
918
+ turnIds: snapshot.turns.map((turn) => turn.id)
919
+ });
920
+ fetch(options.reconnectReportPath, {
921
+ body,
922
+ headers: {
923
+ "Content-Type": "application/json"
924
+ },
925
+ keepalive: true,
926
+ method: "POST"
927
+ }).catch(() => {});
928
+ };
489
929
  const unsubscribeConnection = connection.subscribe((message) => {
490
930
  const action = serverMessageToAction(message);
491
931
  if (action) {
492
932
  store.dispatch(action);
933
+ if (message.type === "connection") {
934
+ reportReconnect();
935
+ }
493
936
  notify();
494
937
  }
495
938
  });
496
939
  return {
940
+ callControl(message) {
941
+ connection.callControl(message);
942
+ },
497
943
  close() {
498
944
  unsubscribeConnection();
499
945
  connection.close();
@@ -522,6 +968,9 @@ var createVoiceStream = (path, options = {}) => {
522
968
  get partial() {
523
969
  return store.getSnapshot().partial;
524
970
  },
971
+ get reconnect() {
972
+ return store.getSnapshot().reconnect;
973
+ },
525
974
  get sessionId() {
526
975
  return connection.getSessionId();
527
976
  },
@@ -537,6 +986,9 @@ var createVoiceStream = (path, options = {}) => {
537
986
  get assistantAudio() {
538
987
  return store.getSnapshot().assistantAudio;
539
988
  },
989
+ get call() {
990
+ return store.getSnapshot().call;
991
+ },
540
992
  sendAudio(audio) {
541
993
  connection.sendAudio(audio);
542
994
  },
@@ -551,27 +1003,31 @@ var createVoiceStream = (path, options = {}) => {
551
1003
 
552
1004
  // src/angular/voice-stream.service.ts
553
1005
  var _dec = [
554
- Injectable({ providedIn: "root" })
1006
+ Injectable3({ providedIn: "root" })
555
1007
  ];
556
1008
  var _init = __decoratorStart(undefined);
557
1009
 
558
1010
  class VoiceStreamService {
559
1011
  connect(path, options = {}) {
560
1012
  const stream = createVoiceStream(path, options);
561
- const assistantAudioSignal = signal([]);
562
- const assistantTextsSignal = signal([]);
563
- const errorSignal = signal(null);
564
- const isConnectedSignal = signal(false);
565
- const partialSignal = signal("");
566
- const sessionIdSignal = signal(stream.sessionId);
567
- const statusSignal = signal(stream.status);
568
- const turnsSignal = signal([]);
1013
+ const assistantAudioSignal = signal3([]);
1014
+ const assistantTextsSignal = signal3([]);
1015
+ const callSignal = signal3(null);
1016
+ const errorSignal = signal3(null);
1017
+ const isConnectedSignal = signal3(false);
1018
+ const partialSignal = signal3("");
1019
+ const reconnectSignal = signal3(stream.reconnect);
1020
+ const sessionIdSignal = signal3(stream.sessionId);
1021
+ const statusSignal = signal3(stream.status);
1022
+ const turnsSignal = signal3([]);
569
1023
  const sync = () => {
570
1024
  assistantAudioSignal.set([...stream.assistantAudio]);
571
1025
  assistantTextsSignal.set([...stream.assistantTexts]);
1026
+ callSignal.set(stream.call);
572
1027
  errorSignal.set(stream.error);
573
1028
  isConnectedSignal.set(stream.isConnected);
574
1029
  partialSignal.set(stream.partial);
1030
+ reconnectSignal.set(stream.reconnect);
575
1031
  sessionIdSignal.set(stream.sessionId);
576
1032
  statusSignal.set(stream.status);
577
1033
  turnsSignal.set([...stream.turns]);
@@ -579,20 +1035,23 @@ class VoiceStreamService {
579
1035
  const unsubscribe = stream.subscribe(sync);
580
1036
  sync();
581
1037
  return {
582
- assistantAudio: computed(() => assistantAudioSignal()),
583
- assistantTexts: computed(() => assistantTextsSignal()),
1038
+ assistantAudio: computed3(() => assistantAudioSignal()),
1039
+ assistantTexts: computed3(() => assistantTextsSignal()),
1040
+ call: computed3(() => callSignal()),
1041
+ callControl: (message) => stream.callControl(message),
584
1042
  close: () => {
585
1043
  unsubscribe();
586
1044
  stream.close();
587
1045
  },
588
1046
  endTurn: () => stream.endTurn(),
589
- error: computed(() => errorSignal()),
590
- isConnected: computed(() => isConnectedSignal()),
591
- partial: computed(() => partialSignal()),
1047
+ error: computed3(() => errorSignal()),
1048
+ isConnected: computed3(() => isConnectedSignal()),
1049
+ partial: computed3(() => partialSignal()),
1050
+ reconnect: computed3(() => reconnectSignal()),
592
1051
  sendAudio: (audio) => stream.sendAudio(audio),
593
- sessionId: computed(() => sessionIdSignal()),
594
- status: computed(() => statusSignal()),
595
- turns: computed(() => turnsSignal())
1052
+ sessionId: computed3(() => sessionIdSignal()),
1053
+ status: computed3(() => statusSignal()),
1054
+ turns: computed3(() => turnsSignal())
596
1055
  };
597
1056
  }
598
1057
  }
@@ -601,7 +1060,7 @@ __runInitializers(_init, 1, VoiceStreamService);
601
1060
  __decoratorMetadata(_init, VoiceStreamService);
602
1061
  let _VoiceStreamService = VoiceStreamService;
603
1062
  // src/angular/voice-controller.service.ts
604
- import { computed as computed2, Injectable as Injectable2, signal as signal2 } from "@angular/core";
1063
+ import { computed as computed4, Injectable as Injectable4, signal as signal4 } from "@angular/core";
605
1064
 
606
1065
  // src/client/htmx.ts
607
1066
  var DEFAULT_EVENT_NAME = "voice-refresh";
@@ -1065,10 +1524,12 @@ var resolveVoiceRuntimePreset = (name = "default") => {
1065
1524
  var createInitialState2 = (stream) => ({
1066
1525
  assistantAudio: [...stream.assistantAudio],
1067
1526
  assistantTexts: [...stream.assistantTexts],
1527
+ call: stream.call,
1068
1528
  error: stream.error,
1069
1529
  isConnected: stream.isConnected,
1070
1530
  isRecording: false,
1071
1531
  partial: stream.partial,
1532
+ reconnect: stream.reconnect,
1072
1533
  recordingError: null,
1073
1534
  sessionId: stream.sessionId,
1074
1535
  scenarioId: stream.scenarioId,
@@ -1094,9 +1555,11 @@ var createVoiceController = (path, options = {}) => {
1094
1555
  ...state,
1095
1556
  assistantAudio: [...stream.assistantAudio],
1096
1557
  assistantTexts: [...stream.assistantTexts],
1558
+ call: stream.call,
1097
1559
  error: stream.error,
1098
1560
  isConnected: stream.isConnected,
1099
1561
  partial: stream.partial,
1562
+ reconnect: stream.reconnect,
1100
1563
  sessionId: stream.sessionId,
1101
1564
  scenarioId: stream.scenarioId,
1102
1565
  status: stream.status,
@@ -1121,7 +1584,13 @@ var createVoiceController = (path, options = {}) => {
1121
1584
  capture = createMicrophoneCapture({
1122
1585
  channelCount: options.capture?.channelCount ?? preset.capture.channelCount,
1123
1586
  onLevel: options.capture?.onLevel,
1124
- onAudio: (audio) => stream.sendAudio(audio),
1587
+ onAudio: (audio) => {
1588
+ if (options.capture?.onAudio) {
1589
+ options.capture.onAudio(audio, stream.sendAudio);
1590
+ return;
1591
+ }
1592
+ stream.sendAudio(audio);
1593
+ },
1125
1594
  sampleRateHz: options.capture?.sampleRateHz ?? preset.capture.sampleRateHz
1126
1595
  });
1127
1596
  return capture;
@@ -1171,6 +1640,7 @@ var createVoiceController = (path, options = {}) => {
1171
1640
  bindHTMX(bindingOptions) {
1172
1641
  return bindVoiceHTMX(stream, bindingOptions);
1173
1642
  },
1643
+ callControl: (message) => stream.callControl(message),
1174
1644
  close,
1175
1645
  endTurn: () => stream.endTurn(),
1176
1646
  get error() {
@@ -1190,6 +1660,9 @@ var createVoiceController = (path, options = {}) => {
1190
1660
  get recordingError() {
1191
1661
  return state.recordingError;
1192
1662
  },
1663
+ get reconnect() {
1664
+ return state.reconnect;
1665
+ },
1193
1666
  sendAudio: (audio) => stream.sendAudio(audio),
1194
1667
  get sessionId() {
1195
1668
  return state.sessionId;
@@ -1223,29 +1696,33 @@ var createVoiceController = (path, options = {}) => {
1223
1696
  },
1224
1697
  get assistantAudio() {
1225
1698
  return state.assistantAudio;
1699
+ },
1700
+ get call() {
1701
+ return state.call;
1226
1702
  }
1227
1703
  };
1228
1704
  };
1229
1705
 
1230
1706
  // src/angular/voice-controller.service.ts
1231
1707
  var _dec = [
1232
- Injectable2({ providedIn: "root" })
1708
+ Injectable4({ providedIn: "root" })
1233
1709
  ];
1234
1710
  var _init = __decoratorStart(undefined);
1235
1711
 
1236
1712
  class VoiceControllerService {
1237
1713
  connect(path, options = {}) {
1238
1714
  const controller = createVoiceController(path, options);
1239
- const assistantAudioSignal = signal2([]);
1240
- const assistantTextsSignal = signal2([]);
1241
- const errorSignal = signal2(null);
1242
- const isConnectedSignal = signal2(false);
1243
- const isRecordingSignal = signal2(false);
1244
- const partialSignal = signal2("");
1245
- const recordingErrorSignal = signal2(null);
1246
- const sessionIdSignal = signal2(controller.sessionId);
1247
- const statusSignal = signal2(controller.status);
1248
- const turnsSignal = signal2([]);
1715
+ const assistantAudioSignal = signal4([]);
1716
+ const assistantTextsSignal = signal4([]);
1717
+ const errorSignal = signal4(null);
1718
+ const isConnectedSignal = signal4(false);
1719
+ const isRecordingSignal = signal4(false);
1720
+ const partialSignal = signal4("");
1721
+ const reconnectSignal = signal4(controller.reconnect);
1722
+ const recordingErrorSignal = signal4(null);
1723
+ const sessionIdSignal = signal4(controller.sessionId);
1724
+ const statusSignal = signal4(controller.status);
1725
+ const turnsSignal = signal4([]);
1249
1726
  const sync = () => {
1250
1727
  assistantAudioSignal.set([...controller.assistantAudio]);
1251
1728
  assistantTextsSignal.set([...controller.assistantTexts]);
@@ -1253,6 +1730,7 @@ class VoiceControllerService {
1253
1730
  isConnectedSignal.set(controller.isConnected);
1254
1731
  isRecordingSignal.set(controller.isRecording);
1255
1732
  partialSignal.set(controller.partial);
1733
+ reconnectSignal.set(controller.reconnect);
1256
1734
  recordingErrorSignal.set(controller.recordingError);
1257
1735
  sessionIdSignal.set(controller.sessionId);
1258
1736
  statusSignal.set(controller.status);
@@ -1261,26 +1739,27 @@ class VoiceControllerService {
1261
1739
  const unsubscribe = controller.subscribe(sync);
1262
1740
  sync();
1263
1741
  return {
1264
- assistantAudio: computed2(() => assistantAudioSignal()),
1265
- assistantTexts: computed2(() => assistantTextsSignal()),
1742
+ assistantAudio: computed4(() => assistantAudioSignal()),
1743
+ assistantTexts: computed4(() => assistantTextsSignal()),
1266
1744
  bindHTMX: controller.bindHTMX,
1267
1745
  close: () => {
1268
1746
  unsubscribe();
1269
1747
  controller.close();
1270
1748
  },
1271
1749
  endTurn: () => controller.endTurn(),
1272
- error: computed2(() => errorSignal()),
1273
- isConnected: computed2(() => isConnectedSignal()),
1274
- isRecording: computed2(() => isRecordingSignal()),
1275
- partial: computed2(() => partialSignal()),
1276
- recordingError: computed2(() => recordingErrorSignal()),
1750
+ error: computed4(() => errorSignal()),
1751
+ isConnected: computed4(() => isConnectedSignal()),
1752
+ isRecording: computed4(() => isRecordingSignal()),
1753
+ partial: computed4(() => partialSignal()),
1754
+ reconnect: computed4(() => reconnectSignal()),
1755
+ recordingError: computed4(() => recordingErrorSignal()),
1277
1756
  sendAudio: (audio) => controller.sendAudio(audio),
1278
- sessionId: computed2(() => sessionIdSignal()),
1757
+ sessionId: computed4(() => sessionIdSignal()),
1279
1758
  startRecording: () => controller.startRecording(),
1280
- status: computed2(() => statusSignal()),
1759
+ status: computed4(() => statusSignal()),
1281
1760
  stopRecording: () => controller.stopRecording(),
1282
1761
  toggleRecording: () => controller.toggleRecording(),
1283
- turns: computed2(() => turnsSignal())
1762
+ turns: computed4(() => turnsSignal())
1284
1763
  };
1285
1764
  }
1286
1765
  }
@@ -1288,7 +1767,900 @@ VoiceControllerService = __decorateElement(_init, 0, "VoiceControllerService", _
1288
1767
  __runInitializers(_init, 1, VoiceControllerService);
1289
1768
  __decoratorMetadata(_init, VoiceControllerService);
1290
1769
  let _VoiceControllerService = VoiceControllerService;
1770
+ // src/angular/voice-provider-capabilities.service.ts
1771
+ import { computed as computed5, Injectable as Injectable5, signal as signal5 } from "@angular/core";
1772
+
1773
+ // src/client/providerCapabilities.ts
1774
+ var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
1775
+ const fetchImpl = options.fetch ?? globalThis.fetch;
1776
+ const response = await fetchImpl(path);
1777
+ if (!response.ok) {
1778
+ throw new Error(`Voice provider capabilities failed: HTTP ${response.status}`);
1779
+ }
1780
+ return await response.json();
1781
+ };
1782
+ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities", options = {}) => {
1783
+ const listeners = new Set;
1784
+ let closed = false;
1785
+ let timer;
1786
+ let snapshot = {
1787
+ error: null,
1788
+ isLoading: false
1789
+ };
1790
+ const emit = () => {
1791
+ for (const listener of listeners) {
1792
+ listener();
1793
+ }
1794
+ };
1795
+ const refresh = async () => {
1796
+ if (closed) {
1797
+ return snapshot.report;
1798
+ }
1799
+ snapshot = {
1800
+ ...snapshot,
1801
+ error: null,
1802
+ isLoading: true
1803
+ };
1804
+ emit();
1805
+ try {
1806
+ const report = await fetchVoiceProviderCapabilities(path, options);
1807
+ snapshot = {
1808
+ error: null,
1809
+ isLoading: false,
1810
+ report,
1811
+ updatedAt: Date.now()
1812
+ };
1813
+ emit();
1814
+ return report;
1815
+ } catch (error) {
1816
+ snapshot = {
1817
+ ...snapshot,
1818
+ error: error instanceof Error ? error.message : String(error),
1819
+ isLoading: false
1820
+ };
1821
+ emit();
1822
+ throw error;
1823
+ }
1824
+ };
1825
+ const close = () => {
1826
+ closed = true;
1827
+ if (timer) {
1828
+ clearInterval(timer);
1829
+ timer = undefined;
1830
+ }
1831
+ listeners.clear();
1832
+ };
1833
+ if (options.intervalMs && options.intervalMs > 0) {
1834
+ timer = setInterval(() => {
1835
+ refresh().catch(() => {});
1836
+ }, options.intervalMs);
1837
+ }
1838
+ return {
1839
+ close,
1840
+ getServerSnapshot: () => snapshot,
1841
+ getSnapshot: () => snapshot,
1842
+ refresh,
1843
+ subscribe: (listener) => {
1844
+ listeners.add(listener);
1845
+ return () => {
1846
+ listeners.delete(listener);
1847
+ };
1848
+ }
1849
+ };
1850
+ };
1851
+
1852
+ // src/angular/voice-provider-capabilities.service.ts
1853
+ var _dec = [
1854
+ Injectable5({ providedIn: "root" })
1855
+ ];
1856
+ var _init = __decoratorStart(undefined);
1857
+
1858
+ class VoiceProviderCapabilitiesService {
1859
+ connect(path = "/api/provider-capabilities", options = {}) {
1860
+ const store = createVoiceProviderCapabilitiesStore(path, options);
1861
+ const errorSignal = signal5(null);
1862
+ const isLoadingSignal = signal5(false);
1863
+ const reportSignal = signal5(undefined);
1864
+ const updatedAtSignal = signal5(undefined);
1865
+ const sync = () => {
1866
+ const snapshot = store.getSnapshot();
1867
+ errorSignal.set(snapshot.error);
1868
+ isLoadingSignal.set(snapshot.isLoading);
1869
+ reportSignal.set(snapshot.report);
1870
+ updatedAtSignal.set(snapshot.updatedAt);
1871
+ };
1872
+ const unsubscribe = store.subscribe(sync);
1873
+ sync();
1874
+ store.refresh().catch(() => {});
1875
+ return {
1876
+ close: () => {
1877
+ unsubscribe();
1878
+ store.close();
1879
+ },
1880
+ error: computed5(() => errorSignal()),
1881
+ isLoading: computed5(() => isLoadingSignal()),
1882
+ refresh: store.refresh,
1883
+ report: computed5(() => reportSignal()),
1884
+ updatedAt: computed5(() => updatedAtSignal())
1885
+ };
1886
+ }
1887
+ }
1888
+ VoiceProviderCapabilitiesService = __decorateElement(_init, 0, "VoiceProviderCapabilitiesService", _dec, VoiceProviderCapabilitiesService);
1889
+ __runInitializers(_init, 1, VoiceProviderCapabilitiesService);
1890
+ __decoratorMetadata(_init, VoiceProviderCapabilitiesService);
1891
+ let _VoiceProviderCapabilitiesService = VoiceProviderCapabilitiesService;
1892
+ // src/angular/voice-provider-status.service.ts
1893
+ import { computed as computed6, Injectable as Injectable6, signal as signal6 } from "@angular/core";
1894
+
1895
+ // src/client/providerStatus.ts
1896
+ var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
1897
+ const fetchImpl = options.fetch ?? globalThis.fetch;
1898
+ const response = await fetchImpl(path);
1899
+ if (!response.ok) {
1900
+ throw new Error(`Voice provider status failed: HTTP ${response.status}`);
1901
+ }
1902
+ return await response.json();
1903
+ };
1904
+ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {}) => {
1905
+ const listeners = new Set;
1906
+ let closed = false;
1907
+ let timer;
1908
+ let snapshot = {
1909
+ error: null,
1910
+ isLoading: false,
1911
+ providers: []
1912
+ };
1913
+ const emit = () => {
1914
+ for (const listener of listeners) {
1915
+ listener();
1916
+ }
1917
+ };
1918
+ const refresh = async () => {
1919
+ if (closed) {
1920
+ return snapshot.providers;
1921
+ }
1922
+ snapshot = {
1923
+ ...snapshot,
1924
+ error: null,
1925
+ isLoading: true
1926
+ };
1927
+ emit();
1928
+ try {
1929
+ const providers = await fetchVoiceProviderStatus(path, options);
1930
+ snapshot = {
1931
+ error: null,
1932
+ isLoading: false,
1933
+ providers,
1934
+ updatedAt: Date.now()
1935
+ };
1936
+ emit();
1937
+ return providers;
1938
+ } catch (error) {
1939
+ snapshot = {
1940
+ ...snapshot,
1941
+ error: error instanceof Error ? error.message : String(error),
1942
+ isLoading: false
1943
+ };
1944
+ emit();
1945
+ throw error;
1946
+ }
1947
+ };
1948
+ const close = () => {
1949
+ closed = true;
1950
+ if (timer) {
1951
+ clearInterval(timer);
1952
+ timer = undefined;
1953
+ }
1954
+ listeners.clear();
1955
+ };
1956
+ if (options.intervalMs && options.intervalMs > 0) {
1957
+ timer = setInterval(() => {
1958
+ refresh().catch(() => {});
1959
+ }, options.intervalMs);
1960
+ }
1961
+ return {
1962
+ close,
1963
+ getServerSnapshot: () => snapshot,
1964
+ getSnapshot: () => snapshot,
1965
+ refresh,
1966
+ subscribe: (listener) => {
1967
+ listeners.add(listener);
1968
+ return () => {
1969
+ listeners.delete(listener);
1970
+ };
1971
+ }
1972
+ };
1973
+ };
1974
+
1975
+ // src/angular/voice-provider-status.service.ts
1976
+ var _dec = [
1977
+ Injectable6({ providedIn: "root" })
1978
+ ];
1979
+ var _init = __decoratorStart(undefined);
1980
+
1981
+ class VoiceProviderStatusService {
1982
+ connect(path = "/api/provider-status", options = {}) {
1983
+ const store = createVoiceProviderStatusStore(path, options);
1984
+ const errorSignal = signal6(null);
1985
+ const isLoadingSignal = signal6(false);
1986
+ const providersSignal = signal6([]);
1987
+ const updatedAtSignal = signal6(undefined);
1988
+ const sync = () => {
1989
+ const snapshot = store.getSnapshot();
1990
+ errorSignal.set(snapshot.error);
1991
+ isLoadingSignal.set(snapshot.isLoading);
1992
+ providersSignal.set([...snapshot.providers]);
1993
+ updatedAtSignal.set(snapshot.updatedAt);
1994
+ };
1995
+ const unsubscribe = store.subscribe(sync);
1996
+ sync();
1997
+ store.refresh().catch(() => {});
1998
+ return {
1999
+ close: () => {
2000
+ unsubscribe();
2001
+ store.close();
2002
+ },
2003
+ error: computed6(() => errorSignal()),
2004
+ isLoading: computed6(() => isLoadingSignal()),
2005
+ providers: computed6(() => providersSignal()),
2006
+ refresh: store.refresh,
2007
+ updatedAt: computed6(() => updatedAtSignal())
2008
+ };
2009
+ }
2010
+ }
2011
+ VoiceProviderStatusService = __decorateElement(_init, 0, "VoiceProviderStatusService", _dec, VoiceProviderStatusService);
2012
+ __runInitializers(_init, 1, VoiceProviderStatusService);
2013
+ __decoratorMetadata(_init, VoiceProviderStatusService);
2014
+ let _VoiceProviderStatusService = VoiceProviderStatusService;
2015
+ // src/angular/voice-routing-status.service.ts
2016
+ import { Injectable as Injectable7, signal as signal7 } from "@angular/core";
2017
+
2018
+ // src/client/routingStatus.ts
2019
+ var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
2020
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2021
+ const response = await fetchImpl(path);
2022
+ if (!response.ok) {
2023
+ throw new Error(`Voice routing status failed: HTTP ${response.status}`);
2024
+ }
2025
+ return await response.json();
2026
+ };
2027
+ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {}) => {
2028
+ const listeners = new Set;
2029
+ let closed = false;
2030
+ let timer;
2031
+ let snapshot = {
2032
+ decision: null,
2033
+ error: null,
2034
+ isLoading: false
2035
+ };
2036
+ const emit = () => {
2037
+ for (const listener of listeners) {
2038
+ listener();
2039
+ }
2040
+ };
2041
+ const refresh = async () => {
2042
+ if (closed) {
2043
+ return snapshot.decision;
2044
+ }
2045
+ snapshot = {
2046
+ ...snapshot,
2047
+ error: null,
2048
+ isLoading: true
2049
+ };
2050
+ emit();
2051
+ try {
2052
+ const decision = await fetchVoiceRoutingStatus(path, options);
2053
+ snapshot = {
2054
+ decision,
2055
+ error: null,
2056
+ isLoading: false,
2057
+ updatedAt: Date.now()
2058
+ };
2059
+ emit();
2060
+ return decision;
2061
+ } catch (error) {
2062
+ snapshot = {
2063
+ ...snapshot,
2064
+ error: error instanceof Error ? error.message : String(error),
2065
+ isLoading: false
2066
+ };
2067
+ emit();
2068
+ throw error;
2069
+ }
2070
+ };
2071
+ const close = () => {
2072
+ closed = true;
2073
+ if (timer) {
2074
+ clearInterval(timer);
2075
+ timer = undefined;
2076
+ }
2077
+ listeners.clear();
2078
+ };
2079
+ if (options.intervalMs && options.intervalMs > 0) {
2080
+ timer = setInterval(() => {
2081
+ refresh().catch(() => {});
2082
+ }, options.intervalMs);
2083
+ }
2084
+ return {
2085
+ close,
2086
+ getServerSnapshot: () => snapshot,
2087
+ getSnapshot: () => snapshot,
2088
+ refresh,
2089
+ subscribe: (listener) => {
2090
+ listeners.add(listener);
2091
+ return () => {
2092
+ listeners.delete(listener);
2093
+ };
2094
+ }
2095
+ };
2096
+ };
2097
+
2098
+ // src/angular/voice-routing-status.service.ts
2099
+ var _dec = [
2100
+ Injectable7({ providedIn: "root" })
2101
+ ];
2102
+ var _init = __decoratorStart(undefined);
2103
+
2104
+ class VoiceRoutingStatusService {
2105
+ connect(path = "/api/routing/latest", options = {}) {
2106
+ const store = createVoiceRoutingStatusStore(path, options);
2107
+ const decisionSignal = signal7(null);
2108
+ const errorSignal = signal7(null);
2109
+ const isLoadingSignal = signal7(false);
2110
+ const updatedAtSignal = signal7(undefined);
2111
+ const sync = () => {
2112
+ const snapshot = store.getSnapshot();
2113
+ decisionSignal.set(snapshot.decision);
2114
+ errorSignal.set(snapshot.error);
2115
+ isLoadingSignal.set(snapshot.isLoading);
2116
+ updatedAtSignal.set(snapshot.updatedAt);
2117
+ };
2118
+ const unsubscribe = store.subscribe(sync);
2119
+ sync();
2120
+ store.refresh().catch(() => {});
2121
+ return {
2122
+ close: () => {
2123
+ unsubscribe();
2124
+ store.close();
2125
+ },
2126
+ decision: decisionSignal.asReadonly(),
2127
+ error: errorSignal.asReadonly(),
2128
+ isLoading: isLoadingSignal.asReadonly(),
2129
+ refresh: store.refresh,
2130
+ updatedAt: updatedAtSignal.asReadonly()
2131
+ };
2132
+ }
2133
+ }
2134
+ VoiceRoutingStatusService = __decorateElement(_init, 0, "VoiceRoutingStatusService", _dec, VoiceRoutingStatusService);
2135
+ __runInitializers(_init, 1, VoiceRoutingStatusService);
2136
+ __decoratorMetadata(_init, VoiceRoutingStatusService);
2137
+ let _VoiceRoutingStatusService = VoiceRoutingStatusService;
2138
+ // src/angular/voice-trace-timeline.service.ts
2139
+ import { computed as computed7, Injectable as Injectable8, signal as signal8 } from "@angular/core";
2140
+
2141
+ // src/client/traceTimeline.ts
2142
+ var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
2143
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2144
+ const response = await fetchImpl(path);
2145
+ if (!response.ok) {
2146
+ throw new Error(`Voice trace timeline failed: HTTP ${response.status}`);
2147
+ }
2148
+ return await response.json();
2149
+ };
2150
+ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) => {
2151
+ const listeners = new Set;
2152
+ let closed = false;
2153
+ let timer;
2154
+ let snapshot = {
2155
+ error: null,
2156
+ isLoading: false,
2157
+ report: null
2158
+ };
2159
+ const emit = () => {
2160
+ for (const listener of listeners) {
2161
+ listener();
2162
+ }
2163
+ };
2164
+ const refresh = async () => {
2165
+ if (closed) {
2166
+ return snapshot.report;
2167
+ }
2168
+ snapshot = {
2169
+ ...snapshot,
2170
+ error: null,
2171
+ isLoading: true
2172
+ };
2173
+ emit();
2174
+ try {
2175
+ const report = await fetchVoiceTraceTimeline(path, options);
2176
+ snapshot = {
2177
+ error: null,
2178
+ isLoading: false,
2179
+ report,
2180
+ updatedAt: Date.now()
2181
+ };
2182
+ emit();
2183
+ return report;
2184
+ } catch (error) {
2185
+ snapshot = {
2186
+ ...snapshot,
2187
+ error: error instanceof Error ? error.message : String(error),
2188
+ isLoading: false
2189
+ };
2190
+ emit();
2191
+ throw error;
2192
+ }
2193
+ };
2194
+ const close = () => {
2195
+ closed = true;
2196
+ if (timer) {
2197
+ clearInterval(timer);
2198
+ timer = undefined;
2199
+ }
2200
+ listeners.clear();
2201
+ };
2202
+ if (options.intervalMs && options.intervalMs > 0) {
2203
+ timer = setInterval(() => {
2204
+ refresh().catch(() => {});
2205
+ }, options.intervalMs);
2206
+ }
2207
+ return {
2208
+ close,
2209
+ getServerSnapshot: () => snapshot,
2210
+ getSnapshot: () => snapshot,
2211
+ refresh,
2212
+ subscribe: (listener) => {
2213
+ listeners.add(listener);
2214
+ return () => {
2215
+ listeners.delete(listener);
2216
+ };
2217
+ }
2218
+ };
2219
+ };
2220
+
2221
+ // src/angular/voice-trace-timeline.service.ts
2222
+ var _dec = [
2223
+ Injectable8({ providedIn: "root" })
2224
+ ];
2225
+ var _init = __decoratorStart(undefined);
2226
+
2227
+ class VoiceTraceTimelineService {
2228
+ connect(path = "/api/voice-traces", options = {}) {
2229
+ const store = createVoiceTraceTimelineStore(path, options);
2230
+ const errorSignal = signal8(null);
2231
+ const isLoadingSignal = signal8(false);
2232
+ const reportSignal = signal8(null);
2233
+ const updatedAtSignal = signal8(undefined);
2234
+ const sync = () => {
2235
+ const snapshot = store.getSnapshot();
2236
+ errorSignal.set(snapshot.error);
2237
+ isLoadingSignal.set(snapshot.isLoading);
2238
+ reportSignal.set(snapshot.report);
2239
+ updatedAtSignal.set(snapshot.updatedAt);
2240
+ };
2241
+ const unsubscribe = store.subscribe(sync);
2242
+ sync();
2243
+ store.refresh().catch(() => {});
2244
+ return {
2245
+ close: () => {
2246
+ unsubscribe();
2247
+ store.close();
2248
+ },
2249
+ error: computed7(() => errorSignal()),
2250
+ isLoading: computed7(() => isLoadingSignal()),
2251
+ refresh: store.refresh,
2252
+ report: computed7(() => reportSignal()),
2253
+ updatedAt: computed7(() => updatedAtSignal())
2254
+ };
2255
+ }
2256
+ }
2257
+ VoiceTraceTimelineService = __decorateElement(_init, 0, "VoiceTraceTimelineService", _dec, VoiceTraceTimelineService);
2258
+ __runInitializers(_init, 1, VoiceTraceTimelineService);
2259
+ __decoratorMetadata(_init, VoiceTraceTimelineService);
2260
+ let _VoiceTraceTimelineService = VoiceTraceTimelineService;
2261
+ // src/angular/voice-turn-latency.service.ts
2262
+ import { computed as computed8, Injectable as Injectable9, signal as signal9 } from "@angular/core";
2263
+
2264
+ // src/client/turnLatency.ts
2265
+ var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
2266
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2267
+ const response = await fetchImpl(path);
2268
+ if (!response.ok) {
2269
+ throw new Error(`Voice turn latency failed: HTTP ${response.status}`);
2270
+ }
2271
+ return await response.json();
2272
+ };
2273
+ var runVoiceTurnLatencyProof = async (path, options = {}) => {
2274
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2275
+ const response = await fetchImpl(path, { method: "POST" });
2276
+ if (!response.ok) {
2277
+ throw new Error(`Voice turn latency proof failed: HTTP ${response.status}`);
2278
+ }
2279
+ return response.json();
2280
+ };
2281
+ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) => {
2282
+ const listeners = new Set;
2283
+ let closed = false;
2284
+ let timer;
2285
+ let snapshot = {
2286
+ error: null,
2287
+ isLoading: false
2288
+ };
2289
+ const emit = () => {
2290
+ for (const listener of listeners) {
2291
+ listener();
2292
+ }
2293
+ };
2294
+ const refresh = async () => {
2295
+ if (closed) {
2296
+ return snapshot.report;
2297
+ }
2298
+ snapshot = { ...snapshot, error: null, isLoading: true };
2299
+ emit();
2300
+ try {
2301
+ const report = await fetchVoiceTurnLatency(path, options);
2302
+ snapshot = {
2303
+ error: null,
2304
+ isLoading: false,
2305
+ report,
2306
+ updatedAt: Date.now()
2307
+ };
2308
+ emit();
2309
+ return report;
2310
+ } catch (error) {
2311
+ snapshot = {
2312
+ ...snapshot,
2313
+ error: error instanceof Error ? error.message : String(error),
2314
+ isLoading: false
2315
+ };
2316
+ emit();
2317
+ throw error;
2318
+ }
2319
+ };
2320
+ const runProof = async () => {
2321
+ if (!options.proofPath) {
2322
+ throw new Error("Voice turn latency proof path is not configured.");
2323
+ }
2324
+ snapshot = { ...snapshot, error: null, isLoading: true };
2325
+ emit();
2326
+ try {
2327
+ await runVoiceTurnLatencyProof(options.proofPath, options);
2328
+ return await refresh();
2329
+ } catch (error) {
2330
+ snapshot = {
2331
+ ...snapshot,
2332
+ error: error instanceof Error ? error.message : String(error),
2333
+ isLoading: false
2334
+ };
2335
+ emit();
2336
+ throw error;
2337
+ }
2338
+ };
2339
+ const close = () => {
2340
+ closed = true;
2341
+ if (timer) {
2342
+ clearInterval(timer);
2343
+ timer = undefined;
2344
+ }
2345
+ listeners.clear();
2346
+ };
2347
+ if (options.intervalMs && options.intervalMs > 0) {
2348
+ timer = setInterval(() => {
2349
+ refresh().catch(() => {});
2350
+ }, options.intervalMs);
2351
+ }
2352
+ return {
2353
+ close,
2354
+ getServerSnapshot: () => snapshot,
2355
+ getSnapshot: () => snapshot,
2356
+ refresh,
2357
+ runProof,
2358
+ subscribe: (listener) => {
2359
+ listeners.add(listener);
2360
+ return () => {
2361
+ listeners.delete(listener);
2362
+ };
2363
+ }
2364
+ };
2365
+ };
2366
+
2367
+ // src/angular/voice-turn-latency.service.ts
2368
+ var _dec = [
2369
+ Injectable9({ providedIn: "root" })
2370
+ ];
2371
+ var _init = __decoratorStart(undefined);
2372
+
2373
+ class VoiceTurnLatencyService {
2374
+ connect(path = "/api/turn-latency", options = {}) {
2375
+ const store = createVoiceTurnLatencyStore(path, options);
2376
+ const errorSignal = signal9(null);
2377
+ const isLoadingSignal = signal9(false);
2378
+ const reportSignal = signal9(undefined);
2379
+ const updatedAtSignal = signal9(undefined);
2380
+ const sync = () => {
2381
+ const snapshot = store.getSnapshot();
2382
+ errorSignal.set(snapshot.error);
2383
+ isLoadingSignal.set(snapshot.isLoading);
2384
+ reportSignal.set(snapshot.report);
2385
+ updatedAtSignal.set(snapshot.updatedAt);
2386
+ };
2387
+ const unsubscribe = store.subscribe(sync);
2388
+ sync();
2389
+ store.refresh().catch(() => {});
2390
+ return {
2391
+ close: () => {
2392
+ unsubscribe();
2393
+ store.close();
2394
+ },
2395
+ error: computed8(() => errorSignal()),
2396
+ isLoading: computed8(() => isLoadingSignal()),
2397
+ refresh: store.refresh,
2398
+ report: computed8(() => reportSignal()),
2399
+ runProof: store.runProof,
2400
+ updatedAt: computed8(() => updatedAtSignal())
2401
+ };
2402
+ }
2403
+ }
2404
+ VoiceTurnLatencyService = __decorateElement(_init, 0, "VoiceTurnLatencyService", _dec, VoiceTurnLatencyService);
2405
+ __runInitializers(_init, 1, VoiceTurnLatencyService);
2406
+ __decoratorMetadata(_init, VoiceTurnLatencyService);
2407
+ let _VoiceTurnLatencyService = VoiceTurnLatencyService;
2408
+ // src/angular/voice-turn-quality.service.ts
2409
+ import { computed as computed9, Injectable as Injectable10, signal as signal10 } from "@angular/core";
2410
+
2411
+ // src/client/turnQuality.ts
2412
+ var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
2413
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2414
+ const response = await fetchImpl(path);
2415
+ if (!response.ok) {
2416
+ throw new Error(`Voice turn quality failed: HTTP ${response.status}`);
2417
+ }
2418
+ return await response.json();
2419
+ };
2420
+ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) => {
2421
+ const listeners = new Set;
2422
+ let closed = false;
2423
+ let timer;
2424
+ let snapshot = {
2425
+ error: null,
2426
+ isLoading: false
2427
+ };
2428
+ const emit = () => {
2429
+ for (const listener of listeners) {
2430
+ listener();
2431
+ }
2432
+ };
2433
+ const refresh = async () => {
2434
+ if (closed) {
2435
+ return snapshot.report;
2436
+ }
2437
+ snapshot = {
2438
+ ...snapshot,
2439
+ error: null,
2440
+ isLoading: true
2441
+ };
2442
+ emit();
2443
+ try {
2444
+ const report = await fetchVoiceTurnQuality(path, options);
2445
+ snapshot = {
2446
+ error: null,
2447
+ isLoading: false,
2448
+ report,
2449
+ updatedAt: Date.now()
2450
+ };
2451
+ emit();
2452
+ return report;
2453
+ } catch (error) {
2454
+ snapshot = {
2455
+ ...snapshot,
2456
+ error: error instanceof Error ? error.message : String(error),
2457
+ isLoading: false
2458
+ };
2459
+ emit();
2460
+ throw error;
2461
+ }
2462
+ };
2463
+ const close = () => {
2464
+ closed = true;
2465
+ if (timer) {
2466
+ clearInterval(timer);
2467
+ timer = undefined;
2468
+ }
2469
+ listeners.clear();
2470
+ };
2471
+ if (options.intervalMs && options.intervalMs > 0) {
2472
+ timer = setInterval(() => {
2473
+ refresh().catch(() => {});
2474
+ }, options.intervalMs);
2475
+ }
2476
+ return {
2477
+ close,
2478
+ getServerSnapshot: () => snapshot,
2479
+ getSnapshot: () => snapshot,
2480
+ refresh,
2481
+ subscribe: (listener) => {
2482
+ listeners.add(listener);
2483
+ return () => {
2484
+ listeners.delete(listener);
2485
+ };
2486
+ }
2487
+ };
2488
+ };
2489
+
2490
+ // src/angular/voice-turn-quality.service.ts
2491
+ var _dec = [
2492
+ Injectable10({ providedIn: "root" })
2493
+ ];
2494
+ var _init = __decoratorStart(undefined);
2495
+
2496
+ class VoiceTurnQualityService {
2497
+ connect(path = "/api/turn-quality", options = {}) {
2498
+ const store = createVoiceTurnQualityStore(path, options);
2499
+ const errorSignal = signal10(null);
2500
+ const isLoadingSignal = signal10(false);
2501
+ const reportSignal = signal10(undefined);
2502
+ const updatedAtSignal = signal10(undefined);
2503
+ const sync = () => {
2504
+ const snapshot = store.getSnapshot();
2505
+ errorSignal.set(snapshot.error);
2506
+ isLoadingSignal.set(snapshot.isLoading);
2507
+ reportSignal.set(snapshot.report);
2508
+ updatedAtSignal.set(snapshot.updatedAt);
2509
+ };
2510
+ const unsubscribe = store.subscribe(sync);
2511
+ sync();
2512
+ store.refresh().catch(() => {});
2513
+ return {
2514
+ close: () => {
2515
+ unsubscribe();
2516
+ store.close();
2517
+ },
2518
+ error: computed9(() => errorSignal()),
2519
+ isLoading: computed9(() => isLoadingSignal()),
2520
+ refresh: store.refresh,
2521
+ report: computed9(() => reportSignal()),
2522
+ updatedAt: computed9(() => updatedAtSignal())
2523
+ };
2524
+ }
2525
+ }
2526
+ VoiceTurnQualityService = __decorateElement(_init, 0, "VoiceTurnQualityService", _dec, VoiceTurnQualityService);
2527
+ __runInitializers(_init, 1, VoiceTurnQualityService);
2528
+ __decoratorMetadata(_init, VoiceTurnQualityService);
2529
+ let _VoiceTurnQualityService = VoiceTurnQualityService;
2530
+ // src/angular/voice-workflow-status.service.ts
2531
+ import { computed as computed10, Injectable as Injectable11, signal as signal11 } from "@angular/core";
2532
+
2533
+ // src/client/workflowStatus.ts
2534
+ var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
2535
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2536
+ const response = await fetchImpl(path);
2537
+ if (!response.ok) {
2538
+ throw new Error(`Voice workflow status failed: HTTP ${response.status}`);
2539
+ }
2540
+ return await response.json();
2541
+ };
2542
+ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options = {}) => {
2543
+ const listeners = new Set;
2544
+ let closed = false;
2545
+ let timer;
2546
+ let snapshot = {
2547
+ error: null,
2548
+ isLoading: false
2549
+ };
2550
+ const emit = () => {
2551
+ for (const listener of listeners) {
2552
+ listener();
2553
+ }
2554
+ };
2555
+ const refresh = async () => {
2556
+ if (closed) {
2557
+ return snapshot.report;
2558
+ }
2559
+ snapshot = {
2560
+ ...snapshot,
2561
+ error: null,
2562
+ isLoading: true
2563
+ };
2564
+ emit();
2565
+ try {
2566
+ const report = await fetchVoiceWorkflowStatus(path, options);
2567
+ snapshot = {
2568
+ error: null,
2569
+ isLoading: false,
2570
+ report,
2571
+ updatedAt: Date.now()
2572
+ };
2573
+ emit();
2574
+ return report;
2575
+ } catch (error) {
2576
+ snapshot = {
2577
+ ...snapshot,
2578
+ error: error instanceof Error ? error.message : String(error),
2579
+ isLoading: false
2580
+ };
2581
+ emit();
2582
+ throw error;
2583
+ }
2584
+ };
2585
+ const close = () => {
2586
+ closed = true;
2587
+ if (timer) {
2588
+ clearInterval(timer);
2589
+ timer = undefined;
2590
+ }
2591
+ listeners.clear();
2592
+ };
2593
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
2594
+ timer = setInterval(() => {
2595
+ refresh().catch(() => {});
2596
+ }, options.intervalMs);
2597
+ }
2598
+ return {
2599
+ close,
2600
+ getServerSnapshot: () => snapshot,
2601
+ getSnapshot: () => snapshot,
2602
+ refresh,
2603
+ subscribe: (listener) => {
2604
+ listeners.add(listener);
2605
+ return () => {
2606
+ listeners.delete(listener);
2607
+ };
2608
+ }
2609
+ };
2610
+ };
2611
+
2612
+ // src/angular/voice-workflow-status.service.ts
2613
+ var _dec = [
2614
+ Injectable11({ providedIn: "root" })
2615
+ ];
2616
+ var _init = __decoratorStart(undefined);
2617
+
2618
+ class VoiceWorkflowStatusService {
2619
+ connect(path = "/evals/scenarios/json", options = {}) {
2620
+ const store = createVoiceWorkflowStatusStore(path, options);
2621
+ const errorSignal = signal11(null);
2622
+ const isLoadingSignal = signal11(false);
2623
+ const reportSignal = signal11(undefined);
2624
+ const updatedAtSignal = signal11(undefined);
2625
+ const sync = () => {
2626
+ const snapshot = store.getSnapshot();
2627
+ errorSignal.set(snapshot.error);
2628
+ isLoadingSignal.set(snapshot.isLoading);
2629
+ reportSignal.set(snapshot.report);
2630
+ updatedAtSignal.set(snapshot.updatedAt);
2631
+ };
2632
+ const unsubscribe = store.subscribe(sync);
2633
+ sync();
2634
+ if (typeof window !== "undefined") {
2635
+ store.refresh().catch(() => {});
2636
+ }
2637
+ return {
2638
+ close: () => {
2639
+ unsubscribe();
2640
+ store.close();
2641
+ },
2642
+ error: computed10(() => errorSignal()),
2643
+ isLoading: computed10(() => isLoadingSignal()),
2644
+ refresh: store.refresh,
2645
+ report: computed10(() => reportSignal()),
2646
+ updatedAt: computed10(() => updatedAtSignal())
2647
+ };
2648
+ }
2649
+ }
2650
+ VoiceWorkflowStatusService = __decorateElement(_init, 0, "VoiceWorkflowStatusService", _dec, VoiceWorkflowStatusService);
2651
+ __runInitializers(_init, 1, VoiceWorkflowStatusService);
2652
+ __decoratorMetadata(_init, VoiceWorkflowStatusService);
2653
+ let _VoiceWorkflowStatusService = VoiceWorkflowStatusService;
1291
2654
  export {
2655
+ VoiceWorkflowStatusService,
2656
+ VoiceTurnQualityService,
2657
+ VoiceTurnLatencyService,
2658
+ VoiceTraceTimelineService,
1292
2659
  VoiceStreamService,
1293
- VoiceControllerService
2660
+ VoiceRoutingStatusService,
2661
+ VoiceProviderStatusService,
2662
+ VoiceProviderCapabilitiesService,
2663
+ VoiceOpsStatusService,
2664
+ VoiceControllerService,
2665
+ VoiceCampaignDialerProofService
1294
2666
  };