@absolutejs/voice 0.0.22-beta.52 → 0.0.22-beta.520

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