@absolutejs/voice 0.0.22-beta.50 → 0.0.22-beta.501

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 (400) hide show
  1. package/README.md +4556 -603
  2. package/dist/agent.d.ts +79 -5
  3. package/dist/agentSquadContract.d.ts +98 -0
  4. package/dist/agentState.d.ts +12 -0
  5. package/dist/agentTools.d.ts +133 -0
  6. package/dist/aiVoiceModel.d.ts +15 -0
  7. package/dist/amdDetector.d.ts +25 -0
  8. package/dist/angular/index.d.ts +32 -5
  9. package/dist/angular/index.js +3704 -326
  10. package/dist/angular/voice-agent-squad-status.service.d.ts +12 -0
  11. package/dist/angular/voice-call-debugger.service.d.ts +12 -0
  12. package/dist/angular/voice-campaign-dialer-proof.service.d.ts +14 -0
  13. package/dist/angular/voice-controller.service.d.ts +3 -1
  14. package/dist/angular/voice-cost-dashboard.service.d.ts +15 -0
  15. package/dist/angular/voice-delivery-runtime.component.d.ts +17 -0
  16. package/dist/angular/voice-delivery-runtime.service.d.ts +16 -0
  17. package/dist/angular/voice-live-call-viewer.service.d.ts +16 -0
  18. package/dist/angular/voice-live-ops.service.d.ts +11 -0
  19. package/dist/angular/voice-ops-action-center.service.d.ts +13 -0
  20. package/dist/angular/voice-ops-status.component.d.ts +15 -0
  21. package/dist/angular/voice-ops-status.service.d.ts +12 -0
  22. package/dist/angular/voice-platform-coverage.service.d.ts +12 -0
  23. package/dist/angular/voice-profile-comparison.service.d.ts +12 -0
  24. package/dist/angular/voice-proof-trends.service.d.ts +12 -0
  25. package/dist/angular/voice-provider-capabilities.service.d.ts +12 -0
  26. package/dist/angular/voice-provider-contracts.service.d.ts +12 -0
  27. package/dist/angular/voice-provider-status.service.d.ts +2 -2
  28. package/dist/angular/voice-readiness-failures.service.d.ts +13 -0
  29. package/dist/angular/voice-reconnect-profile-evidence.service.d.ts +12 -0
  30. package/dist/angular/voice-replay-timeline.service.d.ts +13 -0
  31. package/dist/angular/voice-routing-status.service.d.ts +11 -0
  32. package/dist/angular/voice-session-observability.service.d.ts +12 -0
  33. package/dist/angular/voice-session-snapshot.service.d.ts +13 -0
  34. package/dist/angular/voice-stream.service.d.ts +4 -1
  35. package/dist/angular/voice-trace-timeline.service.d.ts +12 -0
  36. package/dist/angular/voice-turn-latency.service.d.ts +13 -0
  37. package/dist/angular/voice-turn-quality.service.d.ts +12 -0
  38. package/dist/angular/voice-widget.service.d.ts +18 -0
  39. package/dist/angular/voice-workflow-status.service.d.ts +2 -2
  40. package/dist/assistant.d.ts +12 -13
  41. package/dist/assistantHealth.d.ts +6 -6
  42. package/dist/assistantMemory.d.ts +3 -3
  43. package/dist/assistantMode.d.ts +22 -0
  44. package/dist/audioConditioning.d.ts +1 -1
  45. package/dist/audit.d.ts +131 -0
  46. package/dist/auditDeliveryRoutes.d.ts +85 -0
  47. package/dist/auditExport.d.ts +34 -0
  48. package/dist/auditRoutes.d.ts +66 -0
  49. package/dist/auditSinks.d.ts +151 -0
  50. package/dist/backchannel.d.ts +18 -0
  51. package/dist/bargeInRoutes.d.ts +56 -0
  52. package/dist/browserCallProfiles.d.ts +120 -0
  53. package/dist/browserMediaRoutes.d.ts +62 -0
  54. package/dist/callDebugger.d.ts +66 -0
  55. package/dist/callQuota.d.ts +54 -0
  56. package/dist/callerMemory.d.ts +37 -0
  57. package/dist/campaign.d.ts +794 -0
  58. package/dist/campaignControls.d.ts +37 -0
  59. package/dist/campaignDialers.d.ts +111 -0
  60. package/dist/client/actions.d.ts +95 -1
  61. package/dist/client/agentSquadStatus.d.ts +37 -0
  62. package/dist/client/agentSquadStatusWidget.d.ts +24 -0
  63. package/dist/client/audioPlayer.d.ts +2 -2
  64. package/dist/client/bargeInMonitor.d.ts +7 -0
  65. package/dist/client/browserMedia.d.ts +8 -0
  66. package/dist/client/callDebugger.d.ts +19 -0
  67. package/dist/client/callDebuggerWidget.d.ts +30 -0
  68. package/dist/client/campaignDialerProof.d.ts +23 -0
  69. package/dist/client/connection.d.ts +4 -3
  70. package/dist/client/controller.d.ts +1 -1
  71. package/dist/client/costDashboard.d.ts +27 -0
  72. package/dist/client/createVoiceStream.d.ts +1 -1
  73. package/dist/client/deliveryRuntime.d.ts +34 -0
  74. package/dist/client/deliveryRuntimeWidget.d.ts +37 -0
  75. package/dist/client/duplex.d.ts +2 -2
  76. package/dist/client/htmx.d.ts +1 -1
  77. package/dist/client/htmxBootstrap.js +967 -14
  78. package/dist/client/index.d.ts +104 -13
  79. package/dist/client/index.js +10142 -26
  80. package/dist/client/liveCallViewer.d.ts +42 -0
  81. package/dist/client/liveOps.d.ts +22 -0
  82. package/dist/client/liveOpsWidget.d.ts +23 -0
  83. package/dist/client/liveTurnLatency.d.ts +41 -0
  84. package/dist/client/microphone.d.ts +4 -4
  85. package/dist/client/opsActionCenter.d.ts +54 -0
  86. package/dist/client/opsActionCenterWidget.d.ts +29 -0
  87. package/dist/client/opsActionHistory.d.ts +19 -0
  88. package/dist/client/opsActionHistoryWidget.d.ts +11 -0
  89. package/dist/client/opsStatus.d.ts +19 -0
  90. package/dist/client/opsStatusWidget.d.ts +40 -0
  91. package/dist/client/platformCoverage.d.ts +19 -0
  92. package/dist/client/platformCoverageWidget.d.ts +37 -0
  93. package/dist/client/profileComparison.d.ts +19 -0
  94. package/dist/client/profileComparisonWidget.d.ts +41 -0
  95. package/dist/client/profileSwitchRecommendation.d.ts +19 -0
  96. package/dist/client/profileSwitchRecommendationWidget.d.ts +12 -0
  97. package/dist/client/proofTrends.d.ts +19 -0
  98. package/dist/client/proofTrendsWidget.d.ts +37 -0
  99. package/dist/client/providerCapabilities.d.ts +19 -0
  100. package/dist/client/providerCapabilitiesWidget.d.ts +32 -0
  101. package/dist/client/providerContracts.d.ts +19 -0
  102. package/dist/client/providerContractsWidget.d.ts +37 -0
  103. package/dist/client/providerSimulationControls.d.ts +33 -0
  104. package/dist/client/providerSimulationControlsWidget.d.ts +20 -0
  105. package/dist/client/providerStatus.d.ts +1 -1
  106. package/dist/client/providerStatusWidget.d.ts +32 -0
  107. package/dist/client/readinessFailures.d.ts +19 -0
  108. package/dist/client/readinessFailuresWidget.d.ts +42 -0
  109. package/dist/client/reconnectProfileEvidence.d.ts +19 -0
  110. package/dist/client/reconnectProfileEvidenceWidget.d.ts +39 -0
  111. package/dist/client/replayTimeline.d.ts +26 -0
  112. package/dist/client/routingStatus.d.ts +19 -0
  113. package/dist/client/routingStatusWidget.d.ts +32 -0
  114. package/dist/client/sessionObservability.d.ts +19 -0
  115. package/dist/client/sessionObservabilityWidget.d.ts +31 -0
  116. package/dist/client/sessionSnapshot.d.ts +21 -0
  117. package/dist/client/sessionSnapshotWidget.d.ts +33 -0
  118. package/dist/client/store.d.ts +1 -1
  119. package/dist/client/traceTimeline.d.ts +19 -0
  120. package/dist/client/traceTimelineWidget.d.ts +36 -0
  121. package/dist/client/turnLatency.d.ts +22 -0
  122. package/dist/client/turnLatencyWidget.d.ts +33 -0
  123. package/dist/client/turnQuality.d.ts +19 -0
  124. package/dist/client/turnQualityWidget.d.ts +32 -0
  125. package/dist/client/voiceWidgetView.d.ts +50 -0
  126. package/dist/client/workflowStatus.d.ts +1 -1
  127. package/dist/competitiveCoverage.d.ts +141 -0
  128. package/dist/correction.d.ts +2 -2
  129. package/dist/costAccounting.d.ts +76 -0
  130. package/dist/dataControl.d.ts +180 -0
  131. package/dist/defineVoiceAssistant.d.ts +68 -0
  132. package/dist/deliveryRuntime.d.ts +158 -0
  133. package/dist/deliverySinkRoutes.d.ts +117 -0
  134. package/dist/demoReadyRoutes.d.ts +98 -0
  135. package/dist/diagnosticsRoutes.d.ts +2 -2
  136. package/dist/evalRoutes.d.ts +10 -4
  137. package/dist/fileStore.d.ts +21 -7
  138. package/dist/generated/htmxBootstrapBundle.d.ts +1 -0
  139. package/dist/guardrails.d.ts +128 -0
  140. package/dist/handoff.d.ts +6 -6
  141. package/dist/handoffHealth.d.ts +5 -5
  142. package/dist/htmx.d.ts +1 -1
  143. package/dist/incidentBundle.d.ts +119 -0
  144. package/dist/incidentTimeline.d.ts +260 -0
  145. package/dist/index.d.ts +278 -74
  146. package/dist/index.js +40611 -6669
  147. package/dist/ivrPlan.d.ts +40 -0
  148. package/dist/latencySlo.d.ts +56 -0
  149. package/dist/liveLatency.d.ts +78 -0
  150. package/dist/liveOps.d.ts +190 -0
  151. package/dist/llmJudge.d.ts +45 -0
  152. package/dist/logger.d.ts +1 -1
  153. package/dist/mediaPipelineRoutes.d.ts +171 -0
  154. package/dist/mediaPipelineSurfaces.d.ts +48 -0
  155. package/dist/memoryStore.d.ts +1 -1
  156. package/dist/midCallSummary.d.ts +27 -0
  157. package/dist/modelAdapters.d.ts +59 -7
  158. package/dist/monitor.d.ts +148 -0
  159. package/dist/multilingualProof.d.ts +77 -0
  160. package/dist/oauth2TokenSource.d.ts +21 -0
  161. package/dist/observabilityExport.d.ts +501 -0
  162. package/dist/openaiTTS.d.ts +18 -0
  163. package/dist/operationalStatus.d.ts +87 -0
  164. package/dist/operationsRecord.d.ts +370 -0
  165. package/dist/ops.d.ts +12 -12
  166. package/dist/opsActionAuditRoutes.d.ts +99 -0
  167. package/dist/opsConsoleRoutes.d.ts +8 -5
  168. package/dist/opsPresets.d.ts +2 -2
  169. package/dist/opsRecovery.d.ts +137 -0
  170. package/dist/opsRuntime.d.ts +6 -6
  171. package/dist/opsSinks.d.ts +13 -13
  172. package/dist/opsStatus.d.ts +76 -0
  173. package/dist/opsStatusRoutes.d.ts +33 -0
  174. package/dist/opsWebhook.d.ts +6 -6
  175. package/dist/otelExporter.d.ts +83 -0
  176. package/dist/outcomeContract.d.ts +146 -0
  177. package/dist/outcomeRecipes.d.ts +4 -4
  178. package/dist/phoneAgent.d.ts +139 -0
  179. package/dist/phoneAgentProductionSmoke.d.ts +115 -0
  180. package/dist/platformCoverage.d.ts +91 -0
  181. package/dist/plugin.d.ts +2 -2
  182. package/dist/postCallAnalysis.d.ts +98 -0
  183. package/dist/postgresStore.d.ts +17 -6
  184. package/dist/presets.d.ts +3 -3
  185. package/dist/productionReadiness.d.ts +756 -0
  186. package/dist/profileSwitchRecommendation.d.ts +350 -0
  187. package/dist/proofAssertions.d.ts +32 -0
  188. package/dist/proofPack.d.ts +211 -0
  189. package/dist/proofRunner.d.ts +79 -0
  190. package/dist/proofTrends.d.ts +966 -0
  191. package/dist/providerAdapters.d.ts +16 -5
  192. package/dist/providerCapabilities.d.ts +92 -0
  193. package/dist/providerDecisionTraces.d.ts +130 -0
  194. package/dist/providerHealth.d.ts +3 -3
  195. package/dist/providerOrchestration.d.ts +109 -0
  196. package/dist/providerRouterTraces.d.ts +35 -0
  197. package/dist/providerRoutingContract.d.ts +71 -0
  198. package/dist/providerSlo.d.ts +142 -0
  199. package/dist/providerStackRecommendations.d.ts +187 -0
  200. package/dist/qualityRoutes.d.ts +4 -4
  201. package/dist/queue.d.ts +23 -14
  202. package/dist/ragTool.d.ts +57 -0
  203. package/dist/react/VoiceAgentSquadStatus.d.ts +5 -0
  204. package/dist/react/VoiceCallDebuggerLaunch.d.ts +6 -0
  205. package/dist/react/VoiceCostDashboard.d.ts +10 -0
  206. package/dist/react/VoiceDeliveryRuntime.d.ts +7 -0
  207. package/dist/react/VoiceLiveCallViewer.d.ts +9 -0
  208. package/dist/react/VoiceOpsActionCenter.d.ts +5 -0
  209. package/dist/react/VoiceOpsStatus.d.ts +6 -0
  210. package/dist/react/VoicePlatformCoverage.d.ts +6 -0
  211. package/dist/react/VoiceProfileComparison.d.ts +6 -0
  212. package/dist/react/VoiceProfileSwitchRecommendation.d.ts +6 -0
  213. package/dist/react/VoiceProofTrends.d.ts +6 -0
  214. package/dist/react/VoiceProviderCapabilities.d.ts +6 -0
  215. package/dist/react/VoiceProviderContracts.d.ts +6 -0
  216. package/dist/react/VoiceProviderSimulationControls.d.ts +5 -0
  217. package/dist/react/VoiceProviderStatus.d.ts +6 -0
  218. package/dist/react/VoiceReadinessFailures.d.ts +6 -0
  219. package/dist/react/VoiceReconnectProfileEvidence.d.ts +6 -0
  220. package/dist/react/VoiceReplayTimeline.d.ts +6 -0
  221. package/dist/react/VoiceRoutingStatus.d.ts +6 -0
  222. package/dist/react/VoiceSessionObservability.d.ts +6 -0
  223. package/dist/react/VoiceSessionSnapshot.d.ts +6 -0
  224. package/dist/react/VoiceTraceTimeline.d.ts +6 -0
  225. package/dist/react/VoiceTurnLatency.d.ts +6 -0
  226. package/dist/react/VoiceTurnQuality.d.ts +6 -0
  227. package/dist/react/VoiceWidget.d.ts +13 -0
  228. package/dist/react/index.d.ts +55 -5
  229. package/dist/react/index.js +12037 -106
  230. package/dist/react/useVoiceAgentSquadStatus.d.ts +8 -0
  231. package/dist/react/useVoiceCallDebugger.d.ts +8 -0
  232. package/dist/react/useVoiceCampaignDialerProof.d.ts +10 -0
  233. package/dist/react/useVoiceController.d.ts +4 -1
  234. package/dist/react/useVoiceDeliveryRuntime.d.ts +13 -0
  235. package/dist/react/useVoiceLiveOps.d.ts +9 -0
  236. package/dist/react/useVoiceOpsActionCenter.d.ts +11 -0
  237. package/dist/react/useVoiceOpsStatus.d.ts +8 -0
  238. package/dist/react/useVoicePlatformCoverage.d.ts +8 -0
  239. package/dist/react/useVoiceProfileComparison.d.ts +8 -0
  240. package/dist/react/useVoiceProfileSwitchRecommendation.d.ts +8 -0
  241. package/dist/react/useVoiceProofTrends.d.ts +8 -0
  242. package/dist/react/useVoiceProviderCapabilities.d.ts +8 -0
  243. package/dist/react/useVoiceProviderContracts.d.ts +8 -0
  244. package/dist/react/useVoiceProviderSimulationControls.d.ts +10 -0
  245. package/dist/react/useVoiceProviderStatus.d.ts +1 -1
  246. package/dist/react/useVoiceReadinessFailures.d.ts +8 -0
  247. package/dist/react/useVoiceReconnectProfileEvidence.d.ts +8 -0
  248. package/dist/react/useVoiceRoutingStatus.d.ts +8 -0
  249. package/dist/react/useVoiceSessionObservability.d.ts +8 -0
  250. package/dist/react/useVoiceSessionSnapshot.d.ts +9 -0
  251. package/dist/react/useVoiceStream.d.ts +4 -1
  252. package/dist/react/useVoiceTraceTimeline.d.ts +8 -0
  253. package/dist/react/useVoiceTurnLatency.d.ts +9 -0
  254. package/dist/react/useVoiceTurnQuality.d.ts +8 -0
  255. package/dist/react/useVoiceWorkflowStatus.d.ts +1 -1
  256. package/dist/readinessProfiles.d.ts +45 -0
  257. package/dist/realtimeChannel.d.ts +136 -0
  258. package/dist/realtimeProviderContracts.d.ts +133 -0
  259. package/dist/reconnectContract.d.ts +176 -0
  260. package/dist/recordingRedaction.d.ts +18 -0
  261. package/dist/recordingStore.d.ts +60 -0
  262. package/dist/redaction.d.ts +13 -0
  263. package/dist/resilienceRoutes.d.ts +45 -5
  264. package/dist/retention.d.ts +37 -0
  265. package/dist/routeAuth.d.ts +58 -0
  266. package/dist/routing.d.ts +1 -1
  267. package/dist/runtimeOps.d.ts +3 -3
  268. package/dist/s3Store.d.ts +18 -3
  269. package/dist/semanticTurn.d.ts +27 -0
  270. package/dist/session.d.ts +1 -1
  271. package/dist/sessionObservability.d.ts +145 -0
  272. package/dist/sessionReplay.d.ts +19 -7
  273. package/dist/sessionSnapshot.d.ts +109 -0
  274. package/dist/simulationSuite.d.ts +143 -0
  275. package/dist/sloCalibration.d.ts +185 -0
  276. package/dist/sqliteStore.d.ts +17 -6
  277. package/dist/store.d.ts +1 -1
  278. package/dist/svelte/createVoiceAgentSquadStatus.d.ts +9 -0
  279. package/dist/svelte/createVoiceCallDebugger.d.ts +12 -0
  280. package/dist/svelte/createVoiceCampaignDialerProof.d.ts +9 -0
  281. package/dist/svelte/createVoiceCostDashboard.d.ts +13 -0
  282. package/dist/svelte/createVoiceDeliveryRuntime.d.ts +11 -0
  283. package/dist/svelte/createVoiceLiveCallViewer.d.ts +26 -0
  284. package/dist/svelte/createVoiceLiveOps.d.ts +13 -0
  285. package/dist/svelte/createVoiceOpsActionCenter.d.ts +10 -0
  286. package/dist/svelte/createVoiceOpsStatus.d.ts +9 -0
  287. package/dist/svelte/createVoicePlatformCoverage.d.ts +7 -0
  288. package/dist/svelte/createVoiceProfileComparison.d.ts +7 -0
  289. package/dist/svelte/createVoiceProofTrends.d.ts +7 -0
  290. package/dist/svelte/createVoiceProviderCapabilities.d.ts +10 -0
  291. package/dist/svelte/createVoiceProviderContracts.d.ts +10 -0
  292. package/dist/svelte/createVoiceProviderSimulationControls.d.ts +11 -0
  293. package/dist/svelte/createVoiceProviderStatus.d.ts +4 -2
  294. package/dist/svelte/createVoiceReadinessFailures.d.ts +7 -0
  295. package/dist/svelte/createVoiceReconnectProfileEvidence.d.ts +7 -0
  296. package/dist/svelte/createVoiceReplayTimeline.d.ts +13 -0
  297. package/dist/svelte/createVoiceRoutingStatus.d.ts +10 -0
  298. package/dist/svelte/createVoiceSessionObservability.d.ts +10 -0
  299. package/dist/svelte/createVoiceSessionSnapshot.d.ts +13 -0
  300. package/dist/svelte/createVoiceStream.d.ts +1 -1
  301. package/dist/svelte/createVoiceTraceTimeline.d.ts +10 -0
  302. package/dist/svelte/createVoiceTurnLatency.d.ts +11 -0
  303. package/dist/svelte/createVoiceTurnQuality.d.ts +10 -0
  304. package/dist/svelte/createVoiceWidget.d.ts +19 -0
  305. package/dist/svelte/createVoiceWorkflowStatus.d.ts +1 -1
  306. package/dist/svelte/index.d.ts +33 -5
  307. package/dist/svelte/index.js +6493 -546
  308. package/dist/telephony/contract.d.ts +61 -0
  309. package/dist/telephony/matrix.d.ts +97 -0
  310. package/dist/telephony/plivo.d.ts +303 -0
  311. package/dist/telephony/response.d.ts +1 -1
  312. package/dist/telephony/security.d.ts +182 -0
  313. package/dist/telephony/telnyx.d.ts +291 -0
  314. package/dist/telephony/twilio.d.ts +147 -13
  315. package/dist/telephonyMediaRoutes.d.ts +72 -0
  316. package/dist/telephonyOutcome.d.ts +273 -0
  317. package/dist/testing/accuracy.d.ts +1 -1
  318. package/dist/testing/benchmark.d.ts +9 -9
  319. package/dist/testing/corrected.d.ts +5 -5
  320. package/dist/testing/duplex.d.ts +3 -3
  321. package/dist/testing/fixtures.d.ts +3 -3
  322. package/dist/testing/index.d.ts +13 -13
  323. package/dist/testing/index.js +5223 -159
  324. package/dist/testing/ioProviderSimulator.d.ts +5 -5
  325. package/dist/testing/providerSimulator.d.ts +5 -5
  326. package/dist/testing/review.d.ts +4 -4
  327. package/dist/testing/sessionBenchmark.d.ts +3 -3
  328. package/dist/testing/stt.d.ts +3 -3
  329. package/dist/testing/telephony.d.ts +25 -0
  330. package/dist/testing/tts.d.ts +1 -1
  331. package/dist/toolContract.d.ts +161 -0
  332. package/dist/toolRuntime.d.ts +50 -0
  333. package/dist/trace.d.ts +46 -7
  334. package/dist/traceDeliveryRoutes.d.ts +86 -0
  335. package/dist/traceTimeline.d.ts +97 -0
  336. package/dist/turnDetection.d.ts +1 -1
  337. package/dist/turnLatency.d.ts +95 -0
  338. package/dist/turnProfiles.d.ts +2 -2
  339. package/dist/turnQuality.d.ts +94 -0
  340. package/dist/types.d.ts +293 -80
  341. package/dist/vapiAdapter.d.ts +160 -0
  342. package/dist/voiceMonitoring.d.ts +444 -0
  343. package/dist/vue/VoiceCallDebuggerLaunch.d.ts +68 -0
  344. package/dist/vue/VoiceCostDashboard.d.ts +57 -0
  345. package/dist/vue/VoiceDeliveryRuntime.d.ts +30 -0
  346. package/dist/vue/VoiceLiveCallViewer.d.ts +35 -0
  347. package/dist/vue/VoiceOpsActionCenter.d.ts +13 -0
  348. package/dist/vue/VoiceOpsStatus.d.ts +30 -0
  349. package/dist/vue/VoicePlatformCoverage.d.ts +23 -0
  350. package/dist/vue/VoiceProofTrends.d.ts +21 -0
  351. package/dist/vue/VoiceProviderCapabilities.d.ts +51 -0
  352. package/dist/vue/VoiceProviderContracts.d.ts +21 -0
  353. package/dist/vue/VoiceProviderSimulationControls.d.ts +88 -0
  354. package/dist/vue/VoiceProviderStatus.d.ts +51 -0
  355. package/dist/vue/VoiceReadinessFailures.d.ts +21 -0
  356. package/dist/vue/VoiceReconnectProfileEvidence.d.ts +21 -0
  357. package/dist/vue/VoiceReplayTimeline.d.ts +17 -0
  358. package/dist/vue/VoiceRoutingStatus.d.ts +51 -0
  359. package/dist/vue/VoiceSessionObservability.d.ts +23 -0
  360. package/dist/vue/VoiceSessionSnapshot.d.ts +68 -0
  361. package/dist/vue/VoiceTurnLatency.d.ts +69 -0
  362. package/dist/vue/VoiceTurnQuality.d.ts +51 -0
  363. package/dist/vue/VoiceWidget.d.ts +77 -0
  364. package/dist/vue/index.d.ts +47 -5
  365. package/dist/vue/index.js +11299 -132
  366. package/dist/vue/useVoiceAgentSquadStatus.d.ts +9 -0
  367. package/dist/vue/useVoiceCallDebugger.d.ts +10 -0
  368. package/dist/vue/useVoiceCampaignDialerProof.d.ts +11 -0
  369. package/dist/vue/useVoiceController.d.ts +4 -2
  370. package/dist/vue/useVoiceDeliveryRuntime.d.ts +13 -0
  371. package/dist/vue/useVoiceLiveOps.d.ts +9 -0
  372. package/dist/vue/useVoiceOpsActionCenter.d.ts +11 -0
  373. package/dist/vue/useVoiceOpsStatus.d.ts +9 -0
  374. package/dist/vue/useVoicePlatformCoverage.d.ts +9 -0
  375. package/dist/vue/useVoiceProfileComparison.d.ts +9 -0
  376. package/dist/vue/useVoiceProofTrends.d.ts +9 -0
  377. package/dist/vue/useVoiceProviderCapabilities.d.ts +9 -0
  378. package/dist/vue/useVoiceProviderContracts.d.ts +9 -0
  379. package/dist/vue/useVoiceProviderSimulationControls.d.ts +24 -0
  380. package/dist/vue/useVoiceProviderStatus.d.ts +3 -3
  381. package/dist/vue/useVoiceReadinessFailures.d.ts +959 -0
  382. package/dist/vue/useVoiceReconnectProfileEvidence.d.ts +9 -0
  383. package/dist/vue/useVoiceRoutingStatus.d.ts +8 -0
  384. package/dist/vue/useVoiceSessionObservability.d.ts +9 -0
  385. package/dist/vue/useVoiceSessionSnapshot.d.ts +10 -0
  386. package/dist/vue/useVoiceStream.d.ts +5 -2
  387. package/dist/vue/useVoiceTraceTimeline.d.ts +9 -0
  388. package/dist/vue/useVoiceTurnLatency.d.ts +10 -0
  389. package/dist/vue/useVoiceTurnQuality.d.ts +9 -0
  390. package/dist/vue/useVoiceWorkflowStatus.d.ts +3 -3
  391. package/dist/webhookVerification.d.ts +27 -0
  392. package/dist/workflowContract.d.ts +8 -8
  393. package/fixtures/manifest.json +356 -197
  394. package/package.json +265 -256
  395. package/dist/angular/voice-app-kit-status.service.d.ts +0 -12
  396. package/dist/appKit.d.ts +0 -83
  397. package/dist/client/appKitStatus.d.ts +0 -19
  398. package/dist/react/useVoiceAppKitStatus.d.ts +0 -8
  399. package/dist/svelte/createVoiceAppKitStatus.d.ts +0 -8
  400. package/dist/vue/useVoiceAppKitStatus.d.ts +0 -9
@@ -68,20 +68,21 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
68
68
  }
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
+ var __require = import.meta.require;
71
72
 
72
- // src/angular/voice-app-kit-status.service.ts
73
+ // src/angular/voice-ops-status.service.ts
73
74
  import { computed, Injectable, signal } from "@angular/core";
74
75
 
75
- // src/client/appKitStatus.ts
76
- var fetchVoiceAppKitStatus = async (path = "/app-kit/status", options = {}) => {
76
+ // src/client/opsStatus.ts
77
+ var fetchVoiceOpsStatus = async (path = "/api/voice/ops-status", options = {}) => {
77
78
  const fetchImpl = options.fetch ?? globalThis.fetch;
78
79
  const response = await fetchImpl(path);
79
80
  if (!response.ok) {
80
- throw new Error(`Voice app kit status failed: HTTP ${response.status}`);
81
+ throw new Error(`Voice ops status failed: HTTP ${response.status}`);
81
82
  }
82
83
  return await response.json();
83
84
  };
84
- var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
85
+ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) => {
85
86
  const listeners = new Set;
86
87
  let closed = false;
87
88
  let timer;
@@ -105,7 +106,7 @@ var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
105
106
  };
106
107
  emit();
107
108
  try {
108
- const report = await fetchVoiceAppKitStatus(path, options);
109
+ const report = await fetchVoiceOpsStatus(path, options);
109
110
  snapshot = {
110
111
  error: null,
111
112
  isLoading: false,
@@ -151,15 +152,15 @@ var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
151
152
  };
152
153
  };
153
154
 
154
- // src/angular/voice-app-kit-status.service.ts
155
+ // src/angular/voice-ops-status.service.ts
155
156
  var _dec = [
156
157
  Injectable({ providedIn: "root" })
157
158
  ];
158
159
  var _init = __decoratorStart(undefined);
159
160
 
160
- class VoiceAppKitStatusService {
161
- connect(path = "/app-kit/status", options = {}) {
162
- const store = createVoiceAppKitStatusStore(path, options);
161
+ class VoiceOpsStatusService {
162
+ connect(path = "/api/voice/ops-status", options = {}) {
163
+ const store = createVoiceOpsStatusStore(path, options);
163
164
  const errorSignal = signal(null);
164
165
  const isLoadingSignal = signal(false);
165
166
  const reportSignal = signal(undefined);
@@ -189,13 +190,155 @@ class VoiceAppKitStatusService {
189
190
  };
190
191
  }
191
192
  }
192
- VoiceAppKitStatusService = __decorateElement(_init, 0, "VoiceAppKitStatusService", _dec, VoiceAppKitStatusService);
193
- __runInitializers(_init, 1, VoiceAppKitStatusService);
194
- __decoratorMetadata(_init, VoiceAppKitStatusService);
195
- let _VoiceAppKitStatusService = VoiceAppKitStatusService;
196
- // src/angular/voice-stream.service.ts
193
+ VoiceOpsStatusService = __decorateElement(_init, 0, "VoiceOpsStatusService", _dec, VoiceOpsStatusService);
194
+ __runInitializers(_init, 1, VoiceOpsStatusService);
195
+ __decoratorMetadata(_init, VoiceOpsStatusService);
196
+ let _VoiceOpsStatusService = VoiceOpsStatusService;
197
+ // src/angular/voice-widget.service.ts
197
198
  import { computed as computed2, Injectable as Injectable2, signal as signal2 } from "@angular/core";
198
199
 
200
+ // src/client/htmx.ts
201
+ var DEFAULT_EVENT_NAME = "voice-refresh";
202
+ var DEFAULT_QUERY_PARAM = "sessionId";
203
+ var resolveElement = (input) => {
204
+ if (typeof input !== "string") {
205
+ return input;
206
+ }
207
+ return document.querySelector(input);
208
+ };
209
+ var buildRoute = (element, route, queryParam, sessionId) => {
210
+ const baseRoute = route ?? element.getAttribute("hx-get") ?? "";
211
+ if (!baseRoute) {
212
+ return "";
213
+ }
214
+ const url = new URL(baseRoute, window.location.origin);
215
+ if (sessionId) {
216
+ url.searchParams.set(queryParam, sessionId);
217
+ } else {
218
+ url.searchParams.delete(queryParam);
219
+ }
220
+ return `${url.pathname}${url.search}${url.hash}`;
221
+ };
222
+ var bindVoiceHTMX = (stream, options) => {
223
+ if (typeof window === "undefined" || typeof document === "undefined") {
224
+ return () => {};
225
+ }
226
+ const element = resolveElement(options.element);
227
+ if (!element) {
228
+ return () => {};
229
+ }
230
+ const eventName = options.eventName ?? DEFAULT_EVENT_NAME;
231
+ const queryParam = options.sessionQueryParam ?? DEFAULT_QUERY_PARAM;
232
+ const sync = () => {
233
+ const htmxWindow = window;
234
+ const nextRoute = buildRoute(element, options.route, queryParam, stream.sessionId);
235
+ if (nextRoute) {
236
+ element.setAttribute("hx-get", nextRoute);
237
+ }
238
+ htmxWindow.htmx?.process?.(element);
239
+ htmxWindow.htmx?.trigger?.(element, eventName);
240
+ };
241
+ const unsubscribe = stream.subscribe(sync);
242
+ sync();
243
+ return () => {
244
+ unsubscribe();
245
+ };
246
+ };
247
+
248
+ // src/client/microphone.ts
249
+ var clampSample = (value) => Math.max(-1, Math.min(1, value));
250
+ var floatTo16BitPCM = (input) => {
251
+ const output = new Int16Array(input.length);
252
+ for (let index = 0;index < input.length; index += 1) {
253
+ const sample = clampSample(input[index] ?? 0);
254
+ output[index] = sample < 0 ? sample * 32768 : sample * 32767;
255
+ }
256
+ return new Uint8Array(output.buffer);
257
+ };
258
+ var getPcmLevel = (audio) => {
259
+ const bytes = audio instanceof Uint8Array ? audio : new Uint8Array(audio);
260
+ if (bytes.byteLength < 2) {
261
+ return 0;
262
+ }
263
+ const samples = new Int16Array(bytes.buffer, bytes.byteOffset, Math.floor(bytes.byteLength / 2));
264
+ if (samples.length === 0) {
265
+ return 0;
266
+ }
267
+ let sumSquares = 0;
268
+ for (const sample of samples) {
269
+ const normalized = sample / 32768;
270
+ sumSquares += normalized * normalized;
271
+ }
272
+ return Math.min(1, Math.max(0, Math.sqrt(sumSquares / samples.length) * 5.5));
273
+ };
274
+ var downsampleBuffer = (input, sourceRate, targetRate) => {
275
+ if (sourceRate === targetRate) {
276
+ return input;
277
+ }
278
+ const ratio = sourceRate / targetRate;
279
+ const length = Math.round(input.length / ratio);
280
+ const output = new Float32Array(length);
281
+ let offsetResult = 0;
282
+ let offsetBuffer = 0;
283
+ while (offsetResult < output.length) {
284
+ const nextOffsetBuffer = Math.round((offsetResult + 1) * ratio);
285
+ let accum = 0;
286
+ let count = 0;
287
+ for (let index = offsetBuffer;index < nextOffsetBuffer && index < input.length; index += 1) {
288
+ accum += input[index] ?? 0;
289
+ count += 1;
290
+ }
291
+ output[offsetResult] = count > 0 ? accum / count : 0;
292
+ offsetResult += 1;
293
+ offsetBuffer = nextOffsetBuffer;
294
+ }
295
+ return output;
296
+ };
297
+ var createMicrophoneCapture = (options) => {
298
+ let audioContext = null;
299
+ let sourceNode = null;
300
+ let processorNode = null;
301
+ let mediaStream = null;
302
+ const start = async () => {
303
+ if (typeof navigator === "undefined" || !navigator.mediaDevices?.getUserMedia) {
304
+ throw new Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");
305
+ }
306
+ const AudioContextCtor = (typeof window !== "undefined" ? window.AudioContext ?? window.webkitAudioContext : undefined) ?? AudioContext;
307
+ if (!AudioContextCtor) {
308
+ throw new Error("Browser microphone capture requires AudioContext support.");
309
+ }
310
+ mediaStream = await navigator.mediaDevices.getUserMedia({
311
+ audio: {
312
+ channelCount: options.channelCount ?? 1
313
+ }
314
+ });
315
+ audioContext = new AudioContextCtor;
316
+ sourceNode = audioContext.createMediaStreamSource(mediaStream);
317
+ processorNode = audioContext.createScriptProcessor(4096, 1, 1);
318
+ processorNode.onaudioprocess = (event) => {
319
+ const channel = event.inputBuffer.getChannelData(0);
320
+ const downsampled = downsampleBuffer(channel, audioContext?.sampleRate ?? 48000, options.sampleRateHz ?? 16000);
321
+ const pcm = floatTo16BitPCM(downsampled);
322
+ options.onLevel?.(getPcmLevel(pcm));
323
+ options.onAudio(pcm);
324
+ };
325
+ sourceNode.connect(processorNode);
326
+ processorNode.connect(audioContext.destination);
327
+ };
328
+ const stop = () => {
329
+ processorNode?.disconnect();
330
+ sourceNode?.disconnect();
331
+ mediaStream?.getTracks().forEach((track) => track.stop());
332
+ audioContext?.close();
333
+ options.onLevel?.(0);
334
+ audioContext = null;
335
+ mediaStream = null;
336
+ processorNode = null;
337
+ sourceNode = null;
338
+ };
339
+ return { start, stop };
340
+ };
341
+
199
342
  // src/client/actions.ts
200
343
  var normalizeErrorMessage = (value) => {
201
344
  if (typeof value === "string" && value.trim()) {
@@ -244,6 +387,11 @@ var serverMessageToAction = (message) => {
244
387
  sessionId: message.sessionId,
245
388
  type: "complete"
246
389
  };
390
+ case "connection":
391
+ return {
392
+ reconnect: message.reconnect,
393
+ type: "connection"
394
+ };
247
395
  case "call_lifecycle":
248
396
  return {
249
397
  event: message.event,
@@ -265,9 +413,22 @@ var serverMessageToAction = (message) => {
265
413
  transcript: message.transcript,
266
414
  type: "partial"
267
415
  };
416
+ case "replay":
417
+ return {
418
+ assistantTexts: message.assistantTexts,
419
+ call: message.call,
420
+ partial: message.partial,
421
+ scenarioId: message.scenarioId,
422
+ sessionId: message.sessionId,
423
+ sessionMetadata: message.sessionMetadata,
424
+ status: message.status,
425
+ turns: message.turns,
426
+ type: "replay"
427
+ };
268
428
  case "session":
269
429
  return {
270
430
  sessionId: message.sessionId,
431
+ sessionMetadata: message.sessionMetadata,
271
432
  scenarioId: message.scenarioId,
272
433
  status: message.status,
273
434
  type: "session"
@@ -282,6 +443,84 @@ var serverMessageToAction = (message) => {
282
443
  }
283
444
  };
284
445
 
446
+ // src/client/browserMedia.ts
447
+ import {
448
+ buildMediaWebRTCStatsReport,
449
+ buildMediaWebRTCStreamContinuityReport,
450
+ collectMediaWebRTCStats
451
+ } from "@absolutejs/media";
452
+ var DEFAULT_BROWSER_MEDIA_PATH = "/api/voice/browser-media";
453
+ var DEFAULT_BROWSER_MEDIA_INTERVAL_MS = 5000;
454
+ var resolvePeerConnection = async (options) => options.peerConnection ?? await options.getPeerConnection?.() ?? null;
455
+ var postBrowserMediaReport = async (payload, options) => {
456
+ const requestFetch = options.fetch ?? globalThis.fetch;
457
+ if (!requestFetch) {
458
+ return;
459
+ }
460
+ await requestFetch(options.path ?? DEFAULT_BROWSER_MEDIA_PATH, {
461
+ body: JSON.stringify(payload),
462
+ headers: {
463
+ "Content-Type": "application/json"
464
+ },
465
+ keepalive: true,
466
+ method: "POST"
467
+ });
468
+ };
469
+ var createVoiceBrowserMediaReporter = (options) => {
470
+ let interval = null;
471
+ let previousStats = [];
472
+ const reportOnce = async () => {
473
+ const peerConnection = await resolvePeerConnection(options);
474
+ if (!peerConnection) {
475
+ return;
476
+ }
477
+ const stats = await collectMediaWebRTCStats({ peerConnection });
478
+ const report = buildMediaWebRTCStatsReport({
479
+ ...options,
480
+ stats
481
+ });
482
+ const continuity = options.continuity === false ? undefined : buildMediaWebRTCStreamContinuityReport({
483
+ ...options.continuity,
484
+ previousStats,
485
+ stats
486
+ });
487
+ const payload = {
488
+ at: Date.now(),
489
+ continuity,
490
+ report,
491
+ scenarioId: options.getScenarioId?.() ?? null,
492
+ sessionId: options.getSessionId?.() ?? null
493
+ };
494
+ previousStats = stats;
495
+ options.onReport?.(payload);
496
+ await postBrowserMediaReport(payload, options);
497
+ return payload;
498
+ };
499
+ const run = () => {
500
+ reportOnce().catch((error) => {
501
+ options.onError?.(error);
502
+ });
503
+ };
504
+ const stop = () => {
505
+ if (interval) {
506
+ clearInterval(interval);
507
+ interval = null;
508
+ }
509
+ };
510
+ return {
511
+ close: stop,
512
+ reportOnce,
513
+ start: () => {
514
+ if (interval) {
515
+ return;
516
+ }
517
+ run();
518
+ interval = setInterval(run, options.intervalMs ?? DEFAULT_BROWSER_MEDIA_INTERVAL_MS);
519
+ },
520
+ stop
521
+ };
522
+ };
523
+
285
524
  // src/client/connection.ts
286
525
  var WS_OPEN = 1;
287
526
  var WS_CLOSED = 3;
@@ -301,6 +540,7 @@ var NOOP_CONNECTION = {
301
540
  getSessionId: () => "",
302
541
  send: noop,
303
542
  sendAudio: noop,
543
+ simulateDisconnect: noop,
304
544
  start: () => {},
305
545
  subscribe: noopUnsubscribe
306
546
  };
@@ -325,10 +565,12 @@ var isVoiceServerMessage = (value) => {
325
565
  case "assistant":
326
566
  case "call_lifecycle":
327
567
  case "complete":
568
+ case "connection":
328
569
  case "error":
329
570
  case "final":
330
571
  case "partial":
331
572
  case "pong":
573
+ case "replay":
332
574
  case "session":
333
575
  case "turn":
334
576
  return true;
@@ -365,6 +607,9 @@ var createVoiceConnection = (path, options = {}) => {
365
607
  sessionId: options.sessionId ?? createSessionId(),
366
608
  ws: null
367
609
  };
610
+ const emitConnection = (reconnect) => {
611
+ listeners.forEach((listener) => listener(reconnect));
612
+ };
368
613
  const clearTimers = () => {
369
614
  if (state.pingInterval) {
370
615
  clearInterval(state.pingInterval);
@@ -387,9 +632,28 @@ var createVoiceConnection = (path, options = {}) => {
387
632
  }
388
633
  };
389
634
  const scheduleReconnect = () => {
635
+ const nextAttemptAt = Date.now() + RECONNECT_DELAY_MS;
390
636
  state.reconnectAttempts += 1;
637
+ emitConnection({
638
+ reconnect: {
639
+ attempts: state.reconnectAttempts,
640
+ lastDisconnectAt: Date.now(),
641
+ maxAttempts: maxReconnectAttempts,
642
+ nextAttemptAt,
643
+ status: "reconnecting"
644
+ },
645
+ type: "connection"
646
+ });
391
647
  state.reconnectTimeout = setTimeout(() => {
392
648
  if (state.reconnectAttempts > maxReconnectAttempts) {
649
+ emitConnection({
650
+ reconnect: {
651
+ attempts: state.reconnectAttempts,
652
+ maxAttempts: maxReconnectAttempts,
653
+ status: "exhausted"
654
+ },
655
+ type: "connection"
656
+ });
393
657
  return;
394
658
  }
395
659
  connect();
@@ -399,9 +663,21 @@ var createVoiceConnection = (path, options = {}) => {
399
663
  const ws = new WebSocket(buildWsUrl(path, state.sessionId, state.scenarioId));
400
664
  ws.binaryType = "arraybuffer";
401
665
  ws.onopen = () => {
666
+ const wasReconnecting = state.reconnectAttempts > 0;
402
667
  state.isConnected = true;
403
- state.reconnectAttempts = 0;
404
668
  flushPendingMessages();
669
+ if (wasReconnecting) {
670
+ emitConnection({
671
+ reconnect: {
672
+ attempts: state.reconnectAttempts,
673
+ lastResumedAt: Date.now(),
674
+ maxAttempts: maxReconnectAttempts,
675
+ status: "resumed"
676
+ },
677
+ type: "connection"
678
+ });
679
+ state.reconnectAttempts = 0;
680
+ }
405
681
  listeners.forEach((listener) => listener({
406
682
  scenarioId: state.scenarioId ?? undefined,
407
683
  sessionId: state.sessionId,
@@ -431,6 +707,16 @@ var createVoiceConnection = (path, options = {}) => {
431
707
  const reconnectable = shouldReconnect && event.code !== WS_NORMAL_CLOSURE && state.reconnectAttempts < maxReconnectAttempts;
432
708
  if (reconnectable) {
433
709
  scheduleReconnect();
710
+ } else if (shouldReconnect && event.code !== WS_NORMAL_CLOSURE) {
711
+ emitConnection({
712
+ reconnect: {
713
+ attempts: state.reconnectAttempts,
714
+ lastDisconnectAt: Date.now(),
715
+ maxAttempts: maxReconnectAttempts,
716
+ status: "exhausted"
717
+ },
718
+ type: "connection"
719
+ });
434
720
  }
435
721
  };
436
722
  state.ws = ws;
@@ -479,6 +765,11 @@ var createVoiceConnection = (path, options = {}) => {
479
765
  state.isConnected = false;
480
766
  listeners.clear();
481
767
  };
768
+ const simulateDisconnect = () => {
769
+ if (state.ws?.readyState === WS_OPEN) {
770
+ state.ws.close(4000, "absolutejs-voice-reconnect-proof");
771
+ }
772
+ };
482
773
  const subscribe = (callback) => {
483
774
  listeners.add(callback);
484
775
  return () => {
@@ -495,20 +786,28 @@ var createVoiceConnection = (path, options = {}) => {
495
786
  getSessionId: () => state.sessionId,
496
787
  send,
497
788
  sendAudio,
789
+ simulateDisconnect,
498
790
  start,
499
791
  subscribe
500
792
  };
501
793
  };
502
794
 
503
795
  // src/client/store.ts
796
+ var createInitialReconnectState = () => ({
797
+ attempts: 0,
798
+ maxAttempts: 0,
799
+ status: "idle"
800
+ });
504
801
  var createInitialState = () => ({
505
802
  assistantAudio: [],
506
803
  assistantTexts: [],
507
804
  call: null,
508
805
  error: null,
509
806
  isConnected: false,
807
+ sessionMetadata: null,
510
808
  scenarioId: null,
511
809
  partial: "",
810
+ reconnect: createInitialReconnectState(),
512
811
  sessionId: null,
513
812
  status: "idle",
514
813
  turns: []
@@ -565,7 +864,19 @@ var createVoiceStreamStore = () => {
565
864
  case "connected":
566
865
  state = {
567
866
  ...state,
568
- isConnected: true
867
+ isConnected: true,
868
+ reconnect: state.reconnect.status === "reconnecting" ? {
869
+ ...state.reconnect,
870
+ lastResumedAt: Date.now(),
871
+ nextAttemptAt: undefined,
872
+ status: "resumed"
873
+ } : state.reconnect
874
+ };
875
+ break;
876
+ case "connection":
877
+ state = {
878
+ ...state,
879
+ reconnect: action.reconnect
569
880
  };
570
881
  break;
571
882
  case "disconnected":
@@ -593,6 +904,27 @@ var createVoiceStreamStore = () => {
593
904
  partial: action.transcript.text
594
905
  };
595
906
  break;
907
+ case "replay":
908
+ state = {
909
+ ...state,
910
+ assistantTexts: [...action.assistantTexts],
911
+ call: action.call ?? null,
912
+ error: null,
913
+ isConnected: action.status === "active",
914
+ partial: action.partial,
915
+ reconnect: state.reconnect.status === "reconnecting" ? {
916
+ ...state.reconnect,
917
+ lastResumedAt: Date.now(),
918
+ nextAttemptAt: undefined,
919
+ status: "resumed"
920
+ } : state.reconnect,
921
+ scenarioId: action.scenarioId ?? state.scenarioId,
922
+ sessionId: action.sessionId,
923
+ sessionMetadata: action.sessionMetadata ?? state.sessionMetadata,
924
+ status: action.status,
925
+ turns: [...action.turns]
926
+ };
927
+ break;
596
928
  case "session":
597
929
  state = {
598
930
  ...state,
@@ -600,6 +932,7 @@ var createVoiceStreamStore = () => {
600
932
  scenarioId: action.scenarioId ?? state.scenarioId,
601
933
  isConnected: action.status === "active",
602
934
  sessionId: action.sessionId,
935
+ sessionMetadata: action.sessionMetadata ?? state.sessionMetadata,
603
936
  status: action.status
604
937
  };
605
938
  break;
@@ -630,20 +963,50 @@ var createVoiceStreamStore = () => {
630
963
  var createVoiceStream = (path, options = {}) => {
631
964
  const connection = createVoiceConnection(path, options);
632
965
  const store = createVoiceStreamStore();
966
+ const browserMediaReporter = options.browserMedia && typeof window !== "undefined" ? createVoiceBrowserMediaReporter({
967
+ ...options.browserMedia,
968
+ getScenarioId: () => options.browserMedia ? options.browserMedia.getScenarioId?.() ?? connection.getScenarioId() : connection.getScenarioId(),
969
+ getSessionId: () => options.browserMedia ? options.browserMedia.getSessionId?.() ?? connection.getSessionId() : connection.getSessionId()
970
+ }) : null;
633
971
  const subscribers = new Set;
634
972
  const start = (input) => Promise.resolve().then(() => {
635
973
  if (!input?.sessionId && !input?.scenarioId) {
636
974
  return;
637
975
  }
638
976
  connection.start(input);
977
+ browserMediaReporter?.start();
639
978
  });
640
979
  const notify = () => {
641
980
  subscribers.forEach((subscriber) => subscriber());
642
981
  };
982
+ const reportReconnect = () => {
983
+ if (!options.reconnectReportPath || typeof fetch === "undefined") {
984
+ return;
985
+ }
986
+ const snapshot = store.getSnapshot();
987
+ const body = JSON.stringify({
988
+ at: Date.now(),
989
+ reconnect: snapshot.reconnect,
990
+ scenarioId: snapshot.scenarioId,
991
+ sessionId: connection.getSessionId(),
992
+ turnIds: snapshot.turns.map((turn) => turn.id)
993
+ });
994
+ fetch(options.reconnectReportPath, {
995
+ body,
996
+ headers: {
997
+ "Content-Type": "application/json"
998
+ },
999
+ keepalive: true,
1000
+ method: "POST"
1001
+ }).catch(() => {});
1002
+ };
643
1003
  const unsubscribeConnection = connection.subscribe((message) => {
644
1004
  const action = serverMessageToAction(message);
645
1005
  if (action) {
646
1006
  store.dispatch(action);
1007
+ if (message.type === "connection") {
1008
+ reportReconnect();
1009
+ }
647
1010
  notify();
648
1011
  }
649
1012
  });
@@ -653,6 +1016,7 @@ var createVoiceStream = (path, options = {}) => {
653
1016
  },
654
1017
  close() {
655
1018
  unsubscribeConnection();
1019
+ browserMediaReporter?.close();
656
1020
  connection.close();
657
1021
  store.dispatch({ type: "disconnected" });
658
1022
  notify();
@@ -675,10 +1039,16 @@ var createVoiceStream = (path, options = {}) => {
675
1039
  get scenarioId() {
676
1040
  return store.getSnapshot().scenarioId;
677
1041
  },
1042
+ get sessionMetadata() {
1043
+ return store.getSnapshot().sessionMetadata;
1044
+ },
678
1045
  start,
679
1046
  get partial() {
680
1047
  return store.getSnapshot().partial;
681
1048
  },
1049
+ get reconnect() {
1050
+ return store.getSnapshot().reconnect;
1051
+ },
682
1052
  get sessionId() {
683
1053
  return connection.getSessionId();
684
1054
  },
@@ -700,6 +1070,9 @@ var createVoiceStream = (path, options = {}) => {
700
1070
  sendAudio(audio) {
701
1071
  connection.sendAudio(audio);
702
1072
  },
1073
+ simulateDisconnect() {
1074
+ connection.simulateDisconnect();
1075
+ },
703
1076
  subscribe(subscriber) {
704
1077
  subscribers.add(subscriber);
705
1078
  return () => {
@@ -709,214 +1082,14 @@ var createVoiceStream = (path, options = {}) => {
709
1082
  };
710
1083
  };
711
1084
 
712
- // src/angular/voice-stream.service.ts
713
- var _dec = [
714
- Injectable2({ providedIn: "root" })
715
- ];
716
- var _init = __decoratorStart(undefined);
717
-
718
- class VoiceStreamService {
719
- connect(path, options = {}) {
720
- const stream = createVoiceStream(path, options);
721
- const assistantAudioSignal = signal2([]);
722
- const assistantTextsSignal = signal2([]);
723
- const callSignal = signal2(null);
724
- const errorSignal = signal2(null);
725
- const isConnectedSignal = signal2(false);
726
- const partialSignal = signal2("");
727
- const sessionIdSignal = signal2(stream.sessionId);
728
- const statusSignal = signal2(stream.status);
729
- const turnsSignal = signal2([]);
730
- const sync = () => {
731
- assistantAudioSignal.set([...stream.assistantAudio]);
732
- assistantTextsSignal.set([...stream.assistantTexts]);
733
- callSignal.set(stream.call);
734
- errorSignal.set(stream.error);
735
- isConnectedSignal.set(stream.isConnected);
736
- partialSignal.set(stream.partial);
737
- sessionIdSignal.set(stream.sessionId);
738
- statusSignal.set(stream.status);
739
- turnsSignal.set([...stream.turns]);
740
- };
741
- const unsubscribe = stream.subscribe(sync);
742
- sync();
743
- return {
744
- assistantAudio: computed2(() => assistantAudioSignal()),
745
- assistantTexts: computed2(() => assistantTextsSignal()),
746
- call: computed2(() => callSignal()),
747
- callControl: (message) => stream.callControl(message),
748
- close: () => {
749
- unsubscribe();
750
- stream.close();
751
- },
752
- endTurn: () => stream.endTurn(),
753
- error: computed2(() => errorSignal()),
754
- isConnected: computed2(() => isConnectedSignal()),
755
- partial: computed2(() => partialSignal()),
756
- sendAudio: (audio) => stream.sendAudio(audio),
757
- sessionId: computed2(() => sessionIdSignal()),
758
- status: computed2(() => statusSignal()),
759
- turns: computed2(() => turnsSignal())
760
- };
761
- }
762
- }
763
- VoiceStreamService = __decorateElement(_init, 0, "VoiceStreamService", _dec, VoiceStreamService);
764
- __runInitializers(_init, 1, VoiceStreamService);
765
- __decoratorMetadata(_init, VoiceStreamService);
766
- let _VoiceStreamService = VoiceStreamService;
767
- // src/angular/voice-controller.service.ts
768
- import { computed as computed3, Injectable as Injectable3, signal as signal3 } from "@angular/core";
769
-
770
- // src/client/htmx.ts
771
- var DEFAULT_EVENT_NAME = "voice-refresh";
772
- var DEFAULT_QUERY_PARAM = "sessionId";
773
- var resolveElement = (input) => {
774
- if (typeof input !== "string") {
775
- return input;
776
- }
777
- return document.querySelector(input);
778
- };
779
- var buildRoute = (element, route, queryParam, sessionId) => {
780
- const baseRoute = route ?? element.getAttribute("hx-get") ?? "";
781
- if (!baseRoute) {
782
- return "";
783
- }
784
- const url = new URL(baseRoute, window.location.origin);
785
- if (sessionId) {
786
- url.searchParams.set(queryParam, sessionId);
787
- } else {
788
- url.searchParams.delete(queryParam);
789
- }
790
- return `${url.pathname}${url.search}${url.hash}`;
791
- };
792
- var bindVoiceHTMX = (stream, options) => {
793
- if (typeof window === "undefined" || typeof document === "undefined") {
794
- return () => {};
795
- }
796
- const element = resolveElement(options.element);
797
- if (!element) {
798
- return () => {};
799
- }
800
- const eventName = options.eventName ?? DEFAULT_EVENT_NAME;
801
- const queryParam = options.sessionQueryParam ?? DEFAULT_QUERY_PARAM;
802
- const sync = () => {
803
- const htmxWindow = window;
804
- const nextRoute = buildRoute(element, options.route, queryParam, stream.sessionId);
805
- if (nextRoute) {
806
- element.setAttribute("hx-get", nextRoute);
807
- }
808
- htmxWindow.htmx?.process?.(element);
809
- htmxWindow.htmx?.trigger?.(element, eventName);
810
- };
811
- const unsubscribe = stream.subscribe(sync);
812
- sync();
813
- return () => {
814
- unsubscribe();
815
- };
816
- };
817
-
818
- // src/client/microphone.ts
819
- var clampSample = (value) => Math.max(-1, Math.min(1, value));
820
- var floatTo16BitPCM = (input) => {
821
- const output = new Int16Array(input.length);
822
- for (let index = 0;index < input.length; index += 1) {
823
- const sample = clampSample(input[index] ?? 0);
824
- output[index] = sample < 0 ? sample * 32768 : sample * 32767;
825
- }
826
- return new Uint8Array(output.buffer);
827
- };
828
- var getPcmLevel = (audio) => {
829
- const bytes = audio instanceof Uint8Array ? audio : new Uint8Array(audio);
830
- if (bytes.byteLength < 2) {
831
- return 0;
832
- }
833
- const samples = new Int16Array(bytes.buffer, bytes.byteOffset, Math.floor(bytes.byteLength / 2));
834
- if (samples.length === 0) {
835
- return 0;
836
- }
837
- let sumSquares = 0;
838
- for (const sample of samples) {
839
- const normalized = sample / 32768;
840
- sumSquares += normalized * normalized;
841
- }
842
- return Math.min(1, Math.max(0, Math.sqrt(sumSquares / samples.length) * 5.5));
843
- };
844
- var downsampleBuffer = (input, sourceRate, targetRate) => {
845
- if (sourceRate === targetRate) {
846
- return input;
847
- }
848
- const ratio = sourceRate / targetRate;
849
- const length = Math.round(input.length / ratio);
850
- const output = new Float32Array(length);
851
- let offsetResult = 0;
852
- let offsetBuffer = 0;
853
- while (offsetResult < output.length) {
854
- const nextOffsetBuffer = Math.round((offsetResult + 1) * ratio);
855
- let accum = 0;
856
- let count = 0;
857
- for (let index = offsetBuffer;index < nextOffsetBuffer && index < input.length; index += 1) {
858
- accum += input[index] ?? 0;
859
- count += 1;
860
- }
861
- output[offsetResult] = count > 0 ? accum / count : 0;
862
- offsetResult += 1;
863
- offsetBuffer = nextOffsetBuffer;
864
- }
865
- return output;
866
- };
867
- var createMicrophoneCapture = (options) => {
868
- let audioContext = null;
869
- let sourceNode = null;
870
- let processorNode = null;
871
- let mediaStream = null;
872
- const start = async () => {
873
- if (typeof navigator === "undefined" || !navigator.mediaDevices?.getUserMedia) {
874
- throw new Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");
875
- }
876
- const AudioContextCtor = (typeof window !== "undefined" ? window.AudioContext ?? window.webkitAudioContext : undefined) ?? AudioContext;
877
- if (!AudioContextCtor) {
878
- throw new Error("Browser microphone capture requires AudioContext support.");
879
- }
880
- mediaStream = await navigator.mediaDevices.getUserMedia({
881
- audio: {
882
- channelCount: options.channelCount ?? 1
883
- }
884
- });
885
- audioContext = new AudioContextCtor;
886
- sourceNode = audioContext.createMediaStreamSource(mediaStream);
887
- processorNode = audioContext.createScriptProcessor(4096, 1, 1);
888
- processorNode.onaudioprocess = (event) => {
889
- const channel = event.inputBuffer.getChannelData(0);
890
- const downsampled = downsampleBuffer(channel, audioContext?.sampleRate ?? 48000, options.sampleRateHz ?? 16000);
891
- const pcm = floatTo16BitPCM(downsampled);
892
- options.onLevel?.(getPcmLevel(pcm));
893
- options.onAudio(pcm);
894
- };
895
- sourceNode.connect(processorNode);
896
- processorNode.connect(audioContext.destination);
897
- };
898
- const stop = () => {
899
- processorNode?.disconnect();
900
- sourceNode?.disconnect();
901
- mediaStream?.getTracks().forEach((track) => track.stop());
902
- audioContext?.close();
903
- options.onLevel?.(0);
904
- audioContext = null;
905
- mediaStream = null;
906
- processorNode = null;
907
- sourceNode = null;
908
- };
909
- return { start, stop };
910
- };
911
-
912
- // src/audioConditioning.ts
913
- var DEFAULT_TARGET_LEVEL = 0.08;
914
- var DEFAULT_MAX_GAIN = 3;
915
- var DEFAULT_NOISE_GATE_THRESHOLD = 0.006;
916
- var DEFAULT_NOISE_GATE_ATTENUATION = 0.15;
917
- var toInt16Array = (audio) => {
918
- if (audio instanceof ArrayBuffer) {
919
- return new Int16Array(audio, 0, Math.floor(audio.byteLength / 2));
1085
+ // src/audioConditioning.ts
1086
+ var DEFAULT_TARGET_LEVEL = 0.08;
1087
+ var DEFAULT_MAX_GAIN = 3;
1088
+ var DEFAULT_NOISE_GATE_THRESHOLD = 0.006;
1089
+ var DEFAULT_NOISE_GATE_ATTENUATION = 0.15;
1090
+ var toInt16Array = (audio) => {
1091
+ if (audio instanceof ArrayBuffer) {
1092
+ return new Int16Array(audio, 0, Math.floor(audio.byteLength / 2));
920
1093
  }
921
1094
  return new Int16Array(audio.buffer, audio.byteOffset, Math.floor(audio.byteLength / 2));
922
1095
  };
@@ -1234,8 +1407,10 @@ var createInitialState2 = (stream) => ({
1234
1407
  isConnected: stream.isConnected,
1235
1408
  isRecording: false,
1236
1409
  partial: stream.partial,
1410
+ reconnect: stream.reconnect,
1237
1411
  recordingError: null,
1238
1412
  sessionId: stream.sessionId,
1413
+ sessionMetadata: stream.sessionMetadata,
1239
1414
  scenarioId: stream.scenarioId,
1240
1415
  status: stream.status,
1241
1416
  turns: [...stream.turns]
@@ -1263,7 +1438,9 @@ var createVoiceController = (path, options = {}) => {
1263
1438
  error: stream.error,
1264
1439
  isConnected: stream.isConnected,
1265
1440
  partial: stream.partial,
1441
+ reconnect: stream.reconnect,
1266
1442
  sessionId: stream.sessionId,
1443
+ sessionMetadata: stream.sessionMetadata,
1267
1444
  scenarioId: stream.scenarioId,
1268
1445
  status: stream.status,
1269
1446
  turns: [...stream.turns]
@@ -1287,7 +1464,13 @@ var createVoiceController = (path, options = {}) => {
1287
1464
  capture = createMicrophoneCapture({
1288
1465
  channelCount: options.capture?.channelCount ?? preset.capture.channelCount,
1289
1466
  onLevel: options.capture?.onLevel,
1290
- onAudio: (audio) => stream.sendAudio(audio),
1467
+ onAudio: (audio) => {
1468
+ if (options.capture?.onAudio) {
1469
+ options.capture.onAudio(audio, stream.sendAudio);
1470
+ return;
1471
+ }
1472
+ stream.sendAudio(audio);
1473
+ },
1291
1474
  sampleRateHz: options.capture?.sampleRateHz ?? preset.capture.sampleRateHz
1292
1475
  });
1293
1476
  return capture;
@@ -1357,10 +1540,17 @@ var createVoiceController = (path, options = {}) => {
1357
1540
  get recordingError() {
1358
1541
  return state.recordingError;
1359
1542
  },
1543
+ get reconnect() {
1544
+ return state.reconnect;
1545
+ },
1360
1546
  sendAudio: (audio) => stream.sendAudio(audio),
1547
+ simulateDisconnect: () => stream.simulateDisconnect(),
1361
1548
  get sessionId() {
1362
1549
  return state.sessionId;
1363
1550
  },
1551
+ get sessionMetadata() {
1552
+ return state.sessionMetadata;
1553
+ },
1364
1554
  get scenarioId() {
1365
1555
  return state.scenarioId;
1366
1556
  },
@@ -1397,113 +1587,3278 @@ var createVoiceController = (path, options = {}) => {
1397
1587
  };
1398
1588
  };
1399
1589
 
1400
- // src/angular/voice-controller.service.ts
1590
+ // src/agentState.ts
1591
+ var deriveVoiceAgentUIState = (input) => {
1592
+ if (!input.isConnected) {
1593
+ return "idle";
1594
+ }
1595
+ if (input.isPlaying) {
1596
+ return "speaking";
1597
+ }
1598
+ if (input.isRecording && input.hasActivePartial) {
1599
+ return "listening";
1600
+ }
1601
+ if (input.isRecording) {
1602
+ return "listening";
1603
+ }
1604
+ if (input.lastTranscriptAt && !input.lastAssistantAt) {
1605
+ return "thinking";
1606
+ }
1607
+ if (input.lastTranscriptAt && input.lastAssistantAt && input.lastTranscriptAt > input.lastAssistantAt) {
1608
+ return "thinking";
1609
+ }
1610
+ return "idle";
1611
+ };
1612
+ var describeVoiceAgentUIState = (state) => {
1613
+ switch (state) {
1614
+ case "idle":
1615
+ return "Idle";
1616
+ case "listening":
1617
+ return "Listening";
1618
+ case "speaking":
1619
+ return "Speaking";
1620
+ case "thinking":
1621
+ return "Thinking";
1622
+ }
1623
+ };
1624
+ var voiceAgentUIStateOrder = [
1625
+ "idle",
1626
+ "listening",
1627
+ "thinking",
1628
+ "speaking"
1629
+ ];
1630
+
1631
+ // src/client/voiceWidgetView.ts
1632
+ var DEFAULT_VOICE_WIDGET_THEME = {
1633
+ accent: "#3b82f6",
1634
+ background: "#0f172a",
1635
+ errorAccent: "#ef4444",
1636
+ fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
1637
+ foreground: "#f8fafc",
1638
+ radius: 16
1639
+ };
1640
+ var DEFAULT_VOICE_WIDGET_LABELS = {
1641
+ callEnded: "Call ended",
1642
+ connecting: "Connecting\u2026",
1643
+ endCall: "End call",
1644
+ idle: "Idle",
1645
+ listening: "Listening",
1646
+ mute: "Mute",
1647
+ speaking: "Speaking",
1648
+ startCall: "Start call",
1649
+ thinking: "Thinking",
1650
+ unmute: "Unmute"
1651
+ };
1652
+ var stateLabel = (state, labels) => {
1653
+ switch (state) {
1654
+ case "listening":
1655
+ return labels.listening;
1656
+ case "speaking":
1657
+ return labels.speaking;
1658
+ case "thinking":
1659
+ return labels.thinking;
1660
+ case "idle":
1661
+ return labels.idle;
1662
+ }
1663
+ };
1664
+ var createVoiceWidgetViewModel = (input) => {
1665
+ const theme = { ...DEFAULT_VOICE_WIDGET_THEME, ...input.theme };
1666
+ const labels = { ...DEFAULT_VOICE_WIDGET_LABELS, ...input.labels };
1667
+ const lastAssistantAt = input.state.assistantAudio.at(-1)?.receivedAt;
1668
+ const lastTranscriptAt = input.state.turns.at(-1)?.committedAt;
1669
+ const agentState = deriveVoiceAgentUIState({
1670
+ hasActivePartial: input.state.partial.length > 0,
1671
+ isConnected: input.state.isConnected,
1672
+ isPlaying: false,
1673
+ isRecording: input.state.isRecording,
1674
+ lastAssistantAt,
1675
+ lastTranscriptAt
1676
+ });
1677
+ const connecting = !input.state.isConnected && input.state.status !== "idle" && !input.state.error;
1678
+ const statusLabel = input.state.error ? "Error" : connecting ? labels.connecting : input.state.status === "completed" ? labels.callEnded : stateLabel(agentState, labels);
1679
+ return {
1680
+ agentState,
1681
+ classes: {
1682
+ container: `absolute-voice-widget absolute-voice-widget--${agentState}`,
1683
+ dot: `absolute-voice-widget__dot${input.state.error ? " absolute-voice-widget__dot--error" : ""}`
1684
+ },
1685
+ controls: {
1686
+ canEnd: input.state.isConnected,
1687
+ canMute: input.state.isRecording,
1688
+ canStart: !input.state.isRecording && input.state.status !== "completed"
1689
+ },
1690
+ errorMessage: input.state.error ?? undefined,
1691
+ labels,
1692
+ partial: input.state.partial || undefined,
1693
+ statusLabel,
1694
+ theme,
1695
+ title: input.title ?? "Voice"
1696
+ };
1697
+ };
1698
+ var escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1699
+ var resolveRadius = (radius) => typeof radius === "number" ? `${radius}px` : radius;
1700
+ var renderVoiceWidgetHTML = (model) => {
1701
+ const t = model.theme;
1702
+ const containerStyle = `background:${t.background};border-radius:${resolveRadius(t.radius)};color:${t.foreground};font-family:${t.fontFamily};min-width:240px;padding:20px 22px;`;
1703
+ const dotStyle = `background:${model.errorMessage ? t.errorAccent : model.agentState === "idle" ? "rgba(148,163,184,0.6)" : t.accent};border-radius:50%;height:10px;width:10px;`;
1704
+ const buttons = [];
1705
+ if (model.controls.canStart) {
1706
+ buttons.push(`<button type="button" data-action="start" style="background:${t.accent};border:none;border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml(model.labels.startCall)}</button>`);
1707
+ }
1708
+ if (model.controls.canMute) {
1709
+ buttons.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml(model.labels.mute)}</button>`);
1710
+ }
1711
+ if (model.controls.canEnd) {
1712
+ buttons.push(`<button type="button" data-action="end" style="background:${t.errorAccent};border:none;border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml(model.labels.endCall)}</button>`);
1713
+ }
1714
+ return `<div role="region" aria-live="polite" data-agent-state="${model.agentState}" class="${escapeHtml(model.classes.container)}" style="${containerStyle}">
1715
+ <div style="align-items:center;display:flex;gap:10px;margin-bottom:12px;">
1716
+ <span aria-hidden="true" class="${escapeHtml(model.classes.dot)}" style="${dotStyle}"></span>
1717
+ <strong style="font-size:15px;">${escapeHtml(model.title)}</strong>
1718
+ <span style="font-size:13px;margin-left:auto;opacity:0.7;">${escapeHtml(model.statusLabel)}</span>
1719
+ </div>
1720
+ ${model.partial ? `<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">\u201C${escapeHtml(model.partial)}\u201D</p>` : ""}
1721
+ <div style="display:flex;gap:10px;">${buttons.join("")}</div>
1722
+ ${model.errorMessage ? `<p style="color:${t.errorAccent};font-size:12px;margin-top:12px;">${escapeHtml(model.errorMessage)}</p>` : ""}
1723
+ </div>`;
1724
+ };
1725
+
1726
+ // src/angular/voice-widget.service.ts
1401
1727
  var _dec = [
1402
- Injectable3({ providedIn: "root" })
1728
+ Injectable2({ providedIn: "root" })
1403
1729
  ];
1404
1730
  var _init = __decoratorStart(undefined);
1405
1731
 
1406
- class VoiceControllerService {
1732
+ class VoiceWidgetService {
1407
1733
  connect(path, options = {}) {
1408
1734
  const controller = createVoiceController(path, options);
1409
- const assistantAudioSignal = signal3([]);
1410
- const assistantTextsSignal = signal3([]);
1411
- const errorSignal = signal3(null);
1412
- const isConnectedSignal = signal3(false);
1413
- const isRecordingSignal = signal3(false);
1414
- const partialSignal = signal3("");
1415
- const recordingErrorSignal = signal3(null);
1416
- const sessionIdSignal = signal3(controller.sessionId);
1417
- const statusSignal = signal3(controller.status);
1418
- const turnsSignal = signal3([]);
1735
+ const viewModelSignal = signal2(createVoiceWidgetViewModel({
1736
+ labels: options.labels,
1737
+ state: controller.getSnapshot(),
1738
+ theme: options.theme,
1739
+ title: options.title
1740
+ }));
1419
1741
  const sync = () => {
1420
- assistantAudioSignal.set([...controller.assistantAudio]);
1421
- assistantTextsSignal.set([...controller.assistantTexts]);
1422
- errorSignal.set(controller.error);
1423
- isConnectedSignal.set(controller.isConnected);
1424
- isRecordingSignal.set(controller.isRecording);
1425
- partialSignal.set(controller.partial);
1426
- recordingErrorSignal.set(controller.recordingError);
1427
- sessionIdSignal.set(controller.sessionId);
1428
- statusSignal.set(controller.status);
1429
- turnsSignal.set([...controller.turns]);
1742
+ viewModelSignal.set(createVoiceWidgetViewModel({
1743
+ labels: options.labels,
1744
+ state: controller.getSnapshot(),
1745
+ theme: options.theme,
1746
+ title: options.title
1747
+ }));
1430
1748
  };
1431
1749
  const unsubscribe = controller.subscribe(sync);
1432
1750
  sync();
1433
1751
  return {
1434
- assistantAudio: computed3(() => assistantAudioSignal()),
1435
- assistantTexts: computed3(() => assistantTextsSignal()),
1436
- bindHTMX: controller.bindHTMX,
1437
1752
  close: () => {
1438
1753
  unsubscribe();
1439
1754
  controller.close();
1440
1755
  },
1441
- endTurn: () => controller.endTurn(),
1442
- error: computed3(() => errorSignal()),
1443
- isConnected: computed3(() => isConnectedSignal()),
1444
- isRecording: computed3(() => isRecordingSignal()),
1445
- partial: computed3(() => partialSignal()),
1446
- recordingError: computed3(() => recordingErrorSignal()),
1447
- sendAudio: (audio) => controller.sendAudio(audio),
1448
- sessionId: computed3(() => sessionIdSignal()),
1449
- startRecording: () => controller.startRecording(),
1450
- status: computed3(() => statusSignal()),
1451
- stopRecording: () => controller.stopRecording(),
1452
- toggleRecording: () => controller.toggleRecording(),
1453
- turns: computed3(() => turnsSignal())
1756
+ endCall: () => controller.close(),
1757
+ getHTML: () => renderVoiceWidgetHTML(viewModelSignal()),
1758
+ mute: () => controller.stopRecording(),
1759
+ startCall: () => controller.startRecording(),
1760
+ unmute: () => controller.startRecording(),
1761
+ viewModel: computed2(() => viewModelSignal())
1454
1762
  };
1455
1763
  }
1456
1764
  }
1457
- VoiceControllerService = __decorateElement(_init, 0, "VoiceControllerService", _dec, VoiceControllerService);
1458
- __runInitializers(_init, 1, VoiceControllerService);
1459
- __decoratorMetadata(_init, VoiceControllerService);
1460
- let _VoiceControllerService = VoiceControllerService;
1461
- // src/angular/voice-provider-status.service.ts
1462
- import { computed as computed4, Injectable as Injectable4, signal as signal4 } from "@angular/core";
1765
+ VoiceWidgetService = __decorateElement(_init, 0, "VoiceWidgetService", _dec, VoiceWidgetService);
1766
+ __runInitializers(_init, 1, VoiceWidgetService);
1767
+ __decoratorMetadata(_init, VoiceWidgetService);
1768
+ let _VoiceWidgetService = VoiceWidgetService;
1769
+ // src/angular/voice-cost-dashboard.service.ts
1770
+ import { computed as computed3, Injectable as Injectable3, signal as signal3 } from "@angular/core";
1463
1771
 
1464
- // src/client/providerStatus.ts
1465
- var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
1466
- const fetchImpl = options.fetch ?? globalThis.fetch;
1467
- const response = await fetchImpl(path);
1468
- if (!response.ok) {
1469
- throw new Error(`Voice provider status failed: HTTP ${response.status}`);
1772
+ // src/client/costDashboard.ts
1773
+ var padTwo = (value) => String(value).padStart(2, "0");
1774
+ var formatBucketKey = (epochMs, bucketBy) => {
1775
+ const date = new Date(epochMs);
1776
+ const y = date.getUTCFullYear();
1777
+ const m = padTwo(date.getUTCMonth() + 1);
1778
+ const d = padTwo(date.getUTCDate());
1779
+ const h = padTwo(date.getUTCHours());
1780
+ if (bucketBy === "month")
1781
+ return `${y}-${m}`;
1782
+ if (bucketBy === "day")
1783
+ return `${y}-${m}-${d}`;
1784
+ return `${y}-${m}-${d}T${h}`;
1785
+ };
1786
+ var isCostBreakdown = (value) => Boolean(value) && typeof value === "object" && typeof value.totalUsd === "number";
1787
+ var emptyBucket = (bucketKey) => ({
1788
+ bucketKey,
1789
+ callCount: 0,
1790
+ llmUsd: 0,
1791
+ sttUsd: 0,
1792
+ telephonyMinutes: 0,
1793
+ telephonyUsd: 0,
1794
+ totalUsd: 0,
1795
+ ttsUsd: 0
1796
+ });
1797
+ var accumulate = (bucket, payload) => {
1798
+ bucket.callCount += 1;
1799
+ bucket.llmUsd += payload.llm.usd;
1800
+ bucket.sttUsd += payload.stt.usd;
1801
+ bucket.ttsUsd += payload.tts.usd;
1802
+ bucket.telephonyUsd += payload.telephony.usd;
1803
+ bucket.telephonyMinutes += payload.telephony.minutes;
1804
+ bucket.totalUsd += payload.totalUsd;
1805
+ };
1806
+ var roundCurrency = (bucket) => {
1807
+ bucket.llmUsd = Math.round(bucket.llmUsd * 1e6) / 1e6;
1808
+ bucket.sttUsd = Math.round(bucket.sttUsd * 1e6) / 1e6;
1809
+ bucket.ttsUsd = Math.round(bucket.ttsUsd * 1e6) / 1e6;
1810
+ bucket.telephonyUsd = Math.round(bucket.telephonyUsd * 1e6) / 1e6;
1811
+ bucket.totalUsd = Math.round(bucket.totalUsd * 1e6) / 1e6;
1812
+ };
1813
+ var buildVoiceCostDashboardReport = (options) => {
1814
+ const bucketBy = options.bucketBy ?? "day";
1815
+ const fromMs = options.fromMs ?? Number.NEGATIVE_INFINITY;
1816
+ const toMs = options.toMs ?? Number.POSITIVE_INFINITY;
1817
+ const buckets = new Map;
1818
+ const grandTotal = emptyBucket("total");
1819
+ let minMs = Number.POSITIVE_INFINITY;
1820
+ let maxMs = Number.NEGATIVE_INFINITY;
1821
+ for (const event of options.events) {
1822
+ if (event.type !== "cost.ready")
1823
+ continue;
1824
+ if (event.at < fromMs || event.at > toMs)
1825
+ continue;
1826
+ if (!isCostBreakdown(event.payload))
1827
+ continue;
1828
+ minMs = Math.min(minMs, event.at);
1829
+ maxMs = Math.max(maxMs, event.at);
1830
+ const bucketKey = formatBucketKey(event.at, bucketBy);
1831
+ let bucket = buckets.get(bucketKey);
1832
+ if (!bucket) {
1833
+ bucket = emptyBucket(bucketKey);
1834
+ buckets.set(bucketKey, bucket);
1835
+ }
1836
+ accumulate(bucket, event.payload);
1837
+ accumulate(grandTotal, event.payload);
1470
1838
  }
1471
- return await response.json();
1839
+ for (const bucket of buckets.values()) {
1840
+ roundCurrency(bucket);
1841
+ }
1842
+ roundCurrency(grandTotal);
1843
+ return {
1844
+ buckets: Array.from(buckets.values()).sort((a, b) => a.bucketKey.localeCompare(b.bucketKey)),
1845
+ generatedAt: Date.now(),
1846
+ grandTotal,
1847
+ windowEndMs: Number.isFinite(maxMs) ? maxMs : 0,
1848
+ windowStartMs: Number.isFinite(minMs) ? minMs : 0
1849
+ };
1472
1850
  };
1473
- var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {}) => {
1474
- const listeners = new Set;
1475
- let closed = false;
1476
- let timer;
1477
- let snapshot = {
1478
- error: null,
1479
- isLoading: false,
1480
- providers: []
1851
+
1852
+ // src/angular/voice-cost-dashboard.service.ts
1853
+ var _dec = [
1854
+ Injectable3({ providedIn: "root" })
1855
+ ];
1856
+ var _init = __decoratorStart(undefined);
1857
+
1858
+ class VoiceCostDashboardService {
1859
+ build(options) {
1860
+ const events = signal3(options.events);
1861
+ const filters = signal3({
1862
+ bucketBy: options.bucketBy,
1863
+ fromMs: options.fromMs,
1864
+ toMs: options.toMs
1865
+ });
1866
+ const report = computed3(() => {
1867
+ const f = filters();
1868
+ return buildVoiceCostDashboardReport({
1869
+ bucketBy: f.bucketBy,
1870
+ events: events(),
1871
+ fromMs: f.fromMs,
1872
+ toMs: f.toMs
1873
+ });
1874
+ });
1875
+ return {
1876
+ currency: options.currency ?? "USD",
1877
+ report,
1878
+ setEvents: (next) => events.set(next),
1879
+ setFilters: (next) => filters.update((current) => ({
1880
+ ...current,
1881
+ bucketBy: next.bucketBy ?? current.bucketBy,
1882
+ fromMs: next.fromMs ?? current.fromMs,
1883
+ toMs: next.toMs ?? current.toMs
1884
+ })),
1885
+ title: options.title ?? "Voice cost dashboard"
1886
+ };
1887
+ }
1888
+ }
1889
+ VoiceCostDashboardService = __decorateElement(_init, 0, "VoiceCostDashboardService", _dec, VoiceCostDashboardService);
1890
+ __runInitializers(_init, 1, VoiceCostDashboardService);
1891
+ __decoratorMetadata(_init, VoiceCostDashboardService);
1892
+ let _VoiceCostDashboardService = VoiceCostDashboardService;
1893
+ // src/angular/voice-live-call-viewer.service.ts
1894
+ import { computed as computed4, Injectable as Injectable4, signal as signal4 } from "@angular/core";
1895
+
1896
+ // src/client/liveCallViewer.ts
1897
+ var EVENT_BUFFER_LIMIT = 200;
1898
+ var createLiveCallViewer = (options) => {
1899
+ const bufferLimit = options.bufferLimit ?? EVENT_BUFFER_LIMIT;
1900
+ const subscribers = new Set;
1901
+ let state = {
1902
+ agentState: "idle",
1903
+ callDurationMs: 0,
1904
+ events: [],
1905
+ isConnected: true,
1906
+ isLiveListening: true,
1907
+ partialTranscript: "",
1908
+ sessionId: options.sessionId
1481
1909
  };
1482
- const emit = () => {
1483
- for (const listener of listeners) {
1484
- listener();
1485
- }
1910
+ const startedAt = options.startedAt ?? Date.now();
1911
+ const notify = () => {
1912
+ for (const subscriber of subscribers)
1913
+ subscriber();
1486
1914
  };
1487
- const refresh = async () => {
1488
- if (closed) {
1489
- return snapshot.providers;
1915
+ const update = (next) => {
1916
+ state = { ...state, ...next };
1917
+ state.callDurationMs = Math.max(0, Date.now() - startedAt);
1918
+ state.agentState = deriveVoiceAgentUIState({
1919
+ hasActivePartial: state.partialTranscript.length > 0,
1920
+ isConnected: state.isConnected,
1921
+ isPlaying: false,
1922
+ isRecording: state.isLiveListening,
1923
+ lastAssistantAt: state.lastAssistantAt,
1924
+ lastTranscriptAt: state.lastTranscriptAt
1925
+ });
1926
+ notify();
1927
+ };
1928
+ const pushEvent = (event) => {
1929
+ const next = state.events.concat(event);
1930
+ if (next.length > bufferLimit) {
1931
+ next.splice(0, next.length - bufferLimit);
1490
1932
  }
1491
- snapshot = {
1933
+ update({ events: next });
1934
+ };
1935
+ return {
1936
+ applyControl: (control) => {
1937
+ pushEvent({
1938
+ at: Date.now(),
1939
+ detail: control.reason,
1940
+ kind: "lifecycle",
1941
+ title: `control:${control.type}`
1942
+ });
1943
+ },
1944
+ applyEvent: pushEvent,
1945
+ applyMonitorEvent: ({ payload, type }) => {
1946
+ pushEvent({
1947
+ at: Date.now(),
1948
+ detail: JSON.stringify(payload).slice(0, 240),
1949
+ kind: type === "call.lifecycle" ? "lifecycle" : "lifecycle",
1950
+ title: type
1951
+ });
1952
+ },
1953
+ getState: () => state,
1954
+ noteAgentAudio: (at) => {
1955
+ const ts = at ?? Date.now();
1956
+ update({ lastAssistantAt: ts });
1957
+ pushEvent({
1958
+ at: ts,
1959
+ kind: "agent_audio",
1960
+ title: "Agent audio frame"
1961
+ });
1962
+ },
1963
+ notePartial: (text, at) => {
1964
+ update({ partialTranscript: text });
1965
+ if (text) {
1966
+ pushEvent({
1967
+ at: at ?? Date.now(),
1968
+ detail: text,
1969
+ kind: "transcript",
1970
+ title: "Partial"
1971
+ });
1972
+ }
1973
+ },
1974
+ noteTranscript: (text, at) => {
1975
+ const ts = at ?? Date.now();
1976
+ update({ lastTranscriptAt: ts, partialTranscript: "" });
1977
+ pushEvent({
1978
+ at: ts,
1979
+ detail: text,
1980
+ kind: "transcript",
1981
+ title: "Final transcript"
1982
+ });
1983
+ },
1984
+ reset: (sessionId, startedAtOverride) => {
1985
+ state = {
1986
+ agentState: "idle",
1987
+ callDurationMs: 0,
1988
+ events: [],
1989
+ isConnected: true,
1990
+ isLiveListening: true,
1991
+ partialTranscript: "",
1992
+ sessionId
1993
+ };
1994
+ if (typeof startedAtOverride === "number") {}
1995
+ notify();
1996
+ },
1997
+ subscribe: (subscriber) => {
1998
+ subscribers.add(subscriber);
1999
+ return () => subscribers.delete(subscriber);
2000
+ }
2001
+ };
2002
+ };
2003
+
2004
+ // src/angular/voice-live-call-viewer.service.ts
2005
+ var _dec = [
2006
+ Injectable4({ providedIn: "root" })
2007
+ ];
2008
+ var _init = __decoratorStart(undefined);
2009
+
2010
+ class VoiceLiveCallViewerService {
2011
+ build(options) {
2012
+ const viewer = options.viewer ?? createLiveCallViewer(options);
2013
+ const stateSignal = signal4(viewer.getState());
2014
+ const unsubscribe = viewer.subscribe(() => {
2015
+ stateSignal.set(viewer.getState());
2016
+ });
2017
+ return {
2018
+ noteAgentAudio: (at) => viewer.noteAgentAudio(at),
2019
+ notePartial: (text, at) => viewer.notePartial(text, at),
2020
+ noteTranscript: (text, at) => viewer.noteTranscript(text, at),
2021
+ reset: (sessionId, startedAt) => viewer.reset(sessionId, startedAt),
2022
+ state: computed4(() => stateSignal()),
2023
+ stop: () => unsubscribe(),
2024
+ title: options.title ?? "Live call"
2025
+ };
2026
+ }
2027
+ }
2028
+ VoiceLiveCallViewerService = __decorateElement(_init, 0, "VoiceLiveCallViewerService", _dec, VoiceLiveCallViewerService);
2029
+ __runInitializers(_init, 1, VoiceLiveCallViewerService);
2030
+ __decoratorMetadata(_init, VoiceLiveCallViewerService);
2031
+ let _VoiceLiveCallViewerService = VoiceLiveCallViewerService;
2032
+ // src/angular/voice-replay-timeline.service.ts
2033
+ import { computed as computed5, Injectable as Injectable5, signal as signal5 } from "@angular/core";
2034
+
2035
+ // src/client/replayTimeline.ts
2036
+ var categorize = (entry) => {
2037
+ const event = entry.event.toLowerCase();
2038
+ if (event.startsWith("stt.") || event.includes("user"))
2039
+ return "user";
2040
+ if (event.startsWith("tts.") || event.includes("assistant") || event.includes("agent"))
2041
+ return "agent";
2042
+ if (event.startsWith("tool.") || event.includes("tool"))
2043
+ return "tool";
2044
+ return "lifecycle";
2045
+ };
2046
+ var buildReplayTimelineReport = (input) => {
2047
+ const events = [];
2048
+ let summaryAgentTurns = 0;
2049
+ let summaryUserTurns = 0;
2050
+ let summaryToolCalls = 0;
2051
+ for (const entry of input.artifact.timeline ?? []) {
2052
+ const category = categorize(entry);
2053
+ if (category === "user")
2054
+ summaryUserTurns += 1;
2055
+ if (category === "agent")
2056
+ summaryAgentTurns += 1;
2057
+ if (category === "tool")
2058
+ summaryToolCalls += 1;
2059
+ events.push({
2060
+ at: entry.atMs,
2061
+ category,
2062
+ detail: entry.text ?? entry.reason,
2063
+ durationMs: entry.chunkDurationMs,
2064
+ label: entry.event
2065
+ });
2066
+ }
2067
+ events.sort((a, b) => a.at - b.at);
2068
+ const first = events[0]?.at ?? 0;
2069
+ const last = events.at(-1)?.at ?? first;
2070
+ return {
2071
+ duration: last - first,
2072
+ events,
2073
+ metadata: {
2074
+ artifactId: input.artifact.id ?? "",
2075
+ title: input.artifact.title
2076
+ },
2077
+ startedAt: first,
2078
+ summary: {
2079
+ agentTurns: summaryAgentTurns,
2080
+ toolCalls: summaryToolCalls,
2081
+ userTurns: summaryUserTurns
2082
+ }
2083
+ };
2084
+ };
2085
+
2086
+ // src/angular/voice-replay-timeline.service.ts
2087
+ var _dec = [
2088
+ Injectable5({ providedIn: "root" })
2089
+ ];
2090
+ var _init = __decoratorStart(undefined);
2091
+
2092
+ class VoiceReplayTimelineService {
2093
+ build(options) {
2094
+ const artifact = signal5(options.artifact);
2095
+ const report = computed5(() => buildReplayTimelineReport({ artifact: artifact() }));
2096
+ return {
2097
+ report,
2098
+ setArtifact: (next) => artifact.set(next),
2099
+ title: options.title
2100
+ };
2101
+ }
2102
+ }
2103
+ VoiceReplayTimelineService = __decorateElement(_init, 0, "VoiceReplayTimelineService", _dec, VoiceReplayTimelineService);
2104
+ __runInitializers(_init, 1, VoiceReplayTimelineService);
2105
+ __decoratorMetadata(_init, VoiceReplayTimelineService);
2106
+ let _VoiceReplayTimelineService = VoiceReplayTimelineService;
2107
+ // src/angular/voice-platform-coverage.service.ts
2108
+ import { computed as computed6, Injectable as Injectable6, signal as signal6 } from "@angular/core";
2109
+
2110
+ // src/client/platformCoverage.ts
2111
+ var fetchVoicePlatformCoverage = async (path = "/api/voice/platform-coverage", options = {}) => {
2112
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2113
+ const response = await fetchImpl(path);
2114
+ if (!response.ok) {
2115
+ throw new Error(`Voice platform coverage failed: HTTP ${response.status}`);
2116
+ }
2117
+ return await response.json();
2118
+ };
2119
+ var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", options = {}) => {
2120
+ const listeners = new Set;
2121
+ let closed = false;
2122
+ let timer;
2123
+ let snapshot = {
2124
+ error: null,
2125
+ isLoading: false
2126
+ };
2127
+ const emit = () => {
2128
+ for (const listener of listeners) {
2129
+ listener();
2130
+ }
2131
+ };
2132
+ const refresh = async () => {
2133
+ if (closed) {
2134
+ return snapshot.report;
2135
+ }
2136
+ snapshot = {
2137
+ ...snapshot,
2138
+ error: null,
2139
+ isLoading: true
2140
+ };
2141
+ emit();
2142
+ try {
2143
+ const report = await fetchVoicePlatformCoverage(path, options);
2144
+ snapshot = {
2145
+ error: null,
2146
+ isLoading: false,
2147
+ report,
2148
+ updatedAt: Date.now()
2149
+ };
2150
+ emit();
2151
+ return report;
2152
+ } catch (error) {
2153
+ snapshot = {
2154
+ ...snapshot,
2155
+ error: error instanceof Error ? error.message : String(error),
2156
+ isLoading: false
2157
+ };
2158
+ emit();
2159
+ throw error;
2160
+ }
2161
+ };
2162
+ const close = () => {
2163
+ closed = true;
2164
+ if (timer) {
2165
+ clearInterval(timer);
2166
+ timer = undefined;
2167
+ }
2168
+ listeners.clear();
2169
+ };
2170
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
2171
+ timer = setInterval(() => {
2172
+ refresh().catch(() => {});
2173
+ }, options.intervalMs);
2174
+ }
2175
+ return {
2176
+ close,
2177
+ getServerSnapshot: () => snapshot,
2178
+ getSnapshot: () => snapshot,
2179
+ refresh,
2180
+ subscribe: (listener) => {
2181
+ listeners.add(listener);
2182
+ return () => {
2183
+ listeners.delete(listener);
2184
+ };
2185
+ }
2186
+ };
2187
+ };
2188
+
2189
+ // src/angular/voice-platform-coverage.service.ts
2190
+ var _dec = [
2191
+ Injectable6({ providedIn: "root" })
2192
+ ];
2193
+ var _init = __decoratorStart(undefined);
2194
+
2195
+ class VoicePlatformCoverageService {
2196
+ connect(path = "/api/voice/platform-coverage", options = {}) {
2197
+ const store = createVoicePlatformCoverageStore(path, options);
2198
+ const errorSignal = signal6(null);
2199
+ const isLoadingSignal = signal6(false);
2200
+ const reportSignal = signal6(undefined);
2201
+ const updatedAtSignal = signal6(undefined);
2202
+ const sync = () => {
2203
+ const snapshot = store.getSnapshot();
2204
+ errorSignal.set(snapshot.error);
2205
+ isLoadingSignal.set(snapshot.isLoading);
2206
+ reportSignal.set(snapshot.report);
2207
+ updatedAtSignal.set(snapshot.updatedAt);
2208
+ };
2209
+ const unsubscribe = store.subscribe(sync);
2210
+ sync();
2211
+ if (typeof window !== "undefined") {
2212
+ store.refresh().catch(() => {});
2213
+ }
2214
+ return {
2215
+ close: () => {
2216
+ unsubscribe();
2217
+ store.close();
2218
+ },
2219
+ error: computed6(() => errorSignal()),
2220
+ isLoading: computed6(() => isLoadingSignal()),
2221
+ refresh: store.refresh,
2222
+ report: computed6(() => reportSignal()),
2223
+ updatedAt: computed6(() => updatedAtSignal())
2224
+ };
2225
+ }
2226
+ }
2227
+ VoicePlatformCoverageService = __decorateElement(_init, 0, "VoicePlatformCoverageService", _dec, VoicePlatformCoverageService);
2228
+ __runInitializers(_init, 1, VoicePlatformCoverageService);
2229
+ __decoratorMetadata(_init, VoicePlatformCoverageService);
2230
+ let _VoicePlatformCoverageService = VoicePlatformCoverageService;
2231
+ // src/angular/voice-proof-trends.service.ts
2232
+ import { computed as computed7, Injectable as Injectable7, signal as signal7 } from "@angular/core";
2233
+
2234
+ // src/client/proofTrends.ts
2235
+ var fetchVoiceProofTrends = async (path = "/api/voice/proof-trends", options = {}) => {
2236
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2237
+ const response = await fetchImpl(path);
2238
+ if (!response.ok) {
2239
+ throw new Error(`Voice proof trends failed: HTTP ${response.status}`);
2240
+ }
2241
+ return await response.json();
2242
+ };
2243
+ var createVoiceProofTrendsStore = (path = "/api/voice/proof-trends", options = {}) => {
2244
+ const listeners = new Set;
2245
+ let closed = false;
2246
+ let timer;
2247
+ let snapshot = {
2248
+ error: null,
2249
+ isLoading: false
2250
+ };
2251
+ const emit = () => {
2252
+ for (const listener of listeners) {
2253
+ listener();
2254
+ }
2255
+ };
2256
+ const refresh = async () => {
2257
+ if (closed) {
2258
+ return snapshot.report;
2259
+ }
2260
+ snapshot = {
2261
+ ...snapshot,
2262
+ error: null,
2263
+ isLoading: true
2264
+ };
2265
+ emit();
2266
+ try {
2267
+ const report = await fetchVoiceProofTrends(path, options);
2268
+ snapshot = {
2269
+ error: null,
2270
+ isLoading: false,
2271
+ report,
2272
+ updatedAt: Date.now()
2273
+ };
2274
+ emit();
2275
+ return report;
2276
+ } catch (error) {
2277
+ snapshot = {
2278
+ ...snapshot,
2279
+ error: error instanceof Error ? error.message : String(error),
2280
+ isLoading: false
2281
+ };
2282
+ emit();
2283
+ throw error;
2284
+ }
2285
+ };
2286
+ const close = () => {
2287
+ closed = true;
2288
+ if (timer) {
2289
+ clearInterval(timer);
2290
+ timer = undefined;
2291
+ }
2292
+ listeners.clear();
2293
+ };
2294
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
2295
+ timer = setInterval(() => {
2296
+ refresh().catch(() => {});
2297
+ }, options.intervalMs);
2298
+ }
2299
+ return {
2300
+ close,
2301
+ getServerSnapshot: () => snapshot,
2302
+ getSnapshot: () => snapshot,
2303
+ refresh,
2304
+ subscribe: (listener) => {
2305
+ listeners.add(listener);
2306
+ return () => {
2307
+ listeners.delete(listener);
2308
+ };
2309
+ }
2310
+ };
2311
+ };
2312
+
2313
+ // src/angular/voice-proof-trends.service.ts
2314
+ var _dec = [
2315
+ Injectable7({ providedIn: "root" })
2316
+ ];
2317
+ var _init = __decoratorStart(undefined);
2318
+
2319
+ class VoiceProofTrendsService {
2320
+ connect(path = "/api/voice/proof-trends", options = {}) {
2321
+ const store = createVoiceProofTrendsStore(path, options);
2322
+ const errorSignal = signal7(null);
2323
+ const isLoadingSignal = signal7(false);
2324
+ const reportSignal = signal7(undefined);
2325
+ const updatedAtSignal = signal7(undefined);
2326
+ const sync = () => {
2327
+ const snapshot = store.getSnapshot();
2328
+ errorSignal.set(snapshot.error);
2329
+ isLoadingSignal.set(snapshot.isLoading);
2330
+ reportSignal.set(snapshot.report);
2331
+ updatedAtSignal.set(snapshot.updatedAt);
2332
+ };
2333
+ const unsubscribe = store.subscribe(sync);
2334
+ sync();
2335
+ if (typeof window !== "undefined") {
2336
+ store.refresh().catch(() => {});
2337
+ }
2338
+ return {
2339
+ close: () => {
2340
+ unsubscribe();
2341
+ store.close();
2342
+ },
2343
+ error: computed7(() => errorSignal()),
2344
+ isLoading: computed7(() => isLoadingSignal()),
2345
+ refresh: store.refresh,
2346
+ report: computed7(() => reportSignal()),
2347
+ updatedAt: computed7(() => updatedAtSignal())
2348
+ };
2349
+ }
2350
+ }
2351
+ VoiceProofTrendsService = __decorateElement(_init, 0, "VoiceProofTrendsService", _dec, VoiceProofTrendsService);
2352
+ __runInitializers(_init, 1, VoiceProofTrendsService);
2353
+ __decoratorMetadata(_init, VoiceProofTrendsService);
2354
+ let _VoiceProofTrendsService = VoiceProofTrendsService;
2355
+ // src/angular/voice-reconnect-profile-evidence.service.ts
2356
+ import { computed as computed8, Injectable as Injectable8, signal as signal8 } from "@angular/core";
2357
+
2358
+ // src/client/reconnectProfileEvidence.ts
2359
+ var fetchVoiceReconnectProfileEvidence = async (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
2360
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2361
+ const response = await fetchImpl(path);
2362
+ if (!response.ok) {
2363
+ throw new Error(`Voice reconnect profile evidence failed: HTTP ${response.status}`);
2364
+ }
2365
+ return await response.json();
2366
+ };
2367
+ var createVoiceReconnectProfileEvidenceStore = (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
2368
+ const listeners = new Set;
2369
+ let closed = false;
2370
+ let timer;
2371
+ let snapshot = {
2372
+ error: null,
2373
+ isLoading: false
2374
+ };
2375
+ const emit = () => {
2376
+ for (const listener of listeners) {
2377
+ listener();
2378
+ }
2379
+ };
2380
+ const refresh = async () => {
2381
+ if (closed) {
2382
+ return snapshot.report;
2383
+ }
2384
+ snapshot = { ...snapshot, error: null, isLoading: true };
2385
+ emit();
2386
+ try {
2387
+ const report = await fetchVoiceReconnectProfileEvidence(path, options);
2388
+ snapshot = {
2389
+ error: null,
2390
+ isLoading: false,
2391
+ report,
2392
+ updatedAt: Date.now()
2393
+ };
2394
+ emit();
2395
+ return report;
2396
+ } catch (error) {
2397
+ snapshot = {
2398
+ ...snapshot,
2399
+ error: error instanceof Error ? error.message : String(error),
2400
+ isLoading: false
2401
+ };
2402
+ emit();
2403
+ throw error;
2404
+ }
2405
+ };
2406
+ const close = () => {
2407
+ closed = true;
2408
+ if (timer) {
2409
+ clearInterval(timer);
2410
+ timer = undefined;
2411
+ }
2412
+ listeners.clear();
2413
+ };
2414
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
2415
+ timer = setInterval(() => {
2416
+ refresh().catch(() => {});
2417
+ }, options.intervalMs);
2418
+ }
2419
+ return {
2420
+ close,
2421
+ getServerSnapshot: () => snapshot,
2422
+ getSnapshot: () => snapshot,
2423
+ refresh,
2424
+ subscribe: (listener) => {
2425
+ listeners.add(listener);
2426
+ return () => {
2427
+ listeners.delete(listener);
2428
+ };
2429
+ }
2430
+ };
2431
+ };
2432
+
2433
+ // src/angular/voice-reconnect-profile-evidence.service.ts
2434
+ var _dec = [
2435
+ Injectable8({ providedIn: "root" })
2436
+ ];
2437
+ var _init = __decoratorStart(undefined);
2438
+
2439
+ class VoiceReconnectProfileEvidenceService {
2440
+ connect(path = "/api/voice/reconnect-profile-evidence", options = {}) {
2441
+ const store = createVoiceReconnectProfileEvidenceStore(path, options);
2442
+ const errorSignal = signal8(null);
2443
+ const isLoadingSignal = signal8(false);
2444
+ const reportSignal = signal8(undefined);
2445
+ const updatedAtSignal = signal8(undefined);
2446
+ const sync = () => {
2447
+ const snapshot = store.getSnapshot();
2448
+ errorSignal.set(snapshot.error);
2449
+ isLoadingSignal.set(snapshot.isLoading);
2450
+ reportSignal.set(snapshot.report);
2451
+ updatedAtSignal.set(snapshot.updatedAt);
2452
+ };
2453
+ const unsubscribe = store.subscribe(sync);
2454
+ sync();
2455
+ if (typeof window !== "undefined") {
2456
+ store.refresh().catch(() => {});
2457
+ }
2458
+ return {
2459
+ close: () => {
2460
+ unsubscribe();
2461
+ store.close();
2462
+ },
2463
+ error: computed8(() => errorSignal()),
2464
+ isLoading: computed8(() => isLoadingSignal()),
2465
+ refresh: store.refresh,
2466
+ report: computed8(() => reportSignal()),
2467
+ updatedAt: computed8(() => updatedAtSignal())
2468
+ };
2469
+ }
2470
+ }
2471
+ VoiceReconnectProfileEvidenceService = __decorateElement(_init, 0, "VoiceReconnectProfileEvidenceService", _dec, VoiceReconnectProfileEvidenceService);
2472
+ __runInitializers(_init, 1, VoiceReconnectProfileEvidenceService);
2473
+ __decoratorMetadata(_init, VoiceReconnectProfileEvidenceService);
2474
+ let _VoiceReconnectProfileEvidenceService = VoiceReconnectProfileEvidenceService;
2475
+ // src/angular/voice-call-debugger.service.ts
2476
+ import { computed as computed9, Injectable as Injectable9, signal as signal9 } from "@angular/core";
2477
+
2478
+ // src/client/callDebugger.ts
2479
+ var fetchVoiceCallDebugger = async (path, options = {}) => {
2480
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2481
+ const response = await fetchImpl(path);
2482
+ if (!response.ok) {
2483
+ throw new Error(`Voice call debugger failed: HTTP ${response.status}`);
2484
+ }
2485
+ return await response.json();
2486
+ };
2487
+ var createVoiceCallDebuggerStore = (path, options = {}) => {
2488
+ const listeners = new Set;
2489
+ let closed = false;
2490
+ let timer;
2491
+ let snapshot = {
2492
+ error: null,
2493
+ isLoading: false
2494
+ };
2495
+ const emit = () => {
2496
+ for (const listener of listeners) {
2497
+ listener();
2498
+ }
2499
+ };
2500
+ const refresh = async () => {
2501
+ if (closed) {
2502
+ return snapshot.report;
2503
+ }
2504
+ snapshot = { ...snapshot, error: null, isLoading: true };
2505
+ emit();
2506
+ try {
2507
+ const report = await fetchVoiceCallDebugger(path, options);
2508
+ snapshot = {
2509
+ error: null,
2510
+ isLoading: false,
2511
+ report,
2512
+ updatedAt: Date.now()
2513
+ };
2514
+ emit();
2515
+ return report;
2516
+ } catch (error) {
2517
+ snapshot = {
2518
+ ...snapshot,
2519
+ error: error instanceof Error ? error.message : String(error),
2520
+ isLoading: false
2521
+ };
2522
+ emit();
2523
+ throw error;
2524
+ }
2525
+ };
2526
+ const close = () => {
2527
+ closed = true;
2528
+ if (timer) {
2529
+ clearInterval(timer);
2530
+ timer = undefined;
2531
+ }
2532
+ listeners.clear();
2533
+ };
2534
+ if (options.intervalMs && options.intervalMs > 0) {
2535
+ timer = setInterval(() => {
2536
+ refresh().catch(() => {});
2537
+ }, options.intervalMs);
2538
+ }
2539
+ return {
2540
+ close,
2541
+ getServerSnapshot: () => snapshot,
2542
+ getSnapshot: () => snapshot,
2543
+ refresh,
2544
+ subscribe: (listener) => {
2545
+ listeners.add(listener);
2546
+ return () => {
2547
+ listeners.delete(listener);
2548
+ };
2549
+ }
2550
+ };
2551
+ };
2552
+
2553
+ // src/angular/voice-call-debugger.service.ts
2554
+ var _dec = [
2555
+ Injectable9({ providedIn: "root" })
2556
+ ];
2557
+ var _init = __decoratorStart(undefined);
2558
+
2559
+ class VoiceCallDebuggerService {
2560
+ connect(path, options = {}) {
2561
+ const store = createVoiceCallDebuggerStore(path, options);
2562
+ const errorSignal = signal9(null);
2563
+ const isLoadingSignal = signal9(false);
2564
+ const reportSignal = signal9(undefined);
2565
+ const updatedAtSignal = signal9(undefined);
2566
+ const sync = () => {
2567
+ const state = store.getSnapshot();
2568
+ errorSignal.set(state.error);
2569
+ isLoadingSignal.set(state.isLoading);
2570
+ reportSignal.set(state.report);
2571
+ updatedAtSignal.set(state.updatedAt);
2572
+ };
2573
+ const unsubscribe = store.subscribe(sync);
2574
+ sync();
2575
+ store.refresh().catch(() => {});
2576
+ return {
2577
+ close: () => {
2578
+ unsubscribe();
2579
+ store.close();
2580
+ },
2581
+ error: computed9(() => errorSignal()),
2582
+ isLoading: computed9(() => isLoadingSignal()),
2583
+ refresh: store.refresh,
2584
+ report: computed9(() => reportSignal()),
2585
+ updatedAt: computed9(() => updatedAtSignal())
2586
+ };
2587
+ }
2588
+ }
2589
+ VoiceCallDebuggerService = __decorateElement(_init, 0, "VoiceCallDebuggerService", _dec, VoiceCallDebuggerService);
2590
+ __runInitializers(_init, 1, VoiceCallDebuggerService);
2591
+ __decoratorMetadata(_init, VoiceCallDebuggerService);
2592
+ let _VoiceCallDebuggerService = VoiceCallDebuggerService;
2593
+ // src/angular/voice-session-snapshot.service.ts
2594
+ import { computed as computed10, Injectable as Injectable10, signal as signal10 } from "@angular/core";
2595
+
2596
+ // src/client/sessionSnapshot.ts
2597
+ var withTurnId = (path, turnId) => {
2598
+ if (!turnId) {
2599
+ return path;
2600
+ }
2601
+ const url = new URL(path, "http://absolutejs.local");
2602
+ url.searchParams.set("turnId", turnId);
2603
+ return `${url.pathname}${url.search}`;
2604
+ };
2605
+ var fetchVoiceSessionSnapshot = async (path, options = {}) => {
2606
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2607
+ const response = await fetchImpl(withTurnId(path, options.turnId));
2608
+ if (!response.ok) {
2609
+ throw new Error(`Voice session snapshot failed: HTTP ${response.status}`);
2610
+ }
2611
+ return await response.json();
2612
+ };
2613
+ var createVoiceSessionSnapshotStore = (path, options = {}) => {
2614
+ const listeners = new Set;
2615
+ let closed = false;
2616
+ let timer;
2617
+ let snapshot = {
2618
+ error: null,
2619
+ isLoading: false
2620
+ };
2621
+ const emit = () => {
2622
+ for (const listener of listeners) {
2623
+ listener();
2624
+ }
2625
+ };
2626
+ const refresh = async () => {
2627
+ if (closed) {
2628
+ return snapshot.snapshot;
2629
+ }
2630
+ snapshot = { ...snapshot, error: null, isLoading: true };
2631
+ emit();
2632
+ try {
2633
+ const next = await fetchVoiceSessionSnapshot(path, options);
2634
+ snapshot = {
2635
+ error: null,
2636
+ isLoading: false,
2637
+ snapshot: next,
2638
+ updatedAt: Date.now()
2639
+ };
2640
+ emit();
2641
+ return next;
2642
+ } catch (error) {
2643
+ snapshot = {
2644
+ ...snapshot,
2645
+ error: error instanceof Error ? error.message : String(error),
2646
+ isLoading: false
2647
+ };
2648
+ emit();
2649
+ throw error;
2650
+ }
2651
+ };
2652
+ const download = () => {
2653
+ const current = snapshot.snapshot;
2654
+ if (current === undefined) {
2655
+ throw new Error("Voice session snapshot has not been loaded.");
2656
+ }
2657
+ return new Blob([JSON.stringify(current, null, 2)], {
2658
+ type: "application/json"
2659
+ });
2660
+ };
2661
+ const close = () => {
2662
+ closed = true;
2663
+ if (timer) {
2664
+ clearInterval(timer);
2665
+ timer = undefined;
2666
+ }
2667
+ listeners.clear();
2668
+ };
2669
+ if (options.intervalMs && options.intervalMs > 0) {
2670
+ timer = setInterval(() => {
2671
+ refresh().catch(() => {});
2672
+ }, options.intervalMs);
2673
+ }
2674
+ return {
2675
+ close,
2676
+ download,
2677
+ getServerSnapshot: () => snapshot,
2678
+ getSnapshot: () => snapshot,
2679
+ refresh,
2680
+ subscribe: (listener) => {
2681
+ listeners.add(listener);
2682
+ return () => {
2683
+ listeners.delete(listener);
2684
+ };
2685
+ }
2686
+ };
2687
+ };
2688
+
2689
+ // src/angular/voice-session-snapshot.service.ts
2690
+ var _dec = [
2691
+ Injectable10({ providedIn: "root" })
2692
+ ];
2693
+ var _init = __decoratorStart(undefined);
2694
+
2695
+ class VoiceSessionSnapshotService {
2696
+ connect(path, options = {}) {
2697
+ const store = createVoiceSessionSnapshotStore(path, options);
2698
+ const errorSignal = signal10(null);
2699
+ const isLoadingSignal = signal10(false);
2700
+ const snapshotSignal = signal10(undefined);
2701
+ const updatedAtSignal = signal10(undefined);
2702
+ const sync = () => {
2703
+ const state = store.getSnapshot();
2704
+ errorSignal.set(state.error);
2705
+ isLoadingSignal.set(state.isLoading);
2706
+ snapshotSignal.set(state.snapshot);
2707
+ updatedAtSignal.set(state.updatedAt);
2708
+ };
2709
+ const unsubscribe = store.subscribe(sync);
2710
+ sync();
2711
+ store.refresh().catch(() => {});
2712
+ return {
2713
+ close: () => {
2714
+ unsubscribe();
2715
+ store.close();
2716
+ },
2717
+ download: store.download,
2718
+ error: computed10(() => errorSignal()),
2719
+ isLoading: computed10(() => isLoadingSignal()),
2720
+ refresh: store.refresh,
2721
+ snapshot: computed10(() => snapshotSignal()),
2722
+ updatedAt: computed10(() => updatedAtSignal())
2723
+ };
2724
+ }
2725
+ }
2726
+ VoiceSessionSnapshotService = __decorateElement(_init, 0, "VoiceSessionSnapshotService", _dec, VoiceSessionSnapshotService);
2727
+ __runInitializers(_init, 1, VoiceSessionSnapshotService);
2728
+ __decoratorMetadata(_init, VoiceSessionSnapshotService);
2729
+ let _VoiceSessionSnapshotService = VoiceSessionSnapshotService;
2730
+ // src/angular/voice-session-observability.service.ts
2731
+ import { computed as computed11, Injectable as Injectable11, signal as signal11 } from "@angular/core";
2732
+
2733
+ // src/client/sessionObservability.ts
2734
+ var fetchVoiceSessionObservability = async (path, options = {}) => {
2735
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2736
+ const response = await fetchImpl(path);
2737
+ if (!response.ok) {
2738
+ throw new Error(`Voice session observability failed: HTTP ${response.status}`);
2739
+ }
2740
+ return await response.json();
2741
+ };
2742
+ var createVoiceSessionObservabilityStore = (path, options = {}) => {
2743
+ const listeners = new Set;
2744
+ let closed = false;
2745
+ let timer;
2746
+ let snapshot = {
2747
+ error: null,
2748
+ isLoading: false,
2749
+ report: null
2750
+ };
2751
+ const emit = () => {
2752
+ for (const listener of listeners) {
2753
+ listener();
2754
+ }
2755
+ };
2756
+ const refresh = async () => {
2757
+ if (closed) {
2758
+ return snapshot.report;
2759
+ }
2760
+ snapshot = {
2761
+ ...snapshot,
2762
+ error: null,
2763
+ isLoading: true
2764
+ };
2765
+ emit();
2766
+ try {
2767
+ const report = await fetchVoiceSessionObservability(path, options);
2768
+ snapshot = {
2769
+ error: null,
2770
+ isLoading: false,
2771
+ report,
2772
+ updatedAt: Date.now()
2773
+ };
2774
+ emit();
2775
+ return report;
2776
+ } catch (error) {
2777
+ snapshot = {
2778
+ ...snapshot,
2779
+ error: error instanceof Error ? error.message : String(error),
2780
+ isLoading: false
2781
+ };
2782
+ emit();
2783
+ throw error;
2784
+ }
2785
+ };
2786
+ const close = () => {
2787
+ closed = true;
2788
+ if (timer) {
2789
+ clearInterval(timer);
2790
+ timer = undefined;
2791
+ }
2792
+ listeners.clear();
2793
+ };
2794
+ if (options.intervalMs && options.intervalMs > 0) {
2795
+ timer = setInterval(() => {
2796
+ refresh().catch(() => {});
2797
+ }, options.intervalMs);
2798
+ }
2799
+ return {
2800
+ close,
2801
+ getServerSnapshot: () => snapshot,
2802
+ getSnapshot: () => snapshot,
2803
+ refresh,
2804
+ subscribe: (listener) => {
2805
+ listeners.add(listener);
2806
+ return () => {
2807
+ listeners.delete(listener);
2808
+ };
2809
+ }
2810
+ };
2811
+ };
2812
+
2813
+ // src/angular/voice-session-observability.service.ts
2814
+ var _dec = [
2815
+ Injectable11({ providedIn: "root" })
2816
+ ];
2817
+ var _init = __decoratorStart(undefined);
2818
+
2819
+ class VoiceSessionObservabilityService {
2820
+ connect(path = "/api/voice/session-observability/latest", options = {}) {
2821
+ const store = createVoiceSessionObservabilityStore(path, options);
2822
+ const errorSignal = signal11(null);
2823
+ const isLoadingSignal = signal11(false);
2824
+ const reportSignal = signal11(null);
2825
+ const updatedAtSignal = signal11(undefined);
2826
+ const sync = () => {
2827
+ const snapshot = store.getSnapshot();
2828
+ errorSignal.set(snapshot.error);
2829
+ isLoadingSignal.set(snapshot.isLoading);
2830
+ reportSignal.set(snapshot.report);
2831
+ updatedAtSignal.set(snapshot.updatedAt);
2832
+ };
2833
+ const unsubscribe = store.subscribe(sync);
2834
+ sync();
2835
+ store.refresh().catch(() => {});
2836
+ return {
2837
+ close: () => {
2838
+ unsubscribe();
2839
+ store.close();
2840
+ },
2841
+ error: computed11(() => errorSignal()),
2842
+ isLoading: computed11(() => isLoadingSignal()),
2843
+ refresh: store.refresh,
2844
+ report: computed11(() => reportSignal()),
2845
+ updatedAt: computed11(() => updatedAtSignal())
2846
+ };
2847
+ }
2848
+ }
2849
+ VoiceSessionObservabilityService = __decorateElement(_init, 0, "VoiceSessionObservabilityService", _dec, VoiceSessionObservabilityService);
2850
+ __runInitializers(_init, 1, VoiceSessionObservabilityService);
2851
+ __decoratorMetadata(_init, VoiceSessionObservabilityService);
2852
+ let _VoiceSessionObservabilityService = VoiceSessionObservabilityService;
2853
+ // src/angular/voice-profile-comparison.service.ts
2854
+ import { computed as computed12, Injectable as Injectable12, signal as signal12 } from "@angular/core";
2855
+
2856
+ // src/client/profileComparison.ts
2857
+ var fetchVoiceProfileComparison = async (path = "/api/voice/real-call-profile-history", options = {}) => {
2858
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2859
+ const response = await fetchImpl(path);
2860
+ if (!response.ok) {
2861
+ throw new Error(`Voice profile comparison failed: HTTP ${response.status}`);
2862
+ }
2863
+ return await response.json();
2864
+ };
2865
+ var createVoiceProfileComparisonStore = (path = "/api/voice/real-call-profile-history", options = {}) => {
2866
+ const listeners = new Set;
2867
+ let closed = false;
2868
+ let timer;
2869
+ let snapshot = {
2870
+ error: null,
2871
+ isLoading: false
2872
+ };
2873
+ const emit = () => {
2874
+ for (const listener of listeners) {
2875
+ listener();
2876
+ }
2877
+ };
2878
+ const refresh = async () => {
2879
+ if (closed) {
2880
+ return snapshot.report;
2881
+ }
2882
+ snapshot = { ...snapshot, error: null, isLoading: true };
2883
+ emit();
2884
+ try {
2885
+ const report = await fetchVoiceProfileComparison(path, options);
2886
+ snapshot = {
2887
+ error: null,
2888
+ isLoading: false,
2889
+ report,
2890
+ updatedAt: Date.now()
2891
+ };
2892
+ emit();
2893
+ return report;
2894
+ } catch (error) {
2895
+ snapshot = {
2896
+ ...snapshot,
2897
+ error: error instanceof Error ? error.message : String(error),
2898
+ isLoading: false
2899
+ };
2900
+ emit();
2901
+ throw error;
2902
+ }
2903
+ };
2904
+ const close = () => {
2905
+ closed = true;
2906
+ if (timer) {
2907
+ clearInterval(timer);
2908
+ timer = undefined;
2909
+ }
2910
+ listeners.clear();
2911
+ };
2912
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
2913
+ timer = setInterval(() => {
2914
+ refresh().catch(() => {});
2915
+ }, options.intervalMs);
2916
+ }
2917
+ return {
2918
+ close,
2919
+ getServerSnapshot: () => snapshot,
2920
+ getSnapshot: () => snapshot,
2921
+ refresh,
2922
+ subscribe: (listener) => {
2923
+ listeners.add(listener);
2924
+ return () => {
2925
+ listeners.delete(listener);
2926
+ };
2927
+ }
2928
+ };
2929
+ };
2930
+
2931
+ // src/angular/voice-profile-comparison.service.ts
2932
+ var _dec = [
2933
+ Injectable12({ providedIn: "root" })
2934
+ ];
2935
+ var _init = __decoratorStart(undefined);
2936
+
2937
+ class VoiceProfileComparisonService {
2938
+ connect(path = "/api/voice/real-call-profile-history", options = {}) {
2939
+ const store = createVoiceProfileComparisonStore(path, options);
2940
+ const errorSignal = signal12(null);
2941
+ const isLoadingSignal = signal12(false);
2942
+ const reportSignal = signal12(undefined);
2943
+ const updatedAtSignal = signal12(undefined);
2944
+ const sync = () => {
2945
+ const snapshot = store.getSnapshot();
2946
+ errorSignal.set(snapshot.error);
2947
+ isLoadingSignal.set(snapshot.isLoading);
2948
+ reportSignal.set(snapshot.report);
2949
+ updatedAtSignal.set(snapshot.updatedAt);
2950
+ };
2951
+ const unsubscribe = store.subscribe(sync);
2952
+ sync();
2953
+ if (typeof window !== "undefined") {
2954
+ store.refresh().catch(() => {});
2955
+ }
2956
+ return {
2957
+ close: () => {
2958
+ unsubscribe();
2959
+ store.close();
2960
+ },
2961
+ error: computed12(() => errorSignal()),
2962
+ isLoading: computed12(() => isLoadingSignal()),
2963
+ refresh: store.refresh,
2964
+ report: computed12(() => reportSignal()),
2965
+ updatedAt: computed12(() => updatedAtSignal())
2966
+ };
2967
+ }
2968
+ }
2969
+ VoiceProfileComparisonService = __decorateElement(_init, 0, "VoiceProfileComparisonService", _dec, VoiceProfileComparisonService);
2970
+ __runInitializers(_init, 1, VoiceProfileComparisonService);
2971
+ __decoratorMetadata(_init, VoiceProfileComparisonService);
2972
+ let _VoiceProfileComparisonService = VoiceProfileComparisonService;
2973
+ // src/angular/voice-readiness-failures.service.ts
2974
+ import { computed as computed13, Injectable as Injectable13, signal as signal13 } from "@angular/core";
2975
+
2976
+ // src/client/readinessFailures.ts
2977
+ var fetchVoiceReadinessFailures = async (path = "/api/production-readiness", options = {}) => {
2978
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2979
+ const response = await fetchImpl(path);
2980
+ if (!response.ok) {
2981
+ throw new Error(`Voice readiness failed: HTTP ${response.status}`);
2982
+ }
2983
+ return await response.json();
2984
+ };
2985
+ var createVoiceReadinessFailuresStore = (path = "/api/production-readiness", options = {}) => {
2986
+ const listeners = new Set;
2987
+ let closed = false;
2988
+ let timer;
2989
+ let snapshot = {
2990
+ error: null,
2991
+ isLoading: false
2992
+ };
2993
+ const emit = () => {
2994
+ for (const listener of listeners) {
2995
+ listener();
2996
+ }
2997
+ };
2998
+ const refresh = async () => {
2999
+ if (closed) {
3000
+ return snapshot.report;
3001
+ }
3002
+ snapshot = { ...snapshot, error: null, isLoading: true };
3003
+ emit();
3004
+ try {
3005
+ const report = await fetchVoiceReadinessFailures(path, options);
3006
+ snapshot = {
3007
+ error: null,
3008
+ isLoading: false,
3009
+ report,
3010
+ updatedAt: Date.now()
3011
+ };
3012
+ emit();
3013
+ return report;
3014
+ } catch (error) {
3015
+ snapshot = {
3016
+ ...snapshot,
3017
+ error: error instanceof Error ? error.message : String(error),
3018
+ isLoading: false
3019
+ };
3020
+ emit();
3021
+ throw error;
3022
+ }
3023
+ };
3024
+ const close = () => {
3025
+ closed = true;
3026
+ if (timer) {
3027
+ clearInterval(timer);
3028
+ timer = undefined;
3029
+ }
3030
+ listeners.clear();
3031
+ };
3032
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
3033
+ timer = setInterval(() => {
3034
+ refresh().catch(() => {});
3035
+ }, options.intervalMs);
3036
+ }
3037
+ return {
3038
+ close,
3039
+ getServerSnapshot: () => snapshot,
3040
+ getSnapshot: () => snapshot,
3041
+ refresh,
3042
+ subscribe: (listener) => {
3043
+ listeners.add(listener);
3044
+ return () => {
3045
+ listeners.delete(listener);
3046
+ };
3047
+ }
3048
+ };
3049
+ };
3050
+
3051
+ // src/angular/voice-readiness-failures.service.ts
3052
+ var _dec = [
3053
+ Injectable13({ providedIn: "root" })
3054
+ ];
3055
+ var _init = __decoratorStart(undefined);
3056
+
3057
+ class VoiceReadinessFailuresService {
3058
+ connect(path = "/api/production-readiness", options = {}) {
3059
+ const store = createVoiceReadinessFailuresStore(path, options);
3060
+ const errorSignal = signal13(null);
3061
+ const isLoadingSignal = signal13(false);
3062
+ const reportSignal = signal13(undefined);
3063
+ const updatedAtSignal = signal13(undefined);
3064
+ const sync = () => {
3065
+ const snapshot = store.getSnapshot();
3066
+ errorSignal.set(snapshot.error);
3067
+ isLoadingSignal.set(snapshot.isLoading);
3068
+ reportSignal.set(snapshot.report);
3069
+ updatedAtSignal.set(snapshot.updatedAt);
3070
+ };
3071
+ const unsubscribe = store.subscribe(sync);
3072
+ sync();
3073
+ if (typeof window !== "undefined") {
3074
+ store.refresh().catch(() => {});
3075
+ }
3076
+ return {
3077
+ close: () => {
3078
+ unsubscribe();
3079
+ store.close();
3080
+ },
3081
+ error: computed13(() => errorSignal()),
3082
+ explanations: computed13(() => reportSignal()?.checks.filter((check) => check.status !== "pass" && !!check.gateExplanation) ?? []),
3083
+ isLoading: computed13(() => isLoadingSignal()),
3084
+ refresh: store.refresh,
3085
+ report: computed13(() => reportSignal()),
3086
+ updatedAt: computed13(() => updatedAtSignal())
3087
+ };
3088
+ }
3089
+ }
3090
+ VoiceReadinessFailuresService = __decorateElement(_init, 0, "VoiceReadinessFailuresService", _dec, VoiceReadinessFailuresService);
3091
+ __runInitializers(_init, 1, VoiceReadinessFailuresService);
3092
+ __decoratorMetadata(_init, VoiceReadinessFailuresService);
3093
+ let _VoiceReadinessFailuresService = VoiceReadinessFailuresService;
3094
+ // src/angular/voice-ops-action-center.service.ts
3095
+ import { computed as computed14, Injectable as Injectable14, signal as signal14 } from "@angular/core";
3096
+
3097
+ // src/client/opsActionCenter.ts
3098
+ var recordVoiceOpsActionResult = async (result, options = {}) => {
3099
+ if (options.auditPath === false) {
3100
+ return;
3101
+ }
3102
+ const path = options.auditPath ?? "/api/voice/ops-actions/audit";
3103
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3104
+ const response = await fetchImpl(path, {
3105
+ body: JSON.stringify(result),
3106
+ headers: {
3107
+ "Content-Type": "application/json"
3108
+ },
3109
+ method: "POST"
3110
+ });
3111
+ if (!response.ok) {
3112
+ throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
3113
+ }
3114
+ };
3115
+ var createVoiceOpsActionCenterActions = (options = {}) => {
3116
+ const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
3117
+ const actions = [];
3118
+ if (options.includeProductionReadiness !== false) {
3119
+ actions.push({
3120
+ description: "Refresh the production readiness report.",
3121
+ id: "production-readiness",
3122
+ label: "Refresh readiness",
3123
+ method: "GET",
3124
+ path: options.productionReadinessPath ?? "/api/production-readiness"
3125
+ });
3126
+ }
3127
+ if (options.includeDeliveryRuntime !== false) {
3128
+ actions.push({
3129
+ description: "Drain pending and failed audit/trace deliveries.",
3130
+ id: "delivery-runtime.tick",
3131
+ label: "Tick delivery workers",
3132
+ method: "POST",
3133
+ path: `${deliveryRuntimePath.replace(/\/$/, "")}/tick`
3134
+ }, {
3135
+ description: "Move reviewed dead letters back to live delivery queues.",
3136
+ id: "delivery-runtime.requeue-dead-letters",
3137
+ label: "Requeue dead letters",
3138
+ method: "POST",
3139
+ path: `${deliveryRuntimePath.replace(/\/$/, "")}/requeue-dead-letters`
3140
+ });
3141
+ }
3142
+ if (options.includeTurnLatencyProof !== false) {
3143
+ actions.push({
3144
+ description: "Run the synthetic turn latency proof.",
3145
+ id: "turn-latency.proof",
3146
+ label: "Run latency proof",
3147
+ method: "POST",
3148
+ path: options.turnLatencyProofPath ?? "/api/turn-latency/proof"
3149
+ });
3150
+ }
3151
+ if (options.includeProviderSimulation !== false) {
3152
+ const pathPrefix = options.providerSimulationPathPrefix ?? "/api/stt-simulate";
3153
+ for (const provider of options.providers ?? []) {
3154
+ actions.push({
3155
+ description: `Simulate ${provider} provider failure.`,
3156
+ id: `provider.${provider}.failure`,
3157
+ label: `Simulate ${provider} failure`,
3158
+ method: "POST",
3159
+ path: `${pathPrefix}/failure?provider=${encodeURIComponent(provider)}`
3160
+ }, {
3161
+ description: `Mark ${provider} provider recovered.`,
3162
+ id: `provider.${provider}.recovery`,
3163
+ label: `Recover ${provider}`,
3164
+ method: "POST",
3165
+ path: `${pathPrefix}/recovery?provider=${encodeURIComponent(provider)}`
3166
+ });
3167
+ }
3168
+ }
3169
+ return actions;
3170
+ };
3171
+ var runVoiceOpsAction = async (action, options = {}) => {
3172
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3173
+ const response = await fetchImpl(action.path, {
3174
+ method: action.method ?? "POST"
3175
+ });
3176
+ const body = await response.json().catch(() => null);
3177
+ if (!response.ok) {
3178
+ const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
3179
+ throw new Error(message);
3180
+ }
3181
+ return {
3182
+ actionId: action.id,
3183
+ body,
3184
+ ok: response.ok,
3185
+ ranAt: Date.now(),
3186
+ status: response.status
3187
+ };
3188
+ };
3189
+ var createVoiceOpsActionCenterStore = (options = {}) => {
3190
+ const listeners = new Set;
3191
+ let closed = false;
3192
+ let timer;
3193
+ let snapshot = {
3194
+ actions: options.actions ?? createVoiceOpsActionCenterActions(),
3195
+ error: null,
3196
+ isRunning: false
3197
+ };
3198
+ const emit = () => {
3199
+ for (const listener of listeners) {
3200
+ listener();
3201
+ }
3202
+ };
3203
+ const setActions = (actions) => {
3204
+ snapshot = { ...snapshot, actions, updatedAt: Date.now() };
3205
+ emit();
3206
+ };
3207
+ const run = async (actionId) => {
3208
+ if (closed) {
3209
+ return snapshot.lastResult;
3210
+ }
3211
+ const action = snapshot.actions.find((item) => item.id === actionId);
3212
+ if (!action) {
3213
+ throw new Error(`Voice ops action "${actionId}" is not configured.`);
3214
+ }
3215
+ if (action.disabled) {
3216
+ throw new Error(`Voice ops action "${actionId}" is disabled.`);
3217
+ }
3218
+ snapshot = {
3219
+ ...snapshot,
3220
+ error: null,
3221
+ isRunning: true,
3222
+ runningActionId: action.id
3223
+ };
3224
+ emit();
3225
+ try {
3226
+ const result = await runVoiceOpsAction(action, options);
3227
+ await options.onActionResult?.(result);
3228
+ await recordVoiceOpsActionResult(result, options);
3229
+ snapshot = {
3230
+ ...snapshot,
3231
+ error: null,
3232
+ isRunning: false,
3233
+ lastResult: result,
3234
+ runningActionId: undefined,
3235
+ updatedAt: Date.now()
3236
+ };
3237
+ emit();
3238
+ return result;
3239
+ } catch (error) {
3240
+ const result = {
3241
+ actionId: action.id,
3242
+ body: null,
3243
+ error: error instanceof Error ? error.message : String(error),
3244
+ ok: false,
3245
+ ranAt: Date.now(),
3246
+ status: 0
3247
+ };
3248
+ await options.onActionResult?.(result);
3249
+ await recordVoiceOpsActionResult(result, options).catch(() => {});
3250
+ snapshot = {
3251
+ ...snapshot,
3252
+ error: error instanceof Error ? error.message : String(error),
3253
+ isRunning: false,
3254
+ runningActionId: undefined
3255
+ };
3256
+ emit();
3257
+ throw error;
3258
+ }
3259
+ };
3260
+ const close = () => {
3261
+ closed = true;
3262
+ if (timer) {
3263
+ clearInterval(timer);
3264
+ timer = undefined;
3265
+ }
3266
+ listeners.clear();
3267
+ };
3268
+ if (options.intervalMs && options.intervalMs > 0) {
3269
+ timer = setInterval(() => {
3270
+ emit();
3271
+ }, options.intervalMs);
3272
+ }
3273
+ return {
3274
+ close,
3275
+ getServerSnapshot: () => snapshot,
3276
+ getSnapshot: () => snapshot,
3277
+ run,
3278
+ setActions,
3279
+ subscribe: (listener) => {
3280
+ listeners.add(listener);
3281
+ return () => {
3282
+ listeners.delete(listener);
3283
+ };
3284
+ }
3285
+ };
3286
+ };
3287
+
3288
+ // src/angular/voice-ops-action-center.service.ts
3289
+ var _dec = [
3290
+ Injectable14({ providedIn: "root" })
3291
+ ];
3292
+ var _init = __decoratorStart(undefined);
3293
+
3294
+ class VoiceOpsActionCenterService {
3295
+ connect(options = {}) {
3296
+ const store = createVoiceOpsActionCenterStore(options);
3297
+ const actionsSignal = signal14([]);
3298
+ const errorSignal = signal14(null);
3299
+ const isRunningSignal = signal14(false);
3300
+ const lastResultSignal = signal14(undefined);
3301
+ const runningActionIdSignal = signal14(undefined);
3302
+ const sync = () => {
3303
+ const snapshot = store.getSnapshot();
3304
+ actionsSignal.set(snapshot.actions);
3305
+ errorSignal.set(snapshot.error);
3306
+ isRunningSignal.set(snapshot.isRunning);
3307
+ lastResultSignal.set(snapshot.lastResult);
3308
+ runningActionIdSignal.set(snapshot.runningActionId);
3309
+ };
3310
+ const unsubscribe = store.subscribe(sync);
3311
+ sync();
3312
+ return {
3313
+ actions: computed14(() => actionsSignal()),
3314
+ close: () => {
3315
+ unsubscribe();
3316
+ store.close();
3317
+ },
3318
+ error: computed14(() => errorSignal()),
3319
+ isRunning: computed14(() => isRunningSignal()),
3320
+ lastResult: computed14(() => lastResultSignal()),
3321
+ run: store.run,
3322
+ runningActionId: computed14(() => runningActionIdSignal()),
3323
+ setActions: store.setActions
3324
+ };
3325
+ }
3326
+ }
3327
+ VoiceOpsActionCenterService = __decorateElement(_init, 0, "VoiceOpsActionCenterService", _dec, VoiceOpsActionCenterService);
3328
+ __runInitializers(_init, 1, VoiceOpsActionCenterService);
3329
+ __decoratorMetadata(_init, VoiceOpsActionCenterService);
3330
+ let _VoiceOpsActionCenterService = VoiceOpsActionCenterService;
3331
+ // src/angular/voice-live-ops.service.ts
3332
+ import { computed as computed15, Injectable as Injectable15, signal as signal15 } from "@angular/core";
3333
+
3334
+ // src/client/liveOps.ts
3335
+ var postVoiceLiveOpsAction = async (input, options = {}) => {
3336
+ if (!input.sessionId) {
3337
+ throw new Error("Start a voice session before running live ops actions.");
3338
+ }
3339
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3340
+ const response = await fetchImpl(options.actionPath ?? "/api/voice/live-ops/action", {
3341
+ body: JSON.stringify(input),
3342
+ headers: {
3343
+ "Content-Type": "application/json"
3344
+ },
3345
+ method: "POST"
3346
+ });
3347
+ const payload = await response.json().catch(() => null);
3348
+ if (!response.ok || !payload?.ok) {
3349
+ const message = payload && typeof payload === "object" && "error" in payload ? String(payload.error) : `Voice live ops action failed: HTTP ${response.status}`;
3350
+ throw new Error(message);
3351
+ }
3352
+ return payload;
3353
+ };
3354
+ var createVoiceLiveOpsStore = (options = {}) => {
3355
+ const listeners = new Set;
3356
+ let closed = false;
3357
+ let snapshot = {
3358
+ error: null,
3359
+ isRunning: false
3360
+ };
3361
+ const emit = () => {
3362
+ for (const listener of listeners) {
3363
+ listener();
3364
+ }
3365
+ };
3366
+ const run = async (input) => {
3367
+ if (closed) {
3368
+ return snapshot.lastResult;
3369
+ }
3370
+ snapshot = {
3371
+ ...snapshot,
3372
+ error: null,
3373
+ isRunning: true,
3374
+ runningAction: input.action
3375
+ };
3376
+ emit();
3377
+ try {
3378
+ const result = await postVoiceLiveOpsAction(input, options);
3379
+ await options.onControl?.(result);
3380
+ snapshot = {
3381
+ ...snapshot,
3382
+ error: null,
3383
+ isRunning: false,
3384
+ lastResult: result,
3385
+ runningAction: undefined,
3386
+ updatedAt: Date.now()
3387
+ };
3388
+ emit();
3389
+ return result;
3390
+ } catch (error) {
3391
+ snapshot = {
3392
+ ...snapshot,
3393
+ error: error instanceof Error ? error.message : String(error),
3394
+ isRunning: false,
3395
+ runningAction: undefined,
3396
+ updatedAt: Date.now()
3397
+ };
3398
+ emit();
3399
+ throw error;
3400
+ }
3401
+ };
3402
+ const close = () => {
3403
+ closed = true;
3404
+ listeners.clear();
3405
+ };
3406
+ return {
3407
+ close,
3408
+ getServerSnapshot: () => snapshot,
3409
+ getSnapshot: () => snapshot,
3410
+ run,
3411
+ subscribe: (listener) => {
3412
+ listeners.add(listener);
3413
+ return () => {
3414
+ listeners.delete(listener);
3415
+ };
3416
+ }
3417
+ };
3418
+ };
3419
+
3420
+ // src/angular/voice-live-ops.service.ts
3421
+ var _dec = [
3422
+ Injectable15({ providedIn: "root" })
3423
+ ];
3424
+ var _init = __decoratorStart(undefined);
3425
+
3426
+ class VoiceLiveOpsService {
3427
+ connect(options = {}) {
3428
+ const store = createVoiceLiveOpsStore(options);
3429
+ const errorSignal = signal15(null);
3430
+ const isRunningSignal = signal15(false);
3431
+ const lastResultSignal = signal15(undefined);
3432
+ const runningActionSignal = signal15(undefined);
3433
+ const sync = () => {
3434
+ const snapshot = store.getSnapshot();
3435
+ errorSignal.set(snapshot.error);
3436
+ isRunningSignal.set(snapshot.isRunning);
3437
+ lastResultSignal.set(snapshot.lastResult);
3438
+ runningActionSignal.set(snapshot.runningAction);
3439
+ };
3440
+ const unsubscribe = store.subscribe(sync);
3441
+ sync();
3442
+ return {
3443
+ close: () => {
3444
+ unsubscribe();
3445
+ store.close();
3446
+ },
3447
+ error: computed15(() => errorSignal()),
3448
+ isRunning: computed15(() => isRunningSignal()),
3449
+ lastResult: computed15(() => lastResultSignal()),
3450
+ run: store.run,
3451
+ runningAction: computed15(() => runningActionSignal())
3452
+ };
3453
+ }
3454
+ }
3455
+ VoiceLiveOpsService = __decorateElement(_init, 0, "VoiceLiveOpsService", _dec, VoiceLiveOpsService);
3456
+ __runInitializers(_init, 1, VoiceLiveOpsService);
3457
+ __decoratorMetadata(_init, VoiceLiveOpsService);
3458
+ let _VoiceLiveOpsService = VoiceLiveOpsService;
3459
+ // src/angular/voice-delivery-runtime.service.ts
3460
+ import { computed as computed16, Injectable as Injectable16, signal as signal16 } from "@angular/core";
3461
+
3462
+ // src/client/deliveryRuntime.ts
3463
+ var getDefaultActionPath = (path, action, options) => {
3464
+ if (action === "tick") {
3465
+ return options.tickPath ?? `${path.replace(/\/$/, "")}/tick`;
3466
+ }
3467
+ return options.requeueDeadLettersPath ?? `${path.replace(/\/$/, "")}/requeue-dead-letters`;
3468
+ };
3469
+ var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
3470
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3471
+ const response = await fetchImpl(path);
3472
+ if (!response.ok) {
3473
+ throw new Error(`Voice delivery runtime failed: HTTP ${response.status}`);
3474
+ }
3475
+ return await response.json();
3476
+ };
3477
+ var runVoiceDeliveryRuntimeAction = async (action, path = "/api/voice-delivery-runtime", options = {}) => {
3478
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3479
+ const response = await fetchImpl(getDefaultActionPath(path, action, options), {
3480
+ method: "POST"
3481
+ });
3482
+ if (!response.ok) {
3483
+ throw new Error(`Voice delivery runtime ${action} failed: HTTP ${response.status}`);
3484
+ }
3485
+ const body = await response.json();
3486
+ return {
3487
+ action,
3488
+ result: body.result,
3489
+ summary: body.summary,
3490
+ updatedAt: Date.now()
3491
+ };
3492
+ };
3493
+ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
3494
+ const listeners = new Set;
3495
+ let closed = false;
3496
+ let timer;
3497
+ let snapshot = {
3498
+ actionError: null,
3499
+ actionStatus: "idle",
3500
+ error: null,
3501
+ isLoading: false
3502
+ };
3503
+ const emit = () => {
3504
+ for (const listener of listeners) {
3505
+ listener();
3506
+ }
3507
+ };
3508
+ const refresh = async () => {
3509
+ if (closed) {
3510
+ return snapshot.report;
3511
+ }
3512
+ snapshot = {
3513
+ ...snapshot,
3514
+ error: null,
3515
+ isLoading: true
3516
+ };
3517
+ emit();
3518
+ try {
3519
+ const report = await fetchVoiceDeliveryRuntime(path, options);
3520
+ snapshot = {
3521
+ ...snapshot,
3522
+ error: null,
3523
+ isLoading: false,
3524
+ report,
3525
+ updatedAt: Date.now()
3526
+ };
3527
+ emit();
3528
+ return report;
3529
+ } catch (error) {
3530
+ snapshot = {
3531
+ ...snapshot,
3532
+ error: error instanceof Error ? error.message : String(error),
3533
+ isLoading: false
3534
+ };
3535
+ emit();
3536
+ throw error;
3537
+ }
3538
+ };
3539
+ const runAction = async (action) => {
3540
+ if (closed) {
3541
+ return snapshot.lastAction;
3542
+ }
3543
+ snapshot = {
3544
+ ...snapshot,
3545
+ actionError: null,
3546
+ actionStatus: "running"
3547
+ };
3548
+ emit();
3549
+ try {
3550
+ const result = await runVoiceDeliveryRuntimeAction(action, path, options);
3551
+ snapshot = {
3552
+ ...snapshot,
3553
+ actionError: null,
3554
+ actionStatus: "completed",
3555
+ lastAction: result
3556
+ };
3557
+ emit();
3558
+ await refresh();
3559
+ return result;
3560
+ } catch (error) {
3561
+ snapshot = {
3562
+ ...snapshot,
3563
+ actionError: error instanceof Error ? error.message : String(error),
3564
+ actionStatus: "failed"
3565
+ };
3566
+ emit();
3567
+ throw error;
3568
+ }
3569
+ };
3570
+ const close = () => {
3571
+ closed = true;
3572
+ if (timer) {
3573
+ clearInterval(timer);
3574
+ timer = undefined;
3575
+ }
3576
+ listeners.clear();
3577
+ };
3578
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
3579
+ timer = setInterval(() => {
3580
+ refresh().catch(() => {});
3581
+ }, options.intervalMs);
3582
+ }
3583
+ return {
3584
+ close,
3585
+ getServerSnapshot: () => snapshot,
3586
+ getSnapshot: () => snapshot,
3587
+ requeueDeadLetters: () => runAction("requeue-dead-letters"),
3588
+ refresh,
3589
+ tick: () => runAction("tick"),
3590
+ subscribe: (listener) => {
3591
+ listeners.add(listener);
3592
+ return () => {
3593
+ listeners.delete(listener);
3594
+ };
3595
+ }
3596
+ };
3597
+ };
3598
+
3599
+ // src/angular/voice-delivery-runtime.service.ts
3600
+ var _dec = [
3601
+ Injectable16({ providedIn: "root" })
3602
+ ];
3603
+ var _init = __decoratorStart(undefined);
3604
+
3605
+ class VoiceDeliveryRuntimeService {
3606
+ connect(path = "/api/voice-delivery-runtime", options = {}) {
3607
+ const store = createVoiceDeliveryRuntimeStore(path, options);
3608
+ const actionErrorSignal = signal16(null);
3609
+ const actionStatusSignal = signal16("idle");
3610
+ const errorSignal = signal16(null);
3611
+ const isLoadingSignal = signal16(false);
3612
+ const reportSignal = signal16(undefined);
3613
+ const updatedAtSignal = signal16(undefined);
3614
+ const sync = () => {
3615
+ const snapshot = store.getSnapshot();
3616
+ actionErrorSignal.set(snapshot.actionError);
3617
+ actionStatusSignal.set(snapshot.actionStatus);
3618
+ errorSignal.set(snapshot.error);
3619
+ isLoadingSignal.set(snapshot.isLoading);
3620
+ reportSignal.set(snapshot.report);
3621
+ updatedAtSignal.set(snapshot.updatedAt);
3622
+ };
3623
+ const unsubscribe = store.subscribe(sync);
3624
+ sync();
3625
+ if (typeof window !== "undefined") {
3626
+ store.refresh().catch(() => {});
3627
+ }
3628
+ return {
3629
+ close: () => {
3630
+ unsubscribe();
3631
+ store.close();
3632
+ },
3633
+ error: computed16(() => errorSignal()),
3634
+ actionError: computed16(() => actionErrorSignal()),
3635
+ actionStatus: computed16(() => actionStatusSignal()),
3636
+ isLoading: computed16(() => isLoadingSignal()),
3637
+ requeueDeadLetters: store.requeueDeadLetters,
3638
+ refresh: store.refresh,
3639
+ report: computed16(() => reportSignal()),
3640
+ tick: store.tick,
3641
+ updatedAt: computed16(() => updatedAtSignal())
3642
+ };
3643
+ }
3644
+ }
3645
+ VoiceDeliveryRuntimeService = __decorateElement(_init, 0, "VoiceDeliveryRuntimeService", _dec, VoiceDeliveryRuntimeService);
3646
+ __runInitializers(_init, 1, VoiceDeliveryRuntimeService);
3647
+ __decoratorMetadata(_init, VoiceDeliveryRuntimeService);
3648
+ let _VoiceDeliveryRuntimeService = VoiceDeliveryRuntimeService;
3649
+ // src/angular/voice-campaign-dialer-proof.service.ts
3650
+ import { computed as computed17, Injectable as Injectable17, signal as signal17 } from "@angular/core";
3651
+
3652
+ // src/client/campaignDialerProof.ts
3653
+ var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
3654
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3655
+ const response = await fetchImpl(path);
3656
+ if (!response.ok) {
3657
+ throw new Error(`Voice campaign dialer proof status failed: HTTP ${response.status}`);
3658
+ }
3659
+ return await response.json();
3660
+ };
3661
+ var runVoiceCampaignDialerProofAction = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
3662
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3663
+ const response = await fetchImpl(path, { method: "POST" });
3664
+ if (!response.ok) {
3665
+ throw new Error(`Voice campaign dialer proof failed: HTTP ${response.status}`);
3666
+ }
3667
+ return await response.json();
3668
+ };
3669
+ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
3670
+ const listeners = new Set;
3671
+ let closed = false;
3672
+ let timer;
3673
+ let snapshot = {
3674
+ error: null,
3675
+ isLoading: false
3676
+ };
3677
+ const emit = () => {
3678
+ for (const listener of listeners) {
3679
+ listener();
3680
+ }
3681
+ };
3682
+ const refresh = async () => {
3683
+ if (closed) {
3684
+ return snapshot.status;
3685
+ }
3686
+ snapshot = { ...snapshot, error: null, isLoading: true };
3687
+ emit();
3688
+ try {
3689
+ const status = await fetchVoiceCampaignDialerProofStatus(path, options);
3690
+ snapshot = {
3691
+ ...snapshot,
3692
+ error: null,
3693
+ isLoading: false,
3694
+ status,
3695
+ updatedAt: Date.now()
3696
+ };
3697
+ emit();
3698
+ return status;
3699
+ } catch (error) {
3700
+ snapshot = {
3701
+ ...snapshot,
3702
+ error: error instanceof Error ? error.message : String(error),
3703
+ isLoading: false
3704
+ };
3705
+ emit();
3706
+ throw error;
3707
+ }
3708
+ };
3709
+ const runProof = async () => {
3710
+ const runPath = options.runPath ?? snapshot.status?.runPath ?? path;
3711
+ snapshot = { ...snapshot, error: null, isLoading: true };
3712
+ emit();
3713
+ try {
3714
+ const report = await runVoiceCampaignDialerProofAction(runPath, options);
3715
+ snapshot = {
3716
+ ...snapshot,
3717
+ error: null,
3718
+ isLoading: false,
3719
+ report,
3720
+ status: {
3721
+ generatedAt: Date.now(),
3722
+ mode: report.mode,
3723
+ ok: report.ok,
3724
+ providers: report.providers.map((provider) => provider.provider),
3725
+ runPath,
3726
+ safe: true
3727
+ },
3728
+ updatedAt: Date.now()
3729
+ };
3730
+ emit();
3731
+ return report;
3732
+ } catch (error) {
3733
+ snapshot = {
3734
+ ...snapshot,
3735
+ error: error instanceof Error ? error.message : String(error),
3736
+ isLoading: false
3737
+ };
3738
+ emit();
3739
+ throw error;
3740
+ }
3741
+ };
3742
+ const close = () => {
3743
+ closed = true;
3744
+ if (timer) {
3745
+ clearInterval(timer);
3746
+ timer = undefined;
3747
+ }
3748
+ listeners.clear();
3749
+ };
3750
+ if (options.intervalMs && options.intervalMs > 0) {
3751
+ timer = setInterval(() => {
3752
+ refresh().catch(() => {});
3753
+ }, options.intervalMs);
3754
+ }
3755
+ return {
3756
+ close,
3757
+ getServerSnapshot: () => snapshot,
3758
+ getSnapshot: () => snapshot,
3759
+ refresh,
3760
+ runProof,
3761
+ subscribe: (listener) => {
3762
+ listeners.add(listener);
3763
+ return () => {
3764
+ listeners.delete(listener);
3765
+ };
3766
+ }
3767
+ };
3768
+ };
3769
+
3770
+ // src/angular/voice-campaign-dialer-proof.service.ts
3771
+ var _dec = [
3772
+ Injectable17({ providedIn: "root" })
3773
+ ];
3774
+ var _init = __decoratorStart(undefined);
3775
+
3776
+ class VoiceCampaignDialerProofService {
3777
+ connect(path = "/api/voice/campaigns/dialer-proof", options = {}) {
3778
+ const store = createVoiceCampaignDialerProofStore(path, options);
3779
+ const errorSignal = signal17(null);
3780
+ const isLoadingSignal = signal17(false);
3781
+ const reportSignal = signal17(undefined);
3782
+ const statusSignal = signal17(undefined);
3783
+ const updatedAtSignal = signal17(undefined);
3784
+ const sync = () => {
3785
+ const snapshot = store.getSnapshot();
3786
+ errorSignal.set(snapshot.error);
3787
+ isLoadingSignal.set(snapshot.isLoading);
3788
+ reportSignal.set(snapshot.report);
3789
+ statusSignal.set(snapshot.status);
3790
+ updatedAtSignal.set(snapshot.updatedAt);
3791
+ };
3792
+ const unsubscribe = store.subscribe(sync);
3793
+ sync();
3794
+ store.refresh().catch(() => {});
3795
+ return {
3796
+ close: () => {
3797
+ unsubscribe();
3798
+ store.close();
3799
+ },
3800
+ error: computed17(() => errorSignal()),
3801
+ isLoading: computed17(() => isLoadingSignal()),
3802
+ refresh: store.refresh,
3803
+ report: computed17(() => reportSignal()),
3804
+ runProof: store.runProof,
3805
+ status: computed17(() => statusSignal()),
3806
+ updatedAt: computed17(() => updatedAtSignal())
3807
+ };
3808
+ }
3809
+ }
3810
+ VoiceCampaignDialerProofService = __decorateElement(_init, 0, "VoiceCampaignDialerProofService", _dec, VoiceCampaignDialerProofService);
3811
+ __runInitializers(_init, 1, VoiceCampaignDialerProofService);
3812
+ __decoratorMetadata(_init, VoiceCampaignDialerProofService);
3813
+ let _VoiceCampaignDialerProofService = VoiceCampaignDialerProofService;
3814
+ // src/angular/voice-stream.service.ts
3815
+ import { computed as computed18, Injectable as Injectable18, signal as signal18 } from "@angular/core";
3816
+ var _dec = [
3817
+ Injectable18({ providedIn: "root" })
3818
+ ];
3819
+ var _init = __decoratorStart(undefined);
3820
+
3821
+ class VoiceStreamService {
3822
+ connect(path, options = {}) {
3823
+ const stream = createVoiceStream(path, options);
3824
+ const assistantAudioSignal = signal18([]);
3825
+ const assistantTextsSignal = signal18([]);
3826
+ const callSignal = signal18(null);
3827
+ const errorSignal = signal18(null);
3828
+ const isConnectedSignal = signal18(false);
3829
+ const partialSignal = signal18("");
3830
+ const reconnectSignal = signal18(stream.reconnect);
3831
+ const sessionIdSignal = signal18(stream.sessionId);
3832
+ const sessionMetadataSignal = signal18(stream.sessionMetadata);
3833
+ const statusSignal = signal18(stream.status);
3834
+ const turnsSignal = signal18([]);
3835
+ const sync = () => {
3836
+ assistantAudioSignal.set([...stream.assistantAudio]);
3837
+ assistantTextsSignal.set([...stream.assistantTexts]);
3838
+ callSignal.set(stream.call);
3839
+ errorSignal.set(stream.error);
3840
+ isConnectedSignal.set(stream.isConnected);
3841
+ partialSignal.set(stream.partial);
3842
+ reconnectSignal.set(stream.reconnect);
3843
+ sessionIdSignal.set(stream.sessionId);
3844
+ sessionMetadataSignal.set(stream.sessionMetadata);
3845
+ statusSignal.set(stream.status);
3846
+ turnsSignal.set([...stream.turns]);
3847
+ };
3848
+ const unsubscribe = stream.subscribe(sync);
3849
+ sync();
3850
+ return {
3851
+ assistantAudio: computed18(() => assistantAudioSignal()),
3852
+ assistantTexts: computed18(() => assistantTextsSignal()),
3853
+ call: computed18(() => callSignal()),
3854
+ callControl: (message) => stream.callControl(message),
3855
+ close: () => {
3856
+ unsubscribe();
3857
+ stream.close();
3858
+ },
3859
+ endTurn: () => stream.endTurn(),
3860
+ error: computed18(() => errorSignal()),
3861
+ isConnected: computed18(() => isConnectedSignal()),
3862
+ partial: computed18(() => partialSignal()),
3863
+ reconnect: computed18(() => reconnectSignal()),
3864
+ sendAudio: (audio) => stream.sendAudio(audio),
3865
+ simulateDisconnect: () => stream.simulateDisconnect(),
3866
+ sessionId: computed18(() => sessionIdSignal()),
3867
+ sessionMetadata: computed18(() => sessionMetadataSignal()),
3868
+ status: computed18(() => statusSignal()),
3869
+ turns: computed18(() => turnsSignal())
3870
+ };
3871
+ }
3872
+ }
3873
+ VoiceStreamService = __decorateElement(_init, 0, "VoiceStreamService", _dec, VoiceStreamService);
3874
+ __runInitializers(_init, 1, VoiceStreamService);
3875
+ __decoratorMetadata(_init, VoiceStreamService);
3876
+ let _VoiceStreamService = VoiceStreamService;
3877
+ // src/angular/voice-controller.service.ts
3878
+ import { computed as computed19, Injectable as Injectable19, signal as signal19 } from "@angular/core";
3879
+ var _dec = [
3880
+ Injectable19({ providedIn: "root" })
3881
+ ];
3882
+ var _init = __decoratorStart(undefined);
3883
+
3884
+ class VoiceControllerService {
3885
+ connect(path, options = {}) {
3886
+ const controller = createVoiceController(path, options);
3887
+ const assistantAudioSignal = signal19([]);
3888
+ const assistantTextsSignal = signal19([]);
3889
+ const errorSignal = signal19(null);
3890
+ const isConnectedSignal = signal19(false);
3891
+ const isRecordingSignal = signal19(false);
3892
+ const partialSignal = signal19("");
3893
+ const reconnectSignal = signal19(controller.reconnect);
3894
+ const recordingErrorSignal = signal19(null);
3895
+ const sessionIdSignal = signal19(controller.sessionId);
3896
+ const statusSignal = signal19(controller.status);
3897
+ const turnsSignal = signal19([]);
3898
+ const sync = () => {
3899
+ assistantAudioSignal.set([...controller.assistantAudio]);
3900
+ assistantTextsSignal.set([...controller.assistantTexts]);
3901
+ errorSignal.set(controller.error);
3902
+ isConnectedSignal.set(controller.isConnected);
3903
+ isRecordingSignal.set(controller.isRecording);
3904
+ partialSignal.set(controller.partial);
3905
+ reconnectSignal.set(controller.reconnect);
3906
+ recordingErrorSignal.set(controller.recordingError);
3907
+ sessionIdSignal.set(controller.sessionId);
3908
+ statusSignal.set(controller.status);
3909
+ turnsSignal.set([...controller.turns]);
3910
+ };
3911
+ const unsubscribe = controller.subscribe(sync);
3912
+ sync();
3913
+ return {
3914
+ assistantAudio: computed19(() => assistantAudioSignal()),
3915
+ assistantTexts: computed19(() => assistantTextsSignal()),
3916
+ bindHTMX: controller.bindHTMX,
3917
+ close: () => {
3918
+ unsubscribe();
3919
+ controller.close();
3920
+ },
3921
+ endTurn: () => controller.endTurn(),
3922
+ error: computed19(() => errorSignal()),
3923
+ isConnected: computed19(() => isConnectedSignal()),
3924
+ isRecording: computed19(() => isRecordingSignal()),
3925
+ partial: computed19(() => partialSignal()),
3926
+ reconnect: computed19(() => reconnectSignal()),
3927
+ recordingError: computed19(() => recordingErrorSignal()),
3928
+ sendAudio: (audio) => controller.sendAudio(audio),
3929
+ simulateDisconnect: () => controller.simulateDisconnect(),
3930
+ sessionId: computed19(() => sessionIdSignal()),
3931
+ startRecording: () => controller.startRecording(),
3932
+ status: computed19(() => statusSignal()),
3933
+ stopRecording: () => controller.stopRecording(),
3934
+ toggleRecording: () => controller.toggleRecording(),
3935
+ turns: computed19(() => turnsSignal())
3936
+ };
3937
+ }
3938
+ }
3939
+ VoiceControllerService = __decorateElement(_init, 0, "VoiceControllerService", _dec, VoiceControllerService);
3940
+ __runInitializers(_init, 1, VoiceControllerService);
3941
+ __decoratorMetadata(_init, VoiceControllerService);
3942
+ let _VoiceControllerService = VoiceControllerService;
3943
+ // src/angular/voice-provider-capabilities.service.ts
3944
+ import { computed as computed20, Injectable as Injectable20, signal as signal20 } from "@angular/core";
3945
+
3946
+ // src/client/providerCapabilities.ts
3947
+ var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
3948
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3949
+ const response = await fetchImpl(path);
3950
+ if (!response.ok) {
3951
+ throw new Error(`Voice provider capabilities failed: HTTP ${response.status}`);
3952
+ }
3953
+ return await response.json();
3954
+ };
3955
+ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities", options = {}) => {
3956
+ const listeners = new Set;
3957
+ let closed = false;
3958
+ let timer;
3959
+ let snapshot = {
3960
+ error: null,
3961
+ isLoading: false
3962
+ };
3963
+ const emit = () => {
3964
+ for (const listener of listeners) {
3965
+ listener();
3966
+ }
3967
+ };
3968
+ const refresh = async () => {
3969
+ if (closed) {
3970
+ return snapshot.report;
3971
+ }
3972
+ snapshot = {
3973
+ ...snapshot,
3974
+ error: null,
3975
+ isLoading: true
3976
+ };
3977
+ emit();
3978
+ try {
3979
+ const report = await fetchVoiceProviderCapabilities(path, options);
3980
+ snapshot = {
3981
+ error: null,
3982
+ isLoading: false,
3983
+ report,
3984
+ updatedAt: Date.now()
3985
+ };
3986
+ emit();
3987
+ return report;
3988
+ } catch (error) {
3989
+ snapshot = {
3990
+ ...snapshot,
3991
+ error: error instanceof Error ? error.message : String(error),
3992
+ isLoading: false
3993
+ };
3994
+ emit();
3995
+ throw error;
3996
+ }
3997
+ };
3998
+ const close = () => {
3999
+ closed = true;
4000
+ if (timer) {
4001
+ clearInterval(timer);
4002
+ timer = undefined;
4003
+ }
4004
+ listeners.clear();
4005
+ };
4006
+ if (options.intervalMs && options.intervalMs > 0) {
4007
+ timer = setInterval(() => {
4008
+ refresh().catch(() => {});
4009
+ }, options.intervalMs);
4010
+ }
4011
+ return {
4012
+ close,
4013
+ getServerSnapshot: () => snapshot,
4014
+ getSnapshot: () => snapshot,
4015
+ refresh,
4016
+ subscribe: (listener) => {
4017
+ listeners.add(listener);
4018
+ return () => {
4019
+ listeners.delete(listener);
4020
+ };
4021
+ }
4022
+ };
4023
+ };
4024
+
4025
+ // src/angular/voice-provider-capabilities.service.ts
4026
+ var _dec = [
4027
+ Injectable20({ providedIn: "root" })
4028
+ ];
4029
+ var _init = __decoratorStart(undefined);
4030
+
4031
+ class VoiceProviderCapabilitiesService {
4032
+ connect(path = "/api/provider-capabilities", options = {}) {
4033
+ const store = createVoiceProviderCapabilitiesStore(path, options);
4034
+ const errorSignal = signal20(null);
4035
+ const isLoadingSignal = signal20(false);
4036
+ const reportSignal = signal20(undefined);
4037
+ const updatedAtSignal = signal20(undefined);
4038
+ const sync = () => {
4039
+ const snapshot = store.getSnapshot();
4040
+ errorSignal.set(snapshot.error);
4041
+ isLoadingSignal.set(snapshot.isLoading);
4042
+ reportSignal.set(snapshot.report);
4043
+ updatedAtSignal.set(snapshot.updatedAt);
4044
+ };
4045
+ const unsubscribe = store.subscribe(sync);
4046
+ sync();
4047
+ store.refresh().catch(() => {});
4048
+ return {
4049
+ close: () => {
4050
+ unsubscribe();
4051
+ store.close();
4052
+ },
4053
+ error: computed20(() => errorSignal()),
4054
+ isLoading: computed20(() => isLoadingSignal()),
4055
+ refresh: store.refresh,
4056
+ report: computed20(() => reportSignal()),
4057
+ updatedAt: computed20(() => updatedAtSignal())
4058
+ };
4059
+ }
4060
+ }
4061
+ VoiceProviderCapabilitiesService = __decorateElement(_init, 0, "VoiceProviderCapabilitiesService", _dec, VoiceProviderCapabilitiesService);
4062
+ __runInitializers(_init, 1, VoiceProviderCapabilitiesService);
4063
+ __decoratorMetadata(_init, VoiceProviderCapabilitiesService);
4064
+ let _VoiceProviderCapabilitiesService = VoiceProviderCapabilitiesService;
4065
+ // src/angular/voice-provider-contracts.service.ts
4066
+ import { computed as computed21, Injectable as Injectable21, signal as signal21 } from "@angular/core";
4067
+
4068
+ // src/client/providerContracts.ts
4069
+ var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
4070
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4071
+ const response = await fetchImpl(path);
4072
+ if (!response.ok) {
4073
+ throw new Error(`Voice provider contracts failed: HTTP ${response.status}`);
4074
+ }
4075
+ return await response.json();
4076
+ };
4077
+ var createVoiceProviderContractsStore = (path = "/api/provider-contracts", options = {}) => {
4078
+ const listeners = new Set;
4079
+ let closed = false;
4080
+ let timer;
4081
+ let snapshot = {
4082
+ error: null,
4083
+ isLoading: false
4084
+ };
4085
+ const emit = () => {
4086
+ for (const listener of listeners) {
4087
+ listener();
4088
+ }
4089
+ };
4090
+ const refresh = async () => {
4091
+ if (closed) {
4092
+ return snapshot.report;
4093
+ }
4094
+ snapshot = { ...snapshot, error: null, isLoading: true };
4095
+ emit();
4096
+ try {
4097
+ const report = await fetchVoiceProviderContracts(path, options);
4098
+ snapshot = {
4099
+ error: null,
4100
+ isLoading: false,
4101
+ report,
4102
+ updatedAt: Date.now()
4103
+ };
4104
+ emit();
4105
+ return report;
4106
+ } catch (error) {
4107
+ snapshot = {
4108
+ ...snapshot,
4109
+ error: error instanceof Error ? error.message : String(error),
4110
+ isLoading: false
4111
+ };
4112
+ emit();
4113
+ throw error;
4114
+ }
4115
+ };
4116
+ const close = () => {
4117
+ closed = true;
4118
+ if (timer) {
4119
+ clearInterval(timer);
4120
+ timer = undefined;
4121
+ }
4122
+ listeners.clear();
4123
+ };
4124
+ if (options.intervalMs && options.intervalMs > 0) {
4125
+ timer = setInterval(() => {
4126
+ refresh().catch(() => {});
4127
+ }, options.intervalMs);
4128
+ }
4129
+ return {
4130
+ close,
4131
+ getServerSnapshot: () => snapshot,
4132
+ getSnapshot: () => snapshot,
4133
+ refresh,
4134
+ subscribe: (listener) => {
4135
+ listeners.add(listener);
4136
+ return () => {
4137
+ listeners.delete(listener);
4138
+ };
4139
+ }
4140
+ };
4141
+ };
4142
+
4143
+ // src/angular/voice-provider-contracts.service.ts
4144
+ var _dec = [
4145
+ Injectable21({ providedIn: "root" })
4146
+ ];
4147
+ var _init = __decoratorStart(undefined);
4148
+
4149
+ class VoiceProviderContractsService {
4150
+ connect(path = "/api/provider-contracts", options = {}) {
4151
+ const store = createVoiceProviderContractsStore(path, options);
4152
+ const errorSignal = signal21(null);
4153
+ const isLoadingSignal = signal21(false);
4154
+ const reportSignal = signal21(undefined);
4155
+ const updatedAtSignal = signal21(undefined);
4156
+ const sync = () => {
4157
+ const snapshot = store.getSnapshot();
4158
+ errorSignal.set(snapshot.error);
4159
+ isLoadingSignal.set(snapshot.isLoading);
4160
+ reportSignal.set(snapshot.report);
4161
+ updatedAtSignal.set(snapshot.updatedAt);
4162
+ };
4163
+ const unsubscribe = store.subscribe(sync);
4164
+ sync();
4165
+ store.refresh().catch(() => {});
4166
+ return {
4167
+ close: () => {
4168
+ unsubscribe();
4169
+ store.close();
4170
+ },
4171
+ error: computed21(() => errorSignal()),
4172
+ isLoading: computed21(() => isLoadingSignal()),
4173
+ refresh: store.refresh,
4174
+ report: computed21(() => reportSignal()),
4175
+ updatedAt: computed21(() => updatedAtSignal())
4176
+ };
4177
+ }
4178
+ }
4179
+ VoiceProviderContractsService = __decorateElement(_init, 0, "VoiceProviderContractsService", _dec, VoiceProviderContractsService);
4180
+ __runInitializers(_init, 1, VoiceProviderContractsService);
4181
+ __decoratorMetadata(_init, VoiceProviderContractsService);
4182
+ let _VoiceProviderContractsService = VoiceProviderContractsService;
4183
+ // src/angular/voice-provider-status.service.ts
4184
+ import { computed as computed22, Injectable as Injectable22, signal as signal22 } from "@angular/core";
4185
+
4186
+ // src/client/providerStatus.ts
4187
+ var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
4188
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4189
+ const response = await fetchImpl(path);
4190
+ if (!response.ok) {
4191
+ throw new Error(`Voice provider status failed: HTTP ${response.status}`);
4192
+ }
4193
+ return await response.json();
4194
+ };
4195
+ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {}) => {
4196
+ const listeners = new Set;
4197
+ let closed = false;
4198
+ let timer;
4199
+ let snapshot = {
4200
+ error: null,
4201
+ isLoading: false,
4202
+ providers: []
4203
+ };
4204
+ const emit = () => {
4205
+ for (const listener of listeners) {
4206
+ listener();
4207
+ }
4208
+ };
4209
+ const refresh = async () => {
4210
+ if (closed) {
4211
+ return snapshot.providers;
4212
+ }
4213
+ snapshot = {
4214
+ ...snapshot,
4215
+ error: null,
4216
+ isLoading: true
4217
+ };
4218
+ emit();
4219
+ try {
4220
+ const providers = await fetchVoiceProviderStatus(path, options);
4221
+ snapshot = {
4222
+ error: null,
4223
+ isLoading: false,
4224
+ providers,
4225
+ updatedAt: Date.now()
4226
+ };
4227
+ emit();
4228
+ return providers;
4229
+ } catch (error) {
4230
+ snapshot = {
4231
+ ...snapshot,
4232
+ error: error instanceof Error ? error.message : String(error),
4233
+ isLoading: false
4234
+ };
4235
+ emit();
4236
+ throw error;
4237
+ }
4238
+ };
4239
+ const close = () => {
4240
+ closed = true;
4241
+ if (timer) {
4242
+ clearInterval(timer);
4243
+ timer = undefined;
4244
+ }
4245
+ listeners.clear();
4246
+ };
4247
+ if (options.intervalMs && options.intervalMs > 0) {
4248
+ timer = setInterval(() => {
4249
+ refresh().catch(() => {});
4250
+ }, options.intervalMs);
4251
+ }
4252
+ return {
4253
+ close,
4254
+ getServerSnapshot: () => snapshot,
4255
+ getSnapshot: () => snapshot,
4256
+ refresh,
4257
+ subscribe: (listener) => {
4258
+ listeners.add(listener);
4259
+ return () => {
4260
+ listeners.delete(listener);
4261
+ };
4262
+ }
4263
+ };
4264
+ };
4265
+
4266
+ // src/angular/voice-provider-status.service.ts
4267
+ var _dec = [
4268
+ Injectable22({ providedIn: "root" })
4269
+ ];
4270
+ var _init = __decoratorStart(undefined);
4271
+
4272
+ class VoiceProviderStatusService {
4273
+ connect(path = "/api/provider-status", options = {}) {
4274
+ const store = createVoiceProviderStatusStore(path, options);
4275
+ const errorSignal = signal22(null);
4276
+ const isLoadingSignal = signal22(false);
4277
+ const providersSignal = signal22([]);
4278
+ const updatedAtSignal = signal22(undefined);
4279
+ const sync = () => {
4280
+ const snapshot = store.getSnapshot();
4281
+ errorSignal.set(snapshot.error);
4282
+ isLoadingSignal.set(snapshot.isLoading);
4283
+ providersSignal.set([...snapshot.providers]);
4284
+ updatedAtSignal.set(snapshot.updatedAt);
4285
+ };
4286
+ const unsubscribe = store.subscribe(sync);
4287
+ sync();
4288
+ store.refresh().catch(() => {});
4289
+ return {
4290
+ close: () => {
4291
+ unsubscribe();
4292
+ store.close();
4293
+ },
4294
+ error: computed22(() => errorSignal()),
4295
+ isLoading: computed22(() => isLoadingSignal()),
4296
+ providers: computed22(() => providersSignal()),
4297
+ refresh: store.refresh,
4298
+ updatedAt: computed22(() => updatedAtSignal())
4299
+ };
4300
+ }
4301
+ }
4302
+ VoiceProviderStatusService = __decorateElement(_init, 0, "VoiceProviderStatusService", _dec, VoiceProviderStatusService);
4303
+ __runInitializers(_init, 1, VoiceProviderStatusService);
4304
+ __decoratorMetadata(_init, VoiceProviderStatusService);
4305
+ let _VoiceProviderStatusService = VoiceProviderStatusService;
4306
+ // src/angular/voice-routing-status.service.ts
4307
+ import { Injectable as Injectable23, signal as signal23 } from "@angular/core";
4308
+
4309
+ // src/client/routingStatus.ts
4310
+ var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
4311
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4312
+ const response = await fetchImpl(path);
4313
+ if (!response.ok) {
4314
+ throw new Error(`Voice routing status failed: HTTP ${response.status}`);
4315
+ }
4316
+ return await response.json();
4317
+ };
4318
+ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {}) => {
4319
+ const listeners = new Set;
4320
+ let closed = false;
4321
+ let timer;
4322
+ let snapshot = {
4323
+ decision: null,
4324
+ error: null,
4325
+ isLoading: false
4326
+ };
4327
+ const emit = () => {
4328
+ for (const listener of listeners) {
4329
+ listener();
4330
+ }
4331
+ };
4332
+ const refresh = async () => {
4333
+ if (closed) {
4334
+ return snapshot.decision;
4335
+ }
4336
+ snapshot = {
4337
+ ...snapshot,
4338
+ error: null,
4339
+ isLoading: true
4340
+ };
4341
+ emit();
4342
+ try {
4343
+ const decision = await fetchVoiceRoutingStatus(path, options);
4344
+ snapshot = {
4345
+ decision,
4346
+ error: null,
4347
+ isLoading: false,
4348
+ updatedAt: Date.now()
4349
+ };
4350
+ emit();
4351
+ return decision;
4352
+ } catch (error) {
4353
+ snapshot = {
4354
+ ...snapshot,
4355
+ error: error instanceof Error ? error.message : String(error),
4356
+ isLoading: false
4357
+ };
4358
+ emit();
4359
+ throw error;
4360
+ }
4361
+ };
4362
+ const close = () => {
4363
+ closed = true;
4364
+ if (timer) {
4365
+ clearInterval(timer);
4366
+ timer = undefined;
4367
+ }
4368
+ listeners.clear();
4369
+ };
4370
+ if (options.intervalMs && options.intervalMs > 0) {
4371
+ timer = setInterval(() => {
4372
+ refresh().catch(() => {});
4373
+ }, options.intervalMs);
4374
+ }
4375
+ return {
4376
+ close,
4377
+ getServerSnapshot: () => snapshot,
4378
+ getSnapshot: () => snapshot,
4379
+ refresh,
4380
+ subscribe: (listener) => {
4381
+ listeners.add(listener);
4382
+ return () => {
4383
+ listeners.delete(listener);
4384
+ };
4385
+ }
4386
+ };
4387
+ };
4388
+
4389
+ // src/angular/voice-routing-status.service.ts
4390
+ var _dec = [
4391
+ Injectable23({ providedIn: "root" })
4392
+ ];
4393
+ var _init = __decoratorStart(undefined);
4394
+
4395
+ class VoiceRoutingStatusService {
4396
+ connect(path = "/api/routing/latest", options = {}) {
4397
+ const store = createVoiceRoutingStatusStore(path, options);
4398
+ const decisionSignal = signal23(null);
4399
+ const errorSignal = signal23(null);
4400
+ const isLoadingSignal = signal23(false);
4401
+ const updatedAtSignal = signal23(undefined);
4402
+ const sync = () => {
4403
+ const snapshot = store.getSnapshot();
4404
+ decisionSignal.set(snapshot.decision);
4405
+ errorSignal.set(snapshot.error);
4406
+ isLoadingSignal.set(snapshot.isLoading);
4407
+ updatedAtSignal.set(snapshot.updatedAt);
4408
+ };
4409
+ const unsubscribe = store.subscribe(sync);
4410
+ sync();
4411
+ store.refresh().catch(() => {});
4412
+ return {
4413
+ close: () => {
4414
+ unsubscribe();
4415
+ store.close();
4416
+ },
4417
+ decision: decisionSignal.asReadonly(),
4418
+ error: errorSignal.asReadonly(),
4419
+ isLoading: isLoadingSignal.asReadonly(),
4420
+ refresh: store.refresh,
4421
+ updatedAt: updatedAtSignal.asReadonly()
4422
+ };
4423
+ }
4424
+ }
4425
+ VoiceRoutingStatusService = __decorateElement(_init, 0, "VoiceRoutingStatusService", _dec, VoiceRoutingStatusService);
4426
+ __runInitializers(_init, 1, VoiceRoutingStatusService);
4427
+ __decoratorMetadata(_init, VoiceRoutingStatusService);
4428
+ let _VoiceRoutingStatusService = VoiceRoutingStatusService;
4429
+ // src/angular/voice-trace-timeline.service.ts
4430
+ import { computed as computed23, Injectable as Injectable24, signal as signal24 } from "@angular/core";
4431
+
4432
+ // src/client/traceTimeline.ts
4433
+ var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
4434
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4435
+ const response = await fetchImpl(path);
4436
+ if (!response.ok) {
4437
+ throw new Error(`Voice trace timeline failed: HTTP ${response.status}`);
4438
+ }
4439
+ return await response.json();
4440
+ };
4441
+ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) => {
4442
+ const listeners = new Set;
4443
+ let closed = false;
4444
+ let timer;
4445
+ let snapshot = {
4446
+ error: null,
4447
+ isLoading: false,
4448
+ report: null
4449
+ };
4450
+ const emit = () => {
4451
+ for (const listener of listeners) {
4452
+ listener();
4453
+ }
4454
+ };
4455
+ const refresh = async () => {
4456
+ if (closed) {
4457
+ return snapshot.report;
4458
+ }
4459
+ snapshot = {
4460
+ ...snapshot,
4461
+ error: null,
4462
+ isLoading: true
4463
+ };
4464
+ emit();
4465
+ try {
4466
+ const report = await fetchVoiceTraceTimeline(path, options);
4467
+ snapshot = {
4468
+ error: null,
4469
+ isLoading: false,
4470
+ report,
4471
+ updatedAt: Date.now()
4472
+ };
4473
+ emit();
4474
+ return report;
4475
+ } catch (error) {
4476
+ snapshot = {
4477
+ ...snapshot,
4478
+ error: error instanceof Error ? error.message : String(error),
4479
+ isLoading: false
4480
+ };
4481
+ emit();
4482
+ throw error;
4483
+ }
4484
+ };
4485
+ const close = () => {
4486
+ closed = true;
4487
+ if (timer) {
4488
+ clearInterval(timer);
4489
+ timer = undefined;
4490
+ }
4491
+ listeners.clear();
4492
+ };
4493
+ if (options.intervalMs && options.intervalMs > 0) {
4494
+ timer = setInterval(() => {
4495
+ refresh().catch(() => {});
4496
+ }, options.intervalMs);
4497
+ }
4498
+ return {
4499
+ close,
4500
+ getServerSnapshot: () => snapshot,
4501
+ getSnapshot: () => snapshot,
4502
+ refresh,
4503
+ subscribe: (listener) => {
4504
+ listeners.add(listener);
4505
+ return () => {
4506
+ listeners.delete(listener);
4507
+ };
4508
+ }
4509
+ };
4510
+ };
4511
+
4512
+ // src/angular/voice-trace-timeline.service.ts
4513
+ var _dec = [
4514
+ Injectable24({ providedIn: "root" })
4515
+ ];
4516
+ var _init = __decoratorStart(undefined);
4517
+
4518
+ class VoiceTraceTimelineService {
4519
+ connect(path = "/api/voice-traces", options = {}) {
4520
+ const store = createVoiceTraceTimelineStore(path, options);
4521
+ const errorSignal = signal24(null);
4522
+ const isLoadingSignal = signal24(false);
4523
+ const reportSignal = signal24(null);
4524
+ const updatedAtSignal = signal24(undefined);
4525
+ const sync = () => {
4526
+ const snapshot = store.getSnapshot();
4527
+ errorSignal.set(snapshot.error);
4528
+ isLoadingSignal.set(snapshot.isLoading);
4529
+ reportSignal.set(snapshot.report);
4530
+ updatedAtSignal.set(snapshot.updatedAt);
4531
+ };
4532
+ const unsubscribe = store.subscribe(sync);
4533
+ sync();
4534
+ store.refresh().catch(() => {});
4535
+ return {
4536
+ close: () => {
4537
+ unsubscribe();
4538
+ store.close();
4539
+ },
4540
+ error: computed23(() => errorSignal()),
4541
+ isLoading: computed23(() => isLoadingSignal()),
4542
+ refresh: store.refresh,
4543
+ report: computed23(() => reportSignal()),
4544
+ updatedAt: computed23(() => updatedAtSignal())
4545
+ };
4546
+ }
4547
+ }
4548
+ VoiceTraceTimelineService = __decorateElement(_init, 0, "VoiceTraceTimelineService", _dec, VoiceTraceTimelineService);
4549
+ __runInitializers(_init, 1, VoiceTraceTimelineService);
4550
+ __decoratorMetadata(_init, VoiceTraceTimelineService);
4551
+ let _VoiceTraceTimelineService = VoiceTraceTimelineService;
4552
+ // src/angular/voice-agent-squad-status.service.ts
4553
+ import { computed as computed24, Injectable as Injectable25, signal as signal25 } from "@angular/core";
4554
+
4555
+ // src/client/agentSquadStatus.ts
4556
+ var getString = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
4557
+ var getPayloadString = (event, key) => getString(event.payload?.[key]);
4558
+ var eventStatus = (event) => {
4559
+ const status = getPayloadString(event, "status");
4560
+ if (status === "blocked")
4561
+ return "blocked";
4562
+ if (status === "unknown-target")
4563
+ return "unknown-target";
4564
+ if (status === "allowed")
4565
+ return "handoff";
4566
+ return event.type === "agent.result" ? "active" : "handoff";
4567
+ };
4568
+ var deriveSessionSpecialist = (session) => {
4569
+ const events = [...session.events].sort((left, right) => left.at - right.at);
4570
+ const agentEvents = events.filter((event) => event.type === "agent.handoff" || event.type === "agent.context" || event.type === "agent.result" || event.type === "agent.model");
4571
+ const latest = agentEvents.at(-1);
4572
+ if (!latest) {
4573
+ return {
4574
+ lastEventAt: session.lastEventAt,
4575
+ sessionId: session.sessionId,
4576
+ status: "idle"
4577
+ };
4578
+ }
4579
+ const handoffEvents = events.filter((event) => event.type === "agent.handoff");
4580
+ const lastHandoff = handoffEvents.at(-1);
4581
+ const latestAgentId = getPayloadString(latest, "agentId");
4582
+ const handoffStatus = lastHandoff ? eventStatus(lastHandoff) : undefined;
4583
+ const currentTarget = handoffStatus === "blocked" || handoffStatus === "unknown-target" ? getPayloadString(lastHandoff, "fromAgentId") ?? latestAgentId : getPayloadString(lastHandoff ?? latest, "targetAgentId") ?? latestAgentId;
4584
+ return {
4585
+ fromAgentId: getPayloadString(lastHandoff ?? latest, "fromAgentId"),
4586
+ lastEventAt: latest.at,
4587
+ reason: getPayloadString(lastHandoff ?? latest, "reason") ?? getPayloadString(latest, "handoffTarget"),
4588
+ sessionId: session.sessionId,
4589
+ status: lastHandoff ? eventStatus(lastHandoff) : "active",
4590
+ summary: getPayloadString(lastHandoff ?? latest, "summary"),
4591
+ targetAgentId: currentTarget,
4592
+ turnId: latest.turnId
4593
+ };
4594
+ };
4595
+ var buildVoiceAgentSquadStatusReport = (timeline, options = {}) => {
4596
+ const sessions = (timeline?.sessions ?? []).filter((session) => !options.sessionId || session.sessionId === options.sessionId).map(deriveSessionSpecialist).sort((left, right) => (right.lastEventAt ?? 0) - (left.lastEventAt ?? 0));
4597
+ const active = sessions.filter((session) => session.status !== "idle");
4598
+ return {
4599
+ active,
4600
+ checkedAt: timeline?.checkedAt,
4601
+ current: active[0] ?? sessions[0],
4602
+ sessionCount: sessions.length,
4603
+ sessions
4604
+ };
4605
+ };
4606
+ var createVoiceAgentSquadStatusStore = (path = "/api/voice-traces", options = {}) => {
4607
+ const timelineStore = createVoiceTraceTimelineStore(path, options);
4608
+ const getReport = () => buildVoiceAgentSquadStatusReport(timelineStore.getSnapshot().report, {
4609
+ sessionId: options.sessionId
4610
+ });
4611
+ const getSnapshot = () => {
4612
+ const snapshot = timelineStore.getSnapshot();
4613
+ return {
4614
+ error: snapshot.error,
4615
+ isLoading: snapshot.isLoading,
4616
+ report: getReport(),
4617
+ updatedAt: snapshot.updatedAt
4618
+ };
4619
+ };
4620
+ return {
4621
+ close: timelineStore.close,
4622
+ getServerSnapshot: getSnapshot,
4623
+ getSnapshot,
4624
+ refresh: timelineStore.refresh,
4625
+ subscribe: timelineStore.subscribe
4626
+ };
4627
+ };
4628
+
4629
+ // src/angular/voice-agent-squad-status.service.ts
4630
+ var _dec = [
4631
+ Injectable25({ providedIn: "root" })
4632
+ ];
4633
+ var _init = __decoratorStart(undefined);
4634
+
4635
+ class VoiceAgentSquadStatusService {
4636
+ connect(path = "/api/voice-traces", options = {}) {
4637
+ const store = createVoiceAgentSquadStatusStore(path, options);
4638
+ const errorSignal = signal25(null);
4639
+ const isLoadingSignal = signal25(false);
4640
+ const reportSignal = signal25(undefined);
4641
+ const updatedAtSignal = signal25(undefined);
4642
+ const sync = () => {
4643
+ const snapshot = store.getSnapshot();
4644
+ errorSignal.set(snapshot.error);
4645
+ isLoadingSignal.set(snapshot.isLoading);
4646
+ reportSignal.set(snapshot.report);
4647
+ updatedAtSignal.set(snapshot.updatedAt);
4648
+ };
4649
+ const unsubscribe = store.subscribe(sync);
4650
+ sync();
4651
+ store.refresh().catch(() => {});
4652
+ return {
4653
+ close: () => {
4654
+ unsubscribe();
4655
+ store.close();
4656
+ },
4657
+ current: computed24(() => reportSignal()?.current),
4658
+ error: computed24(() => errorSignal()),
4659
+ isLoading: computed24(() => isLoadingSignal()),
4660
+ refresh: store.refresh,
4661
+ report: computed24(() => reportSignal()),
4662
+ updatedAt: computed24(() => updatedAtSignal())
4663
+ };
4664
+ }
4665
+ }
4666
+ VoiceAgentSquadStatusService = __decorateElement(_init, 0, "VoiceAgentSquadStatusService", _dec, VoiceAgentSquadStatusService);
4667
+ __runInitializers(_init, 1, VoiceAgentSquadStatusService);
4668
+ __decoratorMetadata(_init, VoiceAgentSquadStatusService);
4669
+ let _VoiceAgentSquadStatusService = VoiceAgentSquadStatusService;
4670
+ // src/angular/voice-turn-latency.service.ts
4671
+ import { computed as computed25, Injectable as Injectable26, signal as signal26 } from "@angular/core";
4672
+
4673
+ // src/client/turnLatency.ts
4674
+ var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
4675
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4676
+ const response = await fetchImpl(path);
4677
+ if (!response.ok) {
4678
+ throw new Error(`Voice turn latency failed: HTTP ${response.status}`);
4679
+ }
4680
+ return await response.json();
4681
+ };
4682
+ var runVoiceTurnLatencyProof = async (path, options = {}) => {
4683
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4684
+ const response = await fetchImpl(path, { method: "POST" });
4685
+ if (!response.ok) {
4686
+ throw new Error(`Voice turn latency proof failed: HTTP ${response.status}`);
4687
+ }
4688
+ return response.json();
4689
+ };
4690
+ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) => {
4691
+ const listeners = new Set;
4692
+ let closed = false;
4693
+ let timer;
4694
+ let snapshot = {
4695
+ error: null,
4696
+ isLoading: false
4697
+ };
4698
+ const emit = () => {
4699
+ for (const listener of listeners) {
4700
+ listener();
4701
+ }
4702
+ };
4703
+ const refresh = async () => {
4704
+ if (closed) {
4705
+ return snapshot.report;
4706
+ }
4707
+ snapshot = { ...snapshot, error: null, isLoading: true };
4708
+ emit();
4709
+ try {
4710
+ const report = await fetchVoiceTurnLatency(path, options);
4711
+ snapshot = {
4712
+ error: null,
4713
+ isLoading: false,
4714
+ report,
4715
+ updatedAt: Date.now()
4716
+ };
4717
+ emit();
4718
+ return report;
4719
+ } catch (error) {
4720
+ snapshot = {
4721
+ ...snapshot,
4722
+ error: error instanceof Error ? error.message : String(error),
4723
+ isLoading: false
4724
+ };
4725
+ emit();
4726
+ throw error;
4727
+ }
4728
+ };
4729
+ const runProof = async () => {
4730
+ if (!options.proofPath) {
4731
+ throw new Error("Voice turn latency proof path is not configured.");
4732
+ }
4733
+ snapshot = { ...snapshot, error: null, isLoading: true };
4734
+ emit();
4735
+ try {
4736
+ await runVoiceTurnLatencyProof(options.proofPath, options);
4737
+ return await refresh();
4738
+ } catch (error) {
4739
+ snapshot = {
4740
+ ...snapshot,
4741
+ error: error instanceof Error ? error.message : String(error),
4742
+ isLoading: false
4743
+ };
4744
+ emit();
4745
+ throw error;
4746
+ }
4747
+ };
4748
+ const close = () => {
4749
+ closed = true;
4750
+ if (timer) {
4751
+ clearInterval(timer);
4752
+ timer = undefined;
4753
+ }
4754
+ listeners.clear();
4755
+ };
4756
+ if (options.intervalMs && options.intervalMs > 0) {
4757
+ timer = setInterval(() => {
4758
+ refresh().catch(() => {});
4759
+ }, options.intervalMs);
4760
+ }
4761
+ return {
4762
+ close,
4763
+ getServerSnapshot: () => snapshot,
4764
+ getSnapshot: () => snapshot,
4765
+ refresh,
4766
+ runProof,
4767
+ subscribe: (listener) => {
4768
+ listeners.add(listener);
4769
+ return () => {
4770
+ listeners.delete(listener);
4771
+ };
4772
+ }
4773
+ };
4774
+ };
4775
+
4776
+ // src/angular/voice-turn-latency.service.ts
4777
+ var _dec = [
4778
+ Injectable26({ providedIn: "root" })
4779
+ ];
4780
+ var _init = __decoratorStart(undefined);
4781
+
4782
+ class VoiceTurnLatencyService {
4783
+ connect(path = "/api/turn-latency", options = {}) {
4784
+ const store = createVoiceTurnLatencyStore(path, options);
4785
+ const errorSignal = signal26(null);
4786
+ const isLoadingSignal = signal26(false);
4787
+ const reportSignal = signal26(undefined);
4788
+ const updatedAtSignal = signal26(undefined);
4789
+ const sync = () => {
4790
+ const snapshot = store.getSnapshot();
4791
+ errorSignal.set(snapshot.error);
4792
+ isLoadingSignal.set(snapshot.isLoading);
4793
+ reportSignal.set(snapshot.report);
4794
+ updatedAtSignal.set(snapshot.updatedAt);
4795
+ };
4796
+ const unsubscribe = store.subscribe(sync);
4797
+ sync();
4798
+ store.refresh().catch(() => {});
4799
+ return {
4800
+ close: () => {
4801
+ unsubscribe();
4802
+ store.close();
4803
+ },
4804
+ error: computed25(() => errorSignal()),
4805
+ isLoading: computed25(() => isLoadingSignal()),
4806
+ refresh: store.refresh,
4807
+ report: computed25(() => reportSignal()),
4808
+ runProof: store.runProof,
4809
+ updatedAt: computed25(() => updatedAtSignal())
4810
+ };
4811
+ }
4812
+ }
4813
+ VoiceTurnLatencyService = __decorateElement(_init, 0, "VoiceTurnLatencyService", _dec, VoiceTurnLatencyService);
4814
+ __runInitializers(_init, 1, VoiceTurnLatencyService);
4815
+ __decoratorMetadata(_init, VoiceTurnLatencyService);
4816
+ let _VoiceTurnLatencyService = VoiceTurnLatencyService;
4817
+ // src/angular/voice-turn-quality.service.ts
4818
+ import { computed as computed26, Injectable as Injectable27, signal as signal27 } from "@angular/core";
4819
+
4820
+ // src/client/turnQuality.ts
4821
+ var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
4822
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4823
+ const response = await fetchImpl(path);
4824
+ if (!response.ok) {
4825
+ throw new Error(`Voice turn quality failed: HTTP ${response.status}`);
4826
+ }
4827
+ return await response.json();
4828
+ };
4829
+ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) => {
4830
+ const listeners = new Set;
4831
+ let closed = false;
4832
+ let timer;
4833
+ let snapshot = {
4834
+ error: null,
4835
+ isLoading: false
4836
+ };
4837
+ const emit = () => {
4838
+ for (const listener of listeners) {
4839
+ listener();
4840
+ }
4841
+ };
4842
+ const refresh = async () => {
4843
+ if (closed) {
4844
+ return snapshot.report;
4845
+ }
4846
+ snapshot = {
1492
4847
  ...snapshot,
1493
4848
  error: null,
1494
4849
  isLoading: true
1495
4850
  };
1496
4851
  emit();
1497
4852
  try {
1498
- const providers = await fetchVoiceProviderStatus(path, options);
4853
+ const report = await fetchVoiceTurnQuality(path, options);
1499
4854
  snapshot = {
1500
4855
  error: null,
1501
4856
  isLoading: false,
1502
- providers,
4857
+ report,
1503
4858
  updatedAt: Date.now()
1504
4859
  };
1505
4860
  emit();
1506
- return providers;
4861
+ return report;
1507
4862
  } catch (error) {
1508
4863
  snapshot = {
1509
4864
  ...snapshot,
@@ -1541,24 +4896,24 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
1541
4896
  };
1542
4897
  };
1543
4898
 
1544
- // src/angular/voice-provider-status.service.ts
4899
+ // src/angular/voice-turn-quality.service.ts
1545
4900
  var _dec = [
1546
- Injectable4({ providedIn: "root" })
4901
+ Injectable27({ providedIn: "root" })
1547
4902
  ];
1548
4903
  var _init = __decoratorStart(undefined);
1549
4904
 
1550
- class VoiceProviderStatusService {
1551
- connect(path = "/api/provider-status", options = {}) {
1552
- const store = createVoiceProviderStatusStore(path, options);
1553
- const errorSignal = signal4(null);
1554
- const isLoadingSignal = signal4(false);
1555
- const providersSignal = signal4([]);
1556
- const updatedAtSignal = signal4(undefined);
4905
+ class VoiceTurnQualityService {
4906
+ connect(path = "/api/turn-quality", options = {}) {
4907
+ const store = createVoiceTurnQualityStore(path, options);
4908
+ const errorSignal = signal27(null);
4909
+ const isLoadingSignal = signal27(false);
4910
+ const reportSignal = signal27(undefined);
4911
+ const updatedAtSignal = signal27(undefined);
1557
4912
  const sync = () => {
1558
4913
  const snapshot = store.getSnapshot();
1559
4914
  errorSignal.set(snapshot.error);
1560
4915
  isLoadingSignal.set(snapshot.isLoading);
1561
- providersSignal.set([...snapshot.providers]);
4916
+ reportSignal.set(snapshot.report);
1562
4917
  updatedAtSignal.set(snapshot.updatedAt);
1563
4918
  };
1564
4919
  const unsubscribe = store.subscribe(sync);
@@ -1569,20 +4924,20 @@ class VoiceProviderStatusService {
1569
4924
  unsubscribe();
1570
4925
  store.close();
1571
4926
  },
1572
- error: computed4(() => errorSignal()),
1573
- isLoading: computed4(() => isLoadingSignal()),
1574
- providers: computed4(() => providersSignal()),
4927
+ error: computed26(() => errorSignal()),
4928
+ isLoading: computed26(() => isLoadingSignal()),
1575
4929
  refresh: store.refresh,
1576
- updatedAt: computed4(() => updatedAtSignal())
4930
+ report: computed26(() => reportSignal()),
4931
+ updatedAt: computed26(() => updatedAtSignal())
1577
4932
  };
1578
4933
  }
1579
4934
  }
1580
- VoiceProviderStatusService = __decorateElement(_init, 0, "VoiceProviderStatusService", _dec, VoiceProviderStatusService);
1581
- __runInitializers(_init, 1, VoiceProviderStatusService);
1582
- __decoratorMetadata(_init, VoiceProviderStatusService);
1583
- let _VoiceProviderStatusService = VoiceProviderStatusService;
4935
+ VoiceTurnQualityService = __decorateElement(_init, 0, "VoiceTurnQualityService", _dec, VoiceTurnQualityService);
4936
+ __runInitializers(_init, 1, VoiceTurnQualityService);
4937
+ __decoratorMetadata(_init, VoiceTurnQualityService);
4938
+ let _VoiceTurnQualityService = VoiceTurnQualityService;
1584
4939
  // src/angular/voice-workflow-status.service.ts
1585
- import { computed as computed5, Injectable as Injectable5, signal as signal5 } from "@angular/core";
4940
+ import { computed as computed27, Injectable as Injectable28, signal as signal28 } from "@angular/core";
1586
4941
 
1587
4942
  // src/client/workflowStatus.ts
1588
4943
  var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
@@ -1665,17 +5020,17 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
1665
5020
 
1666
5021
  // src/angular/voice-workflow-status.service.ts
1667
5022
  var _dec = [
1668
- Injectable5({ providedIn: "root" })
5023
+ Injectable28({ providedIn: "root" })
1669
5024
  ];
1670
5025
  var _init = __decoratorStart(undefined);
1671
5026
 
1672
5027
  class VoiceWorkflowStatusService {
1673
5028
  connect(path = "/evals/scenarios/json", options = {}) {
1674
5029
  const store = createVoiceWorkflowStatusStore(path, options);
1675
- const errorSignal = signal5(null);
1676
- const isLoadingSignal = signal5(false);
1677
- const reportSignal = signal5(undefined);
1678
- const updatedAtSignal = signal5(undefined);
5030
+ const errorSignal = signal28(null);
5031
+ const isLoadingSignal = signal28(false);
5032
+ const reportSignal = signal28(undefined);
5033
+ const updatedAtSignal = signal28(undefined);
1679
5034
  const sync = () => {
1680
5035
  const snapshot = store.getSnapshot();
1681
5036
  errorSignal.set(snapshot.error);
@@ -1693,11 +5048,11 @@ class VoiceWorkflowStatusService {
1693
5048
  unsubscribe();
1694
5049
  store.close();
1695
5050
  },
1696
- error: computed5(() => errorSignal()),
1697
- isLoading: computed5(() => isLoadingSignal()),
5051
+ error: computed27(() => errorSignal()),
5052
+ isLoading: computed27(() => isLoadingSignal()),
1698
5053
  refresh: store.refresh,
1699
- report: computed5(() => reportSignal()),
1700
- updatedAt: computed5(() => updatedAtSignal())
5054
+ report: computed27(() => reportSignal()),
5055
+ updatedAt: computed27(() => updatedAtSignal())
1701
5056
  };
1702
5057
  }
1703
5058
  }
@@ -1707,8 +5062,31 @@ __decoratorMetadata(_init, VoiceWorkflowStatusService);
1707
5062
  let _VoiceWorkflowStatusService = VoiceWorkflowStatusService;
1708
5063
  export {
1709
5064
  VoiceWorkflowStatusService,
5065
+ VoiceWidgetService,
5066
+ VoiceTurnQualityService,
5067
+ VoiceTurnLatencyService,
5068
+ VoiceTraceTimelineService,
1710
5069
  VoiceStreamService,
5070
+ VoiceSessionSnapshotService,
5071
+ VoiceSessionObservabilityService,
5072
+ VoiceRoutingStatusService,
5073
+ VoiceReplayTimelineService,
5074
+ VoiceReconnectProfileEvidenceService,
5075
+ VoiceReadinessFailuresService,
1711
5076
  VoiceProviderStatusService,
5077
+ VoiceProviderContractsService,
5078
+ VoiceProviderCapabilitiesService,
5079
+ VoiceProofTrendsService,
5080
+ VoiceProfileComparisonService,
5081
+ VoicePlatformCoverageService,
5082
+ VoiceOpsStatusService,
5083
+ VoiceOpsActionCenterService,
5084
+ VoiceLiveOpsService,
5085
+ VoiceLiveCallViewerService,
5086
+ VoiceDeliveryRuntimeService,
5087
+ VoiceCostDashboardService,
1712
5088
  VoiceControllerService,
1713
- VoiceAppKitStatusService
5089
+ VoiceCampaignDialerProofService,
5090
+ VoiceCallDebuggerService,
5091
+ VoiceAgentSquadStatusService
1714
5092
  };