@absolutejs/voice 0.0.22-beta.13 → 0.0.22-beta.130

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 (159) hide show
  1. package/README.md +779 -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 +1394 -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 +697 -15
  33. package/dist/client/index.d.ts +40 -0
  34. package/dist/client/index.js +2138 -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 +103 -9
  61. package/dist/index.js +17158 -4684
  62. package/dist/liveLatency.d.ts +78 -0
  63. package/dist/modelAdapters.d.ts +26 -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 +65 -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 +227 -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 +2726 -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/resilienceRoutes.d.ts +142 -0
  104. package/dist/sessionReplay.d.ts +175 -0
  105. package/dist/simulationSuite.d.ts +120 -0
  106. package/dist/sqliteStore.d.ts +13 -2
  107. package/dist/svelte/createVoiceCampaignDialerProof.d.ts +9 -0
  108. package/dist/svelte/createVoiceOpsStatus.d.ts +9 -0
  109. package/dist/svelte/createVoiceProviderCapabilities.d.ts +10 -0
  110. package/dist/svelte/createVoiceProviderSimulationControls.d.ts +11 -0
  111. package/dist/svelte/createVoiceProviderStatus.d.ts +10 -0
  112. package/dist/svelte/createVoiceRoutingStatus.d.ts +10 -0
  113. package/dist/svelte/createVoiceTraceTimeline.d.ts +10 -0
  114. package/dist/svelte/createVoiceTurnLatency.d.ts +11 -0
  115. package/dist/svelte/createVoiceTurnQuality.d.ts +10 -0
  116. package/dist/svelte/createVoiceWorkflowStatus.d.ts +8 -0
  117. package/dist/svelte/index.d.ts +10 -0
  118. package/dist/svelte/index.js +2152 -202
  119. package/dist/telephony/contract.d.ts +61 -0
  120. package/dist/telephony/matrix.d.ts +97 -0
  121. package/dist/telephony/plivo.d.ts +254 -0
  122. package/dist/telephony/telnyx.d.ts +247 -0
  123. package/dist/telephony/twilio.d.ts +135 -2
  124. package/dist/telephonyOutcome.d.ts +201 -0
  125. package/dist/testing/index.d.ts +2 -0
  126. package/dist/testing/index.js +2830 -37
  127. package/dist/testing/ioProviderSimulator.d.ts +41 -0
  128. package/dist/testing/providerSimulator.d.ts +44 -0
  129. package/dist/toolContract.d.ts +130 -0
  130. package/dist/toolRuntime.d.ts +50 -0
  131. package/dist/trace.d.ts +1 -1
  132. package/dist/traceDeliveryRoutes.d.ts +86 -0
  133. package/dist/traceTimeline.d.ts +93 -0
  134. package/dist/turnLatency.d.ts +95 -0
  135. package/dist/turnQuality.d.ts +94 -0
  136. package/dist/types.d.ts +169 -4
  137. package/dist/vue/VoiceOpsStatus.d.ts +30 -0
  138. package/dist/vue/VoiceProviderCapabilities.d.ts +51 -0
  139. package/dist/vue/VoiceProviderSimulationControls.d.ts +88 -0
  140. package/dist/vue/VoiceProviderStatus.d.ts +51 -0
  141. package/dist/vue/VoiceRoutingStatus.d.ts +51 -0
  142. package/dist/vue/VoiceTurnLatency.d.ts +69 -0
  143. package/dist/vue/VoiceTurnQuality.d.ts +51 -0
  144. package/dist/vue/index.d.ts +17 -0
  145. package/dist/vue/index.js +2636 -31
  146. package/dist/vue/useVoiceCampaignDialerProof.d.ts +11 -0
  147. package/dist/vue/useVoiceController.d.ts +2 -1
  148. package/dist/vue/useVoiceOpsStatus.d.ts +9 -0
  149. package/dist/vue/useVoiceProviderCapabilities.d.ts +9 -0
  150. package/dist/vue/useVoiceProviderSimulationControls.d.ts +24 -0
  151. package/dist/vue/useVoiceProviderStatus.d.ts +9 -0
  152. package/dist/vue/useVoiceRoutingStatus.d.ts +8 -0
  153. package/dist/vue/useVoiceStream.d.ts +4 -1
  154. package/dist/vue/useVoiceTraceTimeline.d.ts +9 -0
  155. package/dist/vue/useVoiceTurnLatency.d.ts +10 -0
  156. package/dist/vue/useVoiceTurnQuality.d.ts +9 -0
  157. package/dist/vue/useVoiceWorkflowStatus.d.ts +9 -0
  158. package/dist/workflowContract.d.ts +91 -0
  159. 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,
@@ -494,6 +913,9 @@ var createVoiceStream = (path, options = {}) => {
494
913
  }
495
914
  });
496
915
  return {
916
+ callControl(message) {
917
+ connection.callControl(message);
918
+ },
497
919
  close() {
498
920
  unsubscribeConnection();
499
921
  connection.close();
@@ -522,6 +944,9 @@ var createVoiceStream = (path, options = {}) => {
522
944
  get partial() {
523
945
  return store.getSnapshot().partial;
524
946
  },
947
+ get reconnect() {
948
+ return store.getSnapshot().reconnect;
949
+ },
525
950
  get sessionId() {
526
951
  return connection.getSessionId();
527
952
  },
@@ -537,6 +962,9 @@ var createVoiceStream = (path, options = {}) => {
537
962
  get assistantAudio() {
538
963
  return store.getSnapshot().assistantAudio;
539
964
  },
965
+ get call() {
966
+ return store.getSnapshot().call;
967
+ },
540
968
  sendAudio(audio) {
541
969
  connection.sendAudio(audio);
542
970
  },
@@ -551,27 +979,31 @@ var createVoiceStream = (path, options = {}) => {
551
979
 
552
980
  // src/angular/voice-stream.service.ts
553
981
  var _dec = [
554
- Injectable({ providedIn: "root" })
982
+ Injectable3({ providedIn: "root" })
555
983
  ];
556
984
  var _init = __decoratorStart(undefined);
557
985
 
558
986
  class VoiceStreamService {
559
987
  connect(path, options = {}) {
560
988
  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([]);
989
+ const assistantAudioSignal = signal3([]);
990
+ const assistantTextsSignal = signal3([]);
991
+ const callSignal = signal3(null);
992
+ const errorSignal = signal3(null);
993
+ const isConnectedSignal = signal3(false);
994
+ const partialSignal = signal3("");
995
+ const reconnectSignal = signal3(stream.reconnect);
996
+ const sessionIdSignal = signal3(stream.sessionId);
997
+ const statusSignal = signal3(stream.status);
998
+ const turnsSignal = signal3([]);
569
999
  const sync = () => {
570
1000
  assistantAudioSignal.set([...stream.assistantAudio]);
571
1001
  assistantTextsSignal.set([...stream.assistantTexts]);
1002
+ callSignal.set(stream.call);
572
1003
  errorSignal.set(stream.error);
573
1004
  isConnectedSignal.set(stream.isConnected);
574
1005
  partialSignal.set(stream.partial);
1006
+ reconnectSignal.set(stream.reconnect);
575
1007
  sessionIdSignal.set(stream.sessionId);
576
1008
  statusSignal.set(stream.status);
577
1009
  turnsSignal.set([...stream.turns]);
@@ -579,20 +1011,23 @@ class VoiceStreamService {
579
1011
  const unsubscribe = stream.subscribe(sync);
580
1012
  sync();
581
1013
  return {
582
- assistantAudio: computed(() => assistantAudioSignal()),
583
- assistantTexts: computed(() => assistantTextsSignal()),
1014
+ assistantAudio: computed3(() => assistantAudioSignal()),
1015
+ assistantTexts: computed3(() => assistantTextsSignal()),
1016
+ call: computed3(() => callSignal()),
1017
+ callControl: (message) => stream.callControl(message),
584
1018
  close: () => {
585
1019
  unsubscribe();
586
1020
  stream.close();
587
1021
  },
588
1022
  endTurn: () => stream.endTurn(),
589
- error: computed(() => errorSignal()),
590
- isConnected: computed(() => isConnectedSignal()),
591
- partial: computed(() => partialSignal()),
1023
+ error: computed3(() => errorSignal()),
1024
+ isConnected: computed3(() => isConnectedSignal()),
1025
+ partial: computed3(() => partialSignal()),
1026
+ reconnect: computed3(() => reconnectSignal()),
592
1027
  sendAudio: (audio) => stream.sendAudio(audio),
593
- sessionId: computed(() => sessionIdSignal()),
594
- status: computed(() => statusSignal()),
595
- turns: computed(() => turnsSignal())
1028
+ sessionId: computed3(() => sessionIdSignal()),
1029
+ status: computed3(() => statusSignal()),
1030
+ turns: computed3(() => turnsSignal())
596
1031
  };
597
1032
  }
598
1033
  }
@@ -601,7 +1036,7 @@ __runInitializers(_init, 1, VoiceStreamService);
601
1036
  __decoratorMetadata(_init, VoiceStreamService);
602
1037
  let _VoiceStreamService = VoiceStreamService;
603
1038
  // src/angular/voice-controller.service.ts
604
- import { computed as computed2, Injectable as Injectable2, signal as signal2 } from "@angular/core";
1039
+ import { computed as computed4, Injectable as Injectable4, signal as signal4 } from "@angular/core";
605
1040
 
606
1041
  // src/client/htmx.ts
607
1042
  var DEFAULT_EVENT_NAME = "voice-refresh";
@@ -1065,10 +1500,12 @@ var resolveVoiceRuntimePreset = (name = "default") => {
1065
1500
  var createInitialState2 = (stream) => ({
1066
1501
  assistantAudio: [...stream.assistantAudio],
1067
1502
  assistantTexts: [...stream.assistantTexts],
1503
+ call: stream.call,
1068
1504
  error: stream.error,
1069
1505
  isConnected: stream.isConnected,
1070
1506
  isRecording: false,
1071
1507
  partial: stream.partial,
1508
+ reconnect: stream.reconnect,
1072
1509
  recordingError: null,
1073
1510
  sessionId: stream.sessionId,
1074
1511
  scenarioId: stream.scenarioId,
@@ -1094,9 +1531,11 @@ var createVoiceController = (path, options = {}) => {
1094
1531
  ...state,
1095
1532
  assistantAudio: [...stream.assistantAudio],
1096
1533
  assistantTexts: [...stream.assistantTexts],
1534
+ call: stream.call,
1097
1535
  error: stream.error,
1098
1536
  isConnected: stream.isConnected,
1099
1537
  partial: stream.partial,
1538
+ reconnect: stream.reconnect,
1100
1539
  sessionId: stream.sessionId,
1101
1540
  scenarioId: stream.scenarioId,
1102
1541
  status: stream.status,
@@ -1121,7 +1560,13 @@ var createVoiceController = (path, options = {}) => {
1121
1560
  capture = createMicrophoneCapture({
1122
1561
  channelCount: options.capture?.channelCount ?? preset.capture.channelCount,
1123
1562
  onLevel: options.capture?.onLevel,
1124
- onAudio: (audio) => stream.sendAudio(audio),
1563
+ onAudio: (audio) => {
1564
+ if (options.capture?.onAudio) {
1565
+ options.capture.onAudio(audio, stream.sendAudio);
1566
+ return;
1567
+ }
1568
+ stream.sendAudio(audio);
1569
+ },
1125
1570
  sampleRateHz: options.capture?.sampleRateHz ?? preset.capture.sampleRateHz
1126
1571
  });
1127
1572
  return capture;
@@ -1171,6 +1616,7 @@ var createVoiceController = (path, options = {}) => {
1171
1616
  bindHTMX(bindingOptions) {
1172
1617
  return bindVoiceHTMX(stream, bindingOptions);
1173
1618
  },
1619
+ callControl: (message) => stream.callControl(message),
1174
1620
  close,
1175
1621
  endTurn: () => stream.endTurn(),
1176
1622
  get error() {
@@ -1190,6 +1636,9 @@ var createVoiceController = (path, options = {}) => {
1190
1636
  get recordingError() {
1191
1637
  return state.recordingError;
1192
1638
  },
1639
+ get reconnect() {
1640
+ return state.reconnect;
1641
+ },
1193
1642
  sendAudio: (audio) => stream.sendAudio(audio),
1194
1643
  get sessionId() {
1195
1644
  return state.sessionId;
@@ -1223,29 +1672,33 @@ var createVoiceController = (path, options = {}) => {
1223
1672
  },
1224
1673
  get assistantAudio() {
1225
1674
  return state.assistantAudio;
1675
+ },
1676
+ get call() {
1677
+ return state.call;
1226
1678
  }
1227
1679
  };
1228
1680
  };
1229
1681
 
1230
1682
  // src/angular/voice-controller.service.ts
1231
1683
  var _dec = [
1232
- Injectable2({ providedIn: "root" })
1684
+ Injectable4({ providedIn: "root" })
1233
1685
  ];
1234
1686
  var _init = __decoratorStart(undefined);
1235
1687
 
1236
1688
  class VoiceControllerService {
1237
1689
  connect(path, options = {}) {
1238
1690
  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([]);
1691
+ const assistantAudioSignal = signal4([]);
1692
+ const assistantTextsSignal = signal4([]);
1693
+ const errorSignal = signal4(null);
1694
+ const isConnectedSignal = signal4(false);
1695
+ const isRecordingSignal = signal4(false);
1696
+ const partialSignal = signal4("");
1697
+ const reconnectSignal = signal4(controller.reconnect);
1698
+ const recordingErrorSignal = signal4(null);
1699
+ const sessionIdSignal = signal4(controller.sessionId);
1700
+ const statusSignal = signal4(controller.status);
1701
+ const turnsSignal = signal4([]);
1249
1702
  const sync = () => {
1250
1703
  assistantAudioSignal.set([...controller.assistantAudio]);
1251
1704
  assistantTextsSignal.set([...controller.assistantTexts]);
@@ -1253,6 +1706,7 @@ class VoiceControllerService {
1253
1706
  isConnectedSignal.set(controller.isConnected);
1254
1707
  isRecordingSignal.set(controller.isRecording);
1255
1708
  partialSignal.set(controller.partial);
1709
+ reconnectSignal.set(controller.reconnect);
1256
1710
  recordingErrorSignal.set(controller.recordingError);
1257
1711
  sessionIdSignal.set(controller.sessionId);
1258
1712
  statusSignal.set(controller.status);
@@ -1261,26 +1715,27 @@ class VoiceControllerService {
1261
1715
  const unsubscribe = controller.subscribe(sync);
1262
1716
  sync();
1263
1717
  return {
1264
- assistantAudio: computed2(() => assistantAudioSignal()),
1265
- assistantTexts: computed2(() => assistantTextsSignal()),
1718
+ assistantAudio: computed4(() => assistantAudioSignal()),
1719
+ assistantTexts: computed4(() => assistantTextsSignal()),
1266
1720
  bindHTMX: controller.bindHTMX,
1267
1721
  close: () => {
1268
1722
  unsubscribe();
1269
1723
  controller.close();
1270
1724
  },
1271
1725
  endTurn: () => controller.endTurn(),
1272
- error: computed2(() => errorSignal()),
1273
- isConnected: computed2(() => isConnectedSignal()),
1274
- isRecording: computed2(() => isRecordingSignal()),
1275
- partial: computed2(() => partialSignal()),
1276
- recordingError: computed2(() => recordingErrorSignal()),
1726
+ error: computed4(() => errorSignal()),
1727
+ isConnected: computed4(() => isConnectedSignal()),
1728
+ isRecording: computed4(() => isRecordingSignal()),
1729
+ partial: computed4(() => partialSignal()),
1730
+ reconnect: computed4(() => reconnectSignal()),
1731
+ recordingError: computed4(() => recordingErrorSignal()),
1277
1732
  sendAudio: (audio) => controller.sendAudio(audio),
1278
- sessionId: computed2(() => sessionIdSignal()),
1733
+ sessionId: computed4(() => sessionIdSignal()),
1279
1734
  startRecording: () => controller.startRecording(),
1280
- status: computed2(() => statusSignal()),
1735
+ status: computed4(() => statusSignal()),
1281
1736
  stopRecording: () => controller.stopRecording(),
1282
1737
  toggleRecording: () => controller.toggleRecording(),
1283
- turns: computed2(() => turnsSignal())
1738
+ turns: computed4(() => turnsSignal())
1284
1739
  };
1285
1740
  }
1286
1741
  }
@@ -1288,7 +1743,900 @@ VoiceControllerService = __decorateElement(_init, 0, "VoiceControllerService", _
1288
1743
  __runInitializers(_init, 1, VoiceControllerService);
1289
1744
  __decoratorMetadata(_init, VoiceControllerService);
1290
1745
  let _VoiceControllerService = VoiceControllerService;
1746
+ // src/angular/voice-provider-capabilities.service.ts
1747
+ import { computed as computed5, Injectable as Injectable5, signal as signal5 } from "@angular/core";
1748
+
1749
+ // src/client/providerCapabilities.ts
1750
+ var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
1751
+ const fetchImpl = options.fetch ?? globalThis.fetch;
1752
+ const response = await fetchImpl(path);
1753
+ if (!response.ok) {
1754
+ throw new Error(`Voice provider capabilities failed: HTTP ${response.status}`);
1755
+ }
1756
+ return await response.json();
1757
+ };
1758
+ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities", options = {}) => {
1759
+ const listeners = new Set;
1760
+ let closed = false;
1761
+ let timer;
1762
+ let snapshot = {
1763
+ error: null,
1764
+ isLoading: false
1765
+ };
1766
+ const emit = () => {
1767
+ for (const listener of listeners) {
1768
+ listener();
1769
+ }
1770
+ };
1771
+ const refresh = async () => {
1772
+ if (closed) {
1773
+ return snapshot.report;
1774
+ }
1775
+ snapshot = {
1776
+ ...snapshot,
1777
+ error: null,
1778
+ isLoading: true
1779
+ };
1780
+ emit();
1781
+ try {
1782
+ const report = await fetchVoiceProviderCapabilities(path, options);
1783
+ snapshot = {
1784
+ error: null,
1785
+ isLoading: false,
1786
+ report,
1787
+ updatedAt: Date.now()
1788
+ };
1789
+ emit();
1790
+ return report;
1791
+ } catch (error) {
1792
+ snapshot = {
1793
+ ...snapshot,
1794
+ error: error instanceof Error ? error.message : String(error),
1795
+ isLoading: false
1796
+ };
1797
+ emit();
1798
+ throw error;
1799
+ }
1800
+ };
1801
+ const close = () => {
1802
+ closed = true;
1803
+ if (timer) {
1804
+ clearInterval(timer);
1805
+ timer = undefined;
1806
+ }
1807
+ listeners.clear();
1808
+ };
1809
+ if (options.intervalMs && options.intervalMs > 0) {
1810
+ timer = setInterval(() => {
1811
+ refresh().catch(() => {});
1812
+ }, options.intervalMs);
1813
+ }
1814
+ return {
1815
+ close,
1816
+ getServerSnapshot: () => snapshot,
1817
+ getSnapshot: () => snapshot,
1818
+ refresh,
1819
+ subscribe: (listener) => {
1820
+ listeners.add(listener);
1821
+ return () => {
1822
+ listeners.delete(listener);
1823
+ };
1824
+ }
1825
+ };
1826
+ };
1827
+
1828
+ // src/angular/voice-provider-capabilities.service.ts
1829
+ var _dec = [
1830
+ Injectable5({ providedIn: "root" })
1831
+ ];
1832
+ var _init = __decoratorStart(undefined);
1833
+
1834
+ class VoiceProviderCapabilitiesService {
1835
+ connect(path = "/api/provider-capabilities", options = {}) {
1836
+ const store = createVoiceProviderCapabilitiesStore(path, options);
1837
+ const errorSignal = signal5(null);
1838
+ const isLoadingSignal = signal5(false);
1839
+ const reportSignal = signal5(undefined);
1840
+ const updatedAtSignal = signal5(undefined);
1841
+ const sync = () => {
1842
+ const snapshot = store.getSnapshot();
1843
+ errorSignal.set(snapshot.error);
1844
+ isLoadingSignal.set(snapshot.isLoading);
1845
+ reportSignal.set(snapshot.report);
1846
+ updatedAtSignal.set(snapshot.updatedAt);
1847
+ };
1848
+ const unsubscribe = store.subscribe(sync);
1849
+ sync();
1850
+ store.refresh().catch(() => {});
1851
+ return {
1852
+ close: () => {
1853
+ unsubscribe();
1854
+ store.close();
1855
+ },
1856
+ error: computed5(() => errorSignal()),
1857
+ isLoading: computed5(() => isLoadingSignal()),
1858
+ refresh: store.refresh,
1859
+ report: computed5(() => reportSignal()),
1860
+ updatedAt: computed5(() => updatedAtSignal())
1861
+ };
1862
+ }
1863
+ }
1864
+ VoiceProviderCapabilitiesService = __decorateElement(_init, 0, "VoiceProviderCapabilitiesService", _dec, VoiceProviderCapabilitiesService);
1865
+ __runInitializers(_init, 1, VoiceProviderCapabilitiesService);
1866
+ __decoratorMetadata(_init, VoiceProviderCapabilitiesService);
1867
+ let _VoiceProviderCapabilitiesService = VoiceProviderCapabilitiesService;
1868
+ // src/angular/voice-provider-status.service.ts
1869
+ import { computed as computed6, Injectable as Injectable6, signal as signal6 } from "@angular/core";
1870
+
1871
+ // src/client/providerStatus.ts
1872
+ var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
1873
+ const fetchImpl = options.fetch ?? globalThis.fetch;
1874
+ const response = await fetchImpl(path);
1875
+ if (!response.ok) {
1876
+ throw new Error(`Voice provider status failed: HTTP ${response.status}`);
1877
+ }
1878
+ return await response.json();
1879
+ };
1880
+ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {}) => {
1881
+ const listeners = new Set;
1882
+ let closed = false;
1883
+ let timer;
1884
+ let snapshot = {
1885
+ error: null,
1886
+ isLoading: false,
1887
+ providers: []
1888
+ };
1889
+ const emit = () => {
1890
+ for (const listener of listeners) {
1891
+ listener();
1892
+ }
1893
+ };
1894
+ const refresh = async () => {
1895
+ if (closed) {
1896
+ return snapshot.providers;
1897
+ }
1898
+ snapshot = {
1899
+ ...snapshot,
1900
+ error: null,
1901
+ isLoading: true
1902
+ };
1903
+ emit();
1904
+ try {
1905
+ const providers = await fetchVoiceProviderStatus(path, options);
1906
+ snapshot = {
1907
+ error: null,
1908
+ isLoading: false,
1909
+ providers,
1910
+ updatedAt: Date.now()
1911
+ };
1912
+ emit();
1913
+ return providers;
1914
+ } catch (error) {
1915
+ snapshot = {
1916
+ ...snapshot,
1917
+ error: error instanceof Error ? error.message : String(error),
1918
+ isLoading: false
1919
+ };
1920
+ emit();
1921
+ throw error;
1922
+ }
1923
+ };
1924
+ const close = () => {
1925
+ closed = true;
1926
+ if (timer) {
1927
+ clearInterval(timer);
1928
+ timer = undefined;
1929
+ }
1930
+ listeners.clear();
1931
+ };
1932
+ if (options.intervalMs && options.intervalMs > 0) {
1933
+ timer = setInterval(() => {
1934
+ refresh().catch(() => {});
1935
+ }, options.intervalMs);
1936
+ }
1937
+ return {
1938
+ close,
1939
+ getServerSnapshot: () => snapshot,
1940
+ getSnapshot: () => snapshot,
1941
+ refresh,
1942
+ subscribe: (listener) => {
1943
+ listeners.add(listener);
1944
+ return () => {
1945
+ listeners.delete(listener);
1946
+ };
1947
+ }
1948
+ };
1949
+ };
1950
+
1951
+ // src/angular/voice-provider-status.service.ts
1952
+ var _dec = [
1953
+ Injectable6({ providedIn: "root" })
1954
+ ];
1955
+ var _init = __decoratorStart(undefined);
1956
+
1957
+ class VoiceProviderStatusService {
1958
+ connect(path = "/api/provider-status", options = {}) {
1959
+ const store = createVoiceProviderStatusStore(path, options);
1960
+ const errorSignal = signal6(null);
1961
+ const isLoadingSignal = signal6(false);
1962
+ const providersSignal = signal6([]);
1963
+ const updatedAtSignal = signal6(undefined);
1964
+ const sync = () => {
1965
+ const snapshot = store.getSnapshot();
1966
+ errorSignal.set(snapshot.error);
1967
+ isLoadingSignal.set(snapshot.isLoading);
1968
+ providersSignal.set([...snapshot.providers]);
1969
+ updatedAtSignal.set(snapshot.updatedAt);
1970
+ };
1971
+ const unsubscribe = store.subscribe(sync);
1972
+ sync();
1973
+ store.refresh().catch(() => {});
1974
+ return {
1975
+ close: () => {
1976
+ unsubscribe();
1977
+ store.close();
1978
+ },
1979
+ error: computed6(() => errorSignal()),
1980
+ isLoading: computed6(() => isLoadingSignal()),
1981
+ providers: computed6(() => providersSignal()),
1982
+ refresh: store.refresh,
1983
+ updatedAt: computed6(() => updatedAtSignal())
1984
+ };
1985
+ }
1986
+ }
1987
+ VoiceProviderStatusService = __decorateElement(_init, 0, "VoiceProviderStatusService", _dec, VoiceProviderStatusService);
1988
+ __runInitializers(_init, 1, VoiceProviderStatusService);
1989
+ __decoratorMetadata(_init, VoiceProviderStatusService);
1990
+ let _VoiceProviderStatusService = VoiceProviderStatusService;
1991
+ // src/angular/voice-routing-status.service.ts
1992
+ import { Injectable as Injectable7, signal as signal7 } from "@angular/core";
1993
+
1994
+ // src/client/routingStatus.ts
1995
+ var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
1996
+ const fetchImpl = options.fetch ?? globalThis.fetch;
1997
+ const response = await fetchImpl(path);
1998
+ if (!response.ok) {
1999
+ throw new Error(`Voice routing status failed: HTTP ${response.status}`);
2000
+ }
2001
+ return await response.json();
2002
+ };
2003
+ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {}) => {
2004
+ const listeners = new Set;
2005
+ let closed = false;
2006
+ let timer;
2007
+ let snapshot = {
2008
+ decision: null,
2009
+ error: null,
2010
+ isLoading: false
2011
+ };
2012
+ const emit = () => {
2013
+ for (const listener of listeners) {
2014
+ listener();
2015
+ }
2016
+ };
2017
+ const refresh = async () => {
2018
+ if (closed) {
2019
+ return snapshot.decision;
2020
+ }
2021
+ snapshot = {
2022
+ ...snapshot,
2023
+ error: null,
2024
+ isLoading: true
2025
+ };
2026
+ emit();
2027
+ try {
2028
+ const decision = await fetchVoiceRoutingStatus(path, options);
2029
+ snapshot = {
2030
+ decision,
2031
+ error: null,
2032
+ isLoading: false,
2033
+ updatedAt: Date.now()
2034
+ };
2035
+ emit();
2036
+ return decision;
2037
+ } catch (error) {
2038
+ snapshot = {
2039
+ ...snapshot,
2040
+ error: error instanceof Error ? error.message : String(error),
2041
+ isLoading: false
2042
+ };
2043
+ emit();
2044
+ throw error;
2045
+ }
2046
+ };
2047
+ const close = () => {
2048
+ closed = true;
2049
+ if (timer) {
2050
+ clearInterval(timer);
2051
+ timer = undefined;
2052
+ }
2053
+ listeners.clear();
2054
+ };
2055
+ if (options.intervalMs && options.intervalMs > 0) {
2056
+ timer = setInterval(() => {
2057
+ refresh().catch(() => {});
2058
+ }, options.intervalMs);
2059
+ }
2060
+ return {
2061
+ close,
2062
+ getServerSnapshot: () => snapshot,
2063
+ getSnapshot: () => snapshot,
2064
+ refresh,
2065
+ subscribe: (listener) => {
2066
+ listeners.add(listener);
2067
+ return () => {
2068
+ listeners.delete(listener);
2069
+ };
2070
+ }
2071
+ };
2072
+ };
2073
+
2074
+ // src/angular/voice-routing-status.service.ts
2075
+ var _dec = [
2076
+ Injectable7({ providedIn: "root" })
2077
+ ];
2078
+ var _init = __decoratorStart(undefined);
2079
+
2080
+ class VoiceRoutingStatusService {
2081
+ connect(path = "/api/routing/latest", options = {}) {
2082
+ const store = createVoiceRoutingStatusStore(path, options);
2083
+ const decisionSignal = signal7(null);
2084
+ const errorSignal = signal7(null);
2085
+ const isLoadingSignal = signal7(false);
2086
+ const updatedAtSignal = signal7(undefined);
2087
+ const sync = () => {
2088
+ const snapshot = store.getSnapshot();
2089
+ decisionSignal.set(snapshot.decision);
2090
+ errorSignal.set(snapshot.error);
2091
+ isLoadingSignal.set(snapshot.isLoading);
2092
+ updatedAtSignal.set(snapshot.updatedAt);
2093
+ };
2094
+ const unsubscribe = store.subscribe(sync);
2095
+ sync();
2096
+ store.refresh().catch(() => {});
2097
+ return {
2098
+ close: () => {
2099
+ unsubscribe();
2100
+ store.close();
2101
+ },
2102
+ decision: decisionSignal.asReadonly(),
2103
+ error: errorSignal.asReadonly(),
2104
+ isLoading: isLoadingSignal.asReadonly(),
2105
+ refresh: store.refresh,
2106
+ updatedAt: updatedAtSignal.asReadonly()
2107
+ };
2108
+ }
2109
+ }
2110
+ VoiceRoutingStatusService = __decorateElement(_init, 0, "VoiceRoutingStatusService", _dec, VoiceRoutingStatusService);
2111
+ __runInitializers(_init, 1, VoiceRoutingStatusService);
2112
+ __decoratorMetadata(_init, VoiceRoutingStatusService);
2113
+ let _VoiceRoutingStatusService = VoiceRoutingStatusService;
2114
+ // src/angular/voice-trace-timeline.service.ts
2115
+ import { computed as computed7, Injectable as Injectable8, signal as signal8 } from "@angular/core";
2116
+
2117
+ // src/client/traceTimeline.ts
2118
+ var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
2119
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2120
+ const response = await fetchImpl(path);
2121
+ if (!response.ok) {
2122
+ throw new Error(`Voice trace timeline failed: HTTP ${response.status}`);
2123
+ }
2124
+ return await response.json();
2125
+ };
2126
+ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) => {
2127
+ const listeners = new Set;
2128
+ let closed = false;
2129
+ let timer;
2130
+ let snapshot = {
2131
+ error: null,
2132
+ isLoading: false,
2133
+ report: null
2134
+ };
2135
+ const emit = () => {
2136
+ for (const listener of listeners) {
2137
+ listener();
2138
+ }
2139
+ };
2140
+ const refresh = async () => {
2141
+ if (closed) {
2142
+ return snapshot.report;
2143
+ }
2144
+ snapshot = {
2145
+ ...snapshot,
2146
+ error: null,
2147
+ isLoading: true
2148
+ };
2149
+ emit();
2150
+ try {
2151
+ const report = await fetchVoiceTraceTimeline(path, options);
2152
+ snapshot = {
2153
+ error: null,
2154
+ isLoading: false,
2155
+ report,
2156
+ updatedAt: Date.now()
2157
+ };
2158
+ emit();
2159
+ return report;
2160
+ } catch (error) {
2161
+ snapshot = {
2162
+ ...snapshot,
2163
+ error: error instanceof Error ? error.message : String(error),
2164
+ isLoading: false
2165
+ };
2166
+ emit();
2167
+ throw error;
2168
+ }
2169
+ };
2170
+ const close = () => {
2171
+ closed = true;
2172
+ if (timer) {
2173
+ clearInterval(timer);
2174
+ timer = undefined;
2175
+ }
2176
+ listeners.clear();
2177
+ };
2178
+ if (options.intervalMs && options.intervalMs > 0) {
2179
+ timer = setInterval(() => {
2180
+ refresh().catch(() => {});
2181
+ }, options.intervalMs);
2182
+ }
2183
+ return {
2184
+ close,
2185
+ getServerSnapshot: () => snapshot,
2186
+ getSnapshot: () => snapshot,
2187
+ refresh,
2188
+ subscribe: (listener) => {
2189
+ listeners.add(listener);
2190
+ return () => {
2191
+ listeners.delete(listener);
2192
+ };
2193
+ }
2194
+ };
2195
+ };
2196
+
2197
+ // src/angular/voice-trace-timeline.service.ts
2198
+ var _dec = [
2199
+ Injectable8({ providedIn: "root" })
2200
+ ];
2201
+ var _init = __decoratorStart(undefined);
2202
+
2203
+ class VoiceTraceTimelineService {
2204
+ connect(path = "/api/voice-traces", options = {}) {
2205
+ const store = createVoiceTraceTimelineStore(path, options);
2206
+ const errorSignal = signal8(null);
2207
+ const isLoadingSignal = signal8(false);
2208
+ const reportSignal = signal8(null);
2209
+ const updatedAtSignal = signal8(undefined);
2210
+ const sync = () => {
2211
+ const snapshot = store.getSnapshot();
2212
+ errorSignal.set(snapshot.error);
2213
+ isLoadingSignal.set(snapshot.isLoading);
2214
+ reportSignal.set(snapshot.report);
2215
+ updatedAtSignal.set(snapshot.updatedAt);
2216
+ };
2217
+ const unsubscribe = store.subscribe(sync);
2218
+ sync();
2219
+ store.refresh().catch(() => {});
2220
+ return {
2221
+ close: () => {
2222
+ unsubscribe();
2223
+ store.close();
2224
+ },
2225
+ error: computed7(() => errorSignal()),
2226
+ isLoading: computed7(() => isLoadingSignal()),
2227
+ refresh: store.refresh,
2228
+ report: computed7(() => reportSignal()),
2229
+ updatedAt: computed7(() => updatedAtSignal())
2230
+ };
2231
+ }
2232
+ }
2233
+ VoiceTraceTimelineService = __decorateElement(_init, 0, "VoiceTraceTimelineService", _dec, VoiceTraceTimelineService);
2234
+ __runInitializers(_init, 1, VoiceTraceTimelineService);
2235
+ __decoratorMetadata(_init, VoiceTraceTimelineService);
2236
+ let _VoiceTraceTimelineService = VoiceTraceTimelineService;
2237
+ // src/angular/voice-turn-latency.service.ts
2238
+ import { computed as computed8, Injectable as Injectable9, signal as signal9 } from "@angular/core";
2239
+
2240
+ // src/client/turnLatency.ts
2241
+ var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
2242
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2243
+ const response = await fetchImpl(path);
2244
+ if (!response.ok) {
2245
+ throw new Error(`Voice turn latency failed: HTTP ${response.status}`);
2246
+ }
2247
+ return await response.json();
2248
+ };
2249
+ var runVoiceTurnLatencyProof = async (path, options = {}) => {
2250
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2251
+ const response = await fetchImpl(path, { method: "POST" });
2252
+ if (!response.ok) {
2253
+ throw new Error(`Voice turn latency proof failed: HTTP ${response.status}`);
2254
+ }
2255
+ return response.json();
2256
+ };
2257
+ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) => {
2258
+ const listeners = new Set;
2259
+ let closed = false;
2260
+ let timer;
2261
+ let snapshot = {
2262
+ error: null,
2263
+ isLoading: false
2264
+ };
2265
+ const emit = () => {
2266
+ for (const listener of listeners) {
2267
+ listener();
2268
+ }
2269
+ };
2270
+ const refresh = async () => {
2271
+ if (closed) {
2272
+ return snapshot.report;
2273
+ }
2274
+ snapshot = { ...snapshot, error: null, isLoading: true };
2275
+ emit();
2276
+ try {
2277
+ const report = await fetchVoiceTurnLatency(path, options);
2278
+ snapshot = {
2279
+ error: null,
2280
+ isLoading: false,
2281
+ report,
2282
+ updatedAt: Date.now()
2283
+ };
2284
+ emit();
2285
+ return report;
2286
+ } catch (error) {
2287
+ snapshot = {
2288
+ ...snapshot,
2289
+ error: error instanceof Error ? error.message : String(error),
2290
+ isLoading: false
2291
+ };
2292
+ emit();
2293
+ throw error;
2294
+ }
2295
+ };
2296
+ const runProof = async () => {
2297
+ if (!options.proofPath) {
2298
+ throw new Error("Voice turn latency proof path is not configured.");
2299
+ }
2300
+ snapshot = { ...snapshot, error: null, isLoading: true };
2301
+ emit();
2302
+ try {
2303
+ await runVoiceTurnLatencyProof(options.proofPath, options);
2304
+ return await refresh();
2305
+ } catch (error) {
2306
+ snapshot = {
2307
+ ...snapshot,
2308
+ error: error instanceof Error ? error.message : String(error),
2309
+ isLoading: false
2310
+ };
2311
+ emit();
2312
+ throw error;
2313
+ }
2314
+ };
2315
+ const close = () => {
2316
+ closed = true;
2317
+ if (timer) {
2318
+ clearInterval(timer);
2319
+ timer = undefined;
2320
+ }
2321
+ listeners.clear();
2322
+ };
2323
+ if (options.intervalMs && options.intervalMs > 0) {
2324
+ timer = setInterval(() => {
2325
+ refresh().catch(() => {});
2326
+ }, options.intervalMs);
2327
+ }
2328
+ return {
2329
+ close,
2330
+ getServerSnapshot: () => snapshot,
2331
+ getSnapshot: () => snapshot,
2332
+ refresh,
2333
+ runProof,
2334
+ subscribe: (listener) => {
2335
+ listeners.add(listener);
2336
+ return () => {
2337
+ listeners.delete(listener);
2338
+ };
2339
+ }
2340
+ };
2341
+ };
2342
+
2343
+ // src/angular/voice-turn-latency.service.ts
2344
+ var _dec = [
2345
+ Injectable9({ providedIn: "root" })
2346
+ ];
2347
+ var _init = __decoratorStart(undefined);
2348
+
2349
+ class VoiceTurnLatencyService {
2350
+ connect(path = "/api/turn-latency", options = {}) {
2351
+ const store = createVoiceTurnLatencyStore(path, options);
2352
+ const errorSignal = signal9(null);
2353
+ const isLoadingSignal = signal9(false);
2354
+ const reportSignal = signal9(undefined);
2355
+ const updatedAtSignal = signal9(undefined);
2356
+ const sync = () => {
2357
+ const snapshot = store.getSnapshot();
2358
+ errorSignal.set(snapshot.error);
2359
+ isLoadingSignal.set(snapshot.isLoading);
2360
+ reportSignal.set(snapshot.report);
2361
+ updatedAtSignal.set(snapshot.updatedAt);
2362
+ };
2363
+ const unsubscribe = store.subscribe(sync);
2364
+ sync();
2365
+ store.refresh().catch(() => {});
2366
+ return {
2367
+ close: () => {
2368
+ unsubscribe();
2369
+ store.close();
2370
+ },
2371
+ error: computed8(() => errorSignal()),
2372
+ isLoading: computed8(() => isLoadingSignal()),
2373
+ refresh: store.refresh,
2374
+ report: computed8(() => reportSignal()),
2375
+ runProof: store.runProof,
2376
+ updatedAt: computed8(() => updatedAtSignal())
2377
+ };
2378
+ }
2379
+ }
2380
+ VoiceTurnLatencyService = __decorateElement(_init, 0, "VoiceTurnLatencyService", _dec, VoiceTurnLatencyService);
2381
+ __runInitializers(_init, 1, VoiceTurnLatencyService);
2382
+ __decoratorMetadata(_init, VoiceTurnLatencyService);
2383
+ let _VoiceTurnLatencyService = VoiceTurnLatencyService;
2384
+ // src/angular/voice-turn-quality.service.ts
2385
+ import { computed as computed9, Injectable as Injectable10, signal as signal10 } from "@angular/core";
2386
+
2387
+ // src/client/turnQuality.ts
2388
+ var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
2389
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2390
+ const response = await fetchImpl(path);
2391
+ if (!response.ok) {
2392
+ throw new Error(`Voice turn quality failed: HTTP ${response.status}`);
2393
+ }
2394
+ return await response.json();
2395
+ };
2396
+ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) => {
2397
+ const listeners = new Set;
2398
+ let closed = false;
2399
+ let timer;
2400
+ let snapshot = {
2401
+ error: null,
2402
+ isLoading: false
2403
+ };
2404
+ const emit = () => {
2405
+ for (const listener of listeners) {
2406
+ listener();
2407
+ }
2408
+ };
2409
+ const refresh = async () => {
2410
+ if (closed) {
2411
+ return snapshot.report;
2412
+ }
2413
+ snapshot = {
2414
+ ...snapshot,
2415
+ error: null,
2416
+ isLoading: true
2417
+ };
2418
+ emit();
2419
+ try {
2420
+ const report = await fetchVoiceTurnQuality(path, options);
2421
+ snapshot = {
2422
+ error: null,
2423
+ isLoading: false,
2424
+ report,
2425
+ updatedAt: Date.now()
2426
+ };
2427
+ emit();
2428
+ return report;
2429
+ } catch (error) {
2430
+ snapshot = {
2431
+ ...snapshot,
2432
+ error: error instanceof Error ? error.message : String(error),
2433
+ isLoading: false
2434
+ };
2435
+ emit();
2436
+ throw error;
2437
+ }
2438
+ };
2439
+ const close = () => {
2440
+ closed = true;
2441
+ if (timer) {
2442
+ clearInterval(timer);
2443
+ timer = undefined;
2444
+ }
2445
+ listeners.clear();
2446
+ };
2447
+ if (options.intervalMs && options.intervalMs > 0) {
2448
+ timer = setInterval(() => {
2449
+ refresh().catch(() => {});
2450
+ }, options.intervalMs);
2451
+ }
2452
+ return {
2453
+ close,
2454
+ getServerSnapshot: () => snapshot,
2455
+ getSnapshot: () => snapshot,
2456
+ refresh,
2457
+ subscribe: (listener) => {
2458
+ listeners.add(listener);
2459
+ return () => {
2460
+ listeners.delete(listener);
2461
+ };
2462
+ }
2463
+ };
2464
+ };
2465
+
2466
+ // src/angular/voice-turn-quality.service.ts
2467
+ var _dec = [
2468
+ Injectable10({ providedIn: "root" })
2469
+ ];
2470
+ var _init = __decoratorStart(undefined);
2471
+
2472
+ class VoiceTurnQualityService {
2473
+ connect(path = "/api/turn-quality", options = {}) {
2474
+ const store = createVoiceTurnQualityStore(path, options);
2475
+ const errorSignal = signal10(null);
2476
+ const isLoadingSignal = signal10(false);
2477
+ const reportSignal = signal10(undefined);
2478
+ const updatedAtSignal = signal10(undefined);
2479
+ const sync = () => {
2480
+ const snapshot = store.getSnapshot();
2481
+ errorSignal.set(snapshot.error);
2482
+ isLoadingSignal.set(snapshot.isLoading);
2483
+ reportSignal.set(snapshot.report);
2484
+ updatedAtSignal.set(snapshot.updatedAt);
2485
+ };
2486
+ const unsubscribe = store.subscribe(sync);
2487
+ sync();
2488
+ store.refresh().catch(() => {});
2489
+ return {
2490
+ close: () => {
2491
+ unsubscribe();
2492
+ store.close();
2493
+ },
2494
+ error: computed9(() => errorSignal()),
2495
+ isLoading: computed9(() => isLoadingSignal()),
2496
+ refresh: store.refresh,
2497
+ report: computed9(() => reportSignal()),
2498
+ updatedAt: computed9(() => updatedAtSignal())
2499
+ };
2500
+ }
2501
+ }
2502
+ VoiceTurnQualityService = __decorateElement(_init, 0, "VoiceTurnQualityService", _dec, VoiceTurnQualityService);
2503
+ __runInitializers(_init, 1, VoiceTurnQualityService);
2504
+ __decoratorMetadata(_init, VoiceTurnQualityService);
2505
+ let _VoiceTurnQualityService = VoiceTurnQualityService;
2506
+ // src/angular/voice-workflow-status.service.ts
2507
+ import { computed as computed10, Injectable as Injectable11, signal as signal11 } from "@angular/core";
2508
+
2509
+ // src/client/workflowStatus.ts
2510
+ var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
2511
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2512
+ const response = await fetchImpl(path);
2513
+ if (!response.ok) {
2514
+ throw new Error(`Voice workflow status failed: HTTP ${response.status}`);
2515
+ }
2516
+ return await response.json();
2517
+ };
2518
+ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options = {}) => {
2519
+ const listeners = new Set;
2520
+ let closed = false;
2521
+ let timer;
2522
+ let snapshot = {
2523
+ error: null,
2524
+ isLoading: false
2525
+ };
2526
+ const emit = () => {
2527
+ for (const listener of listeners) {
2528
+ listener();
2529
+ }
2530
+ };
2531
+ const refresh = async () => {
2532
+ if (closed) {
2533
+ return snapshot.report;
2534
+ }
2535
+ snapshot = {
2536
+ ...snapshot,
2537
+ error: null,
2538
+ isLoading: true
2539
+ };
2540
+ emit();
2541
+ try {
2542
+ const report = await fetchVoiceWorkflowStatus(path, options);
2543
+ snapshot = {
2544
+ error: null,
2545
+ isLoading: false,
2546
+ report,
2547
+ updatedAt: Date.now()
2548
+ };
2549
+ emit();
2550
+ return report;
2551
+ } catch (error) {
2552
+ snapshot = {
2553
+ ...snapshot,
2554
+ error: error instanceof Error ? error.message : String(error),
2555
+ isLoading: false
2556
+ };
2557
+ emit();
2558
+ throw error;
2559
+ }
2560
+ };
2561
+ const close = () => {
2562
+ closed = true;
2563
+ if (timer) {
2564
+ clearInterval(timer);
2565
+ timer = undefined;
2566
+ }
2567
+ listeners.clear();
2568
+ };
2569
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
2570
+ timer = setInterval(() => {
2571
+ refresh().catch(() => {});
2572
+ }, options.intervalMs);
2573
+ }
2574
+ return {
2575
+ close,
2576
+ getServerSnapshot: () => snapshot,
2577
+ getSnapshot: () => snapshot,
2578
+ refresh,
2579
+ subscribe: (listener) => {
2580
+ listeners.add(listener);
2581
+ return () => {
2582
+ listeners.delete(listener);
2583
+ };
2584
+ }
2585
+ };
2586
+ };
2587
+
2588
+ // src/angular/voice-workflow-status.service.ts
2589
+ var _dec = [
2590
+ Injectable11({ providedIn: "root" })
2591
+ ];
2592
+ var _init = __decoratorStart(undefined);
2593
+
2594
+ class VoiceWorkflowStatusService {
2595
+ connect(path = "/evals/scenarios/json", options = {}) {
2596
+ const store = createVoiceWorkflowStatusStore(path, options);
2597
+ const errorSignal = signal11(null);
2598
+ const isLoadingSignal = signal11(false);
2599
+ const reportSignal = signal11(undefined);
2600
+ const updatedAtSignal = signal11(undefined);
2601
+ const sync = () => {
2602
+ const snapshot = store.getSnapshot();
2603
+ errorSignal.set(snapshot.error);
2604
+ isLoadingSignal.set(snapshot.isLoading);
2605
+ reportSignal.set(snapshot.report);
2606
+ updatedAtSignal.set(snapshot.updatedAt);
2607
+ };
2608
+ const unsubscribe = store.subscribe(sync);
2609
+ sync();
2610
+ if (typeof window !== "undefined") {
2611
+ store.refresh().catch(() => {});
2612
+ }
2613
+ return {
2614
+ close: () => {
2615
+ unsubscribe();
2616
+ store.close();
2617
+ },
2618
+ error: computed10(() => errorSignal()),
2619
+ isLoading: computed10(() => isLoadingSignal()),
2620
+ refresh: store.refresh,
2621
+ report: computed10(() => reportSignal()),
2622
+ updatedAt: computed10(() => updatedAtSignal())
2623
+ };
2624
+ }
2625
+ }
2626
+ VoiceWorkflowStatusService = __decorateElement(_init, 0, "VoiceWorkflowStatusService", _dec, VoiceWorkflowStatusService);
2627
+ __runInitializers(_init, 1, VoiceWorkflowStatusService);
2628
+ __decoratorMetadata(_init, VoiceWorkflowStatusService);
2629
+ let _VoiceWorkflowStatusService = VoiceWorkflowStatusService;
1291
2630
  export {
2631
+ VoiceWorkflowStatusService,
2632
+ VoiceTurnQualityService,
2633
+ VoiceTurnLatencyService,
2634
+ VoiceTraceTimelineService,
1292
2635
  VoiceStreamService,
1293
- VoiceControllerService
2636
+ VoiceRoutingStatusService,
2637
+ VoiceProviderStatusService,
2638
+ VoiceProviderCapabilitiesService,
2639
+ VoiceOpsStatusService,
2640
+ VoiceControllerService,
2641
+ VoiceCampaignDialerProofService
1294
2642
  };